mirror of
https://github.com/odriverobotics/ODrive.git
synced 2026-09-28 16:13:37 +08:00
Merge branch 'master' into devel
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
name: 'Add version to release channel'
|
||||
description: |
|
||||
Appends the specified version to the end of the specified release channel if
|
||||
it wasn't already part of that channel.
|
||||
|
||||
inputs:
|
||||
release_type:
|
||||
description: 'Release type (firmware, gui, docs, internal-docs).'
|
||||
required: true
|
||||
channel:
|
||||
description: 'The channel on which to register this version'
|
||||
required: true
|
||||
version:
|
||||
description: 'The version name (commit hash or semantic version name)'
|
||||
required: true
|
||||
odrive_api_key:
|
||||
description: 'Key to our release index server'
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Register on release server
|
||||
shell: python
|
||||
run: |
|
||||
import asyncio
|
||||
import sys
|
||||
import aiohttp
|
||||
|
||||
sys.path.insert(0, '${{ github.workspace }}/.github/actions/upload-release')
|
||||
from odrive.api_client import ApiClient
|
||||
from private_release_api import PrivateReleaseApi
|
||||
|
||||
async def main():
|
||||
async with aiohttp.ClientSession() as session:
|
||||
api_client = ApiClient(session, key='${{ inputs.odrive_api_key }}')
|
||||
release_api = PrivateReleaseApi(api_client)
|
||||
await release_api.append_to_channel('${{ inputs.release_type }}', "${{ inputs.channel }}", "${{ inputs.version }}")
|
||||
await release_api.refresh_routes('${{ inputs.release_type }}')
|
||||
|
||||
asyncio.run(main())
|
||||
@@ -1,60 +0,0 @@
|
||||
name: 'Release Firmware'
|
||||
description: 'Compiles the firmware for the specified board version and uploads it to a GitHub release url'
|
||||
inputs:
|
||||
board_version:
|
||||
required: true
|
||||
url:
|
||||
required: true
|
||||
token:
|
||||
required: true
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Compile for ODrive ${{ inputs.board_version }}
|
||||
shell: bash
|
||||
run: |
|
||||
# for debugging
|
||||
arm-none-eabi-gcc --version
|
||||
python3 --version
|
||||
|
||||
cd ${{ github.workspace }}/Firmware
|
||||
|
||||
mkdir -p autogen
|
||||
python ../tools/odrive/version.py --output autogen/version.c
|
||||
|
||||
echo "CONFIG_STRICT=true" > tup.config
|
||||
echo "CONFIG_BOARD_VERSION=${{ inputs.board_version }}" >> tup.config
|
||||
tup init
|
||||
tup generate ./tup_build.sh
|
||||
bash -xe ./tup_build.sh
|
||||
|
||||
- name: Upload ELF file
|
||||
shell: bash
|
||||
run: |
|
||||
urls=( ${{ inputs.url }} )
|
||||
URL="${urls[0]}=ODriveFirmware_${{ inputs.board_version }}.elf"
|
||||
echo "uploading to $URL"
|
||||
|
||||
curl --silent --show-error --fail \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
-H "Authorization: token ${{ inputs.token }}" \
|
||||
--data-binary @"Firmware/build/ODriveFirmware.elf" \
|
||||
"$URL"
|
||||
|
||||
- name: Upload HEX file
|
||||
shell: bash
|
||||
run: |
|
||||
urls=( ${{ inputs.url }} )
|
||||
URL="${urls[0]}=ODriveFirmware_${{ inputs.board_version }}.hex"
|
||||
echo "uploading to $URL"
|
||||
|
||||
curl --silent --show-error --fail \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
-H "Authorization: token ${{ inputs.token }}" \
|
||||
--data-binary @"Firmware/build/ODriveFirmware.hex" \
|
||||
"$URL"
|
||||
|
||||
# This is required to make the action repeatable
|
||||
- name: Clean up
|
||||
shell: bash
|
||||
run: git clean -dffx
|
||||
@@ -2,11 +2,14 @@ name: 'Upload (Pre)release'
|
||||
description: |
|
||||
Pushes the specified local directory to our release file server and registers
|
||||
the new content on our release index server.
|
||||
Whether the release will be public depends on the channel and its settings.
|
||||
The version will not yet be associated with a channel.
|
||||
|
||||
inputs:
|
||||
release_type:
|
||||
description: 'Release type (firmware, gui, docs, internal-docs).' # TODO: Currently only firmware is supported.
|
||||
description: 'Release type (firmware, gui, docs, internal-docs).' # TODO: Currently only firmware and docs is supported.
|
||||
required: true
|
||||
version:
|
||||
description: 'The version name (commit hash or semantic version name)'
|
||||
required: true
|
||||
src_dir:
|
||||
description: 'The source directory on the local system.'
|
||||
@@ -27,7 +30,7 @@ inputs:
|
||||
description: 'Firmware app name (default, bootloader) (for firmware releases only).'
|
||||
required: false
|
||||
variant:
|
||||
description: 'Variant (for docs releases only).'
|
||||
description: 'Variant (public or internal).'
|
||||
required: false
|
||||
|
||||
runs:
|
||||
@@ -101,10 +104,9 @@ runs:
|
||||
from private_release_api import PrivateReleaseApi
|
||||
from odrive.crypto import safe_b64decode
|
||||
|
||||
channel="0.5.4"
|
||||
version="${{ inputs.version }}"
|
||||
|
||||
print("Channel: ", channel)
|
||||
print("Commit hash: ", '${{ github.sha }}')
|
||||
print("Version: ", version)
|
||||
print("Content key: ", '${{ steps.load-content-key.outputs.content-key }}')
|
||||
|
||||
async def main():
|
||||
@@ -121,8 +123,12 @@ runs:
|
||||
qualifiers['variant'] = '${{ inputs.variant }}'
|
||||
|
||||
content_key = safe_b64decode('${{ steps.load-content-key.outputs.content-key }}')
|
||||
await release_api.register_content('${{ inputs.release_type }}', '${{ github.sha }}', content_key, **qualifiers)
|
||||
await release_api.register_commit('${{ inputs.release_type }}', channel, '${{ github.sha }}')
|
||||
await release_api.refresh_routes('${{ inputs.release_type }}')
|
||||
|
||||
# Content can only be registered once, afterwards the indicated_commit cannot be changed
|
||||
if "${{ steps.load-content-key.outputs.needs-upload}}" == 'true':
|
||||
await release_api.register_content('${{ inputs.release_type }}', content_key, '${{ github.sha }}')
|
||||
|
||||
# Can be called multiple times with same or different parameters. No effect if called twice with the same parameters.
|
||||
await release_api.register_version('${{ inputs.release_type }}', version, content_key, **qualifiers)
|
||||
|
||||
asyncio.run(main())
|
||||
|
||||
@@ -48,19 +48,25 @@ class PrivateReleaseApi():
|
||||
})
|
||||
return outputs
|
||||
|
||||
async def register_content(self, release_type: str, commit_hash: str, content_key: bytes, **qualifiers):
|
||||
args = {
|
||||
'commit_hash': commit_hash,
|
||||
async def register_content(self, release_type: str, content_key: bytes, indicated_commit: str):
|
||||
outputs = await self._api_client.call('PUT', PrivateReleaseApi.BASE_URL + '/' + release_type + '/content', inputs={
|
||||
'content_key': b64encode(content_key),
|
||||
**qualifiers
|
||||
}
|
||||
outputs = await self._api_client.call('PUT', PrivateReleaseApi.BASE_URL + '/' + release_type + '/content', inputs=args)
|
||||
'indicated_commit': indicated_commit,
|
||||
})
|
||||
return outputs['created']
|
||||
|
||||
async def register_commit(self, release_type: str, channel: str, commit_hash: str):
|
||||
outputs = await self._api_client.call('PUT', PrivateReleaseApi.BASE_URL + '/' + release_type + '/commit', inputs={
|
||||
'commit_hash': commit_hash,
|
||||
'channel': channel
|
||||
async def register_version(self, release_type: str, version: str, content_key: bytes, **qualifiers):
|
||||
outputs = await self._api_client.call('PUT', PrivateReleaseApi.BASE_URL + '/' + release_type + '/version', inputs={
|
||||
'version': version,
|
||||
'content_key': b64encode(content_key),
|
||||
**qualifiers
|
||||
})
|
||||
return outputs['created']
|
||||
|
||||
async def append_to_channel(self, release_type: str, channel: str, version: str):
|
||||
outputs = await self._api_client.call('PUT', PrivateReleaseApi.BASE_URL + '/' + release_type + '/channel', inputs={
|
||||
'channel': channel,
|
||||
'version': version,
|
||||
})
|
||||
return outputs['published']
|
||||
|
||||
|
||||
@@ -3,9 +3,8 @@ name: Tests
|
||||
on:
|
||||
pull_request:
|
||||
branches: [master, devel]
|
||||
tags: ['fw-v*']
|
||||
push:
|
||||
branches: [master, devel, 'fw-v*']
|
||||
branches: [master, devel]
|
||||
tags: ['fw-v*']
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -2,7 +2,7 @@ name: Build and publish HTML documentation website
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
branches: [ 'docs-v**' ]
|
||||
paths: ['docs/**', '.github/**']
|
||||
|
||||
jobs:
|
||||
@@ -10,6 +10,18 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Get release name and channel
|
||||
id: release-info
|
||||
shell: python
|
||||
run: |
|
||||
channel = "master"
|
||||
version = "${{ github.ref }}"
|
||||
assert version.startswith("refs/heads/docs-v0.5.")
|
||||
version = version[len("refs/heads/docs-v"):]
|
||||
|
||||
print("::set-output name=channel::" + channel)
|
||||
print("::set-output name=version::" + version)
|
||||
|
||||
- name: Cache pip
|
||||
uses: actions/cache@v2
|
||||
@@ -32,8 +44,17 @@ jobs:
|
||||
uses: ./.github/actions/upload-release
|
||||
with:
|
||||
release_type: docs
|
||||
version: ${{ steps.release-info.outputs.version }}
|
||||
src_dir: docs/_build/html
|
||||
do_access_key: ${{ secrets.DIGITALOCEAN_ACCESS_KEY }}
|
||||
do_secret_key: ${{ secrets.DIGITALOCEAN_SECRET_KEY }}
|
||||
odrive_api_key: ${{ secrets.ODRIVE_API_KEY }}
|
||||
variant: public
|
||||
|
||||
- name: Add version to release channel
|
||||
uses: ./.github/actions/add-version-to-channel
|
||||
with:
|
||||
release_type: docs
|
||||
channel: ${{ steps.release-info.outputs.channel }}
|
||||
version: ${{ steps.release-info.outputs.version }}
|
||||
odrive_api_key: ${{ secrets.ODRIVE_API_KEY }}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
name: pip install odrive (nightly)
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 2 * * *' # run at 2 AM UTC
|
||||
|
||||
jobs:
|
||||
nightly:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
#pip: [pip2, pip3]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Install odrivetool
|
||||
shell: bash
|
||||
run: |
|
||||
pip3 list | grep setuptools || echo "setuptools not installed" # show version
|
||||
pip3 install setuptools # TODO: this should be a dependency of odrive
|
||||
pip3 install odrive
|
||||
env:
|
||||
# TODO: this is a workaround for https://github.com/pypa/setuptools/issues/2353 and we
|
||||
# can remove it as soon as python3-setuptools on GitHub's ubuntu-latest
|
||||
# moves to version 50.1+.
|
||||
SETUPTOOLS_USE_DISTUTILS: stdlib
|
||||
|
||||
# This one currently fails because Github Actions runs pip as non-root
|
||||
#- name: Check if udev rules were set up properly
|
||||
# if: matrix.os == 'ubuntu-latest'
|
||||
# run: test -f /etc/udev/rules.d/91-odrive.rules
|
||||
|
||||
# This step is mentioned in the user guide
|
||||
- name: Add ~/.local/bin to path
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: echo "~/.local/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Launch odrivetool
|
||||
# This returns a non-zero exit code if the odrivetool throws an exception
|
||||
run: echo 'quit()' | odrivetool shell
|
||||
@@ -1,109 +0,0 @@
|
||||
name: Create Release Draft
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: ['fw-v*']
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Parse Release Specs
|
||||
id: release_specs
|
||||
run: |
|
||||
echo "github.ref = ${{ github.ref }}"
|
||||
|
||||
function get_version() { sed -E -n "s|.*([0-9]+\.[0-9]+\.[0-9]+).*|\1|p"; }
|
||||
|
||||
#LAST_VERSION="$(curl -s https://api.github.com/repos/madcowswe/ODrive/releases/latest | jq '.name' | get_version)"
|
||||
#echo "previous version = $LAST_VERSION"
|
||||
|
||||
NEW_VERSION="$(echo "${{ github.ref }}" | get_version)"
|
||||
echo "version = $NEW_VERSION"
|
||||
|
||||
ALL_TITLES="$(grep -E -n "^## .*[0-9]+\.[0-9]+\.[0-9]+" CHANGELOG.md)"
|
||||
|
||||
echo "I found the following version headers in the changelog:"
|
||||
echo "$ALL_TITLES"
|
||||
|
||||
START_LINE="$(head -1 <<< "$ALL_TITLES" | cut -f 1 -d ':')"
|
||||
END_LINE="$(head -2 <<< "$ALL_TITLES" | tail -1 | cut -f 1 -d ':')"
|
||||
|
||||
BODY="$(head -$(("$END_LINE" - 1)) CHANGELOG.md | tail +$(("$START_LINE" + 1)))"
|
||||
|
||||
IS_PRERELEASE="$(grep -F "$NEW_VERSION"-rc <<< "${{ github.ref }}" >/dev/null && echo true || echo false)"
|
||||
echo "Is prerelease: $IS_PRERELEASE"
|
||||
|
||||
# The git tag is later read when packaging the python tools and
|
||||
# compiling the firmware. We set it explicitly here in case the
|
||||
# workflow was triggered by something other than a git tag.
|
||||
git tag "${{ github.ref }}"
|
||||
|
||||
# Escape BODY string to set it as GitHub Actions output
|
||||
BODY="${BODY//'%'/'%25'}"
|
||||
BODY="${BODY//$'\n'/'%0A'}"
|
||||
BODY="${BODY//$'\r'/'%0D'}"
|
||||
|
||||
echo "::set-output name=body::$BODY"
|
||||
echo "::set-output name=version::$NEW_VERSION"
|
||||
echo "::set-output name=is_prerelease::$IS_PRERELEASE"
|
||||
|
||||
- name: Create Release Draft
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: Firmware version ${{ steps.release_specs.outputs.version }}
|
||||
body: ${{ steps.release_specs.outputs.body }}
|
||||
draft: true # Only do a draft so we have a change to manually review
|
||||
# the release before it goes live.
|
||||
prerelease: ${{ steps.release_specs.outputs.is_prerelease }}
|
||||
|
||||
- name: Install Prerequisites
|
||||
run: |
|
||||
sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa
|
||||
sudo add-apt-repository ppa:jonathonf/tup
|
||||
sudo apt-get update
|
||||
sudo apt-get install gcc-arm-embedded
|
||||
sudo apt-get install tup
|
||||
sudo apt install python3 python3-yaml python3-jinja2 python3-jsonschema
|
||||
|
||||
- name: Build Python Tools
|
||||
run: |
|
||||
cd ${{ github.workspace }}/tools
|
||||
python setup.py sdist
|
||||
|
||||
cd dist
|
||||
PKG_NAME="$(ls)"
|
||||
if [ "$(wc -l <<< "$PKG_NAME")" != 1 ]; then
|
||||
echo "Expected exactly one output file but got:"
|
||||
ls
|
||||
exit 1
|
||||
fi
|
||||
|
||||
urls=( ${{ steps.create_release.outputs.upload_url }} )
|
||||
URL="${urls[0]}=python-${PKG_NAME}"
|
||||
echo "uploading to $URL"
|
||||
|
||||
curl --silent --show-error --fail \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||
--data-binary @"${PKG_NAME}" \
|
||||
"$URL"
|
||||
|
||||
# Run the action under .github/actions/release-firmware for every board version
|
||||
#- {uses: ./.github/actions/release-firmware, with: {board-version: v3.2, url: '${{ steps.create_release.outputs.upload_url }}', token: '${{ secrets.GITHUB_TOKEN }}' }}
|
||||
#- {uses: ./.github/actions/release-firmware, with: {board-version: v3.3, url: '${{ steps.create_release.outputs.upload_url }}', token: '${{ secrets.GITHUB_TOKEN }}' }}
|
||||
#- {uses: ./.github/actions/release-firmware, with: {board-version: v3.4-24V, url: '${{ steps.create_release.outputs.upload_url }}', token: '${{ secrets.GITHUB_TOKEN }}' }}
|
||||
#- {uses: ./.github/actions/release-firmware, with: {board-version: v3.4-48V, url: '${{ steps.create_release.outputs.upload_url }}', token: '${{ secrets.GITHUB_TOKEN }}' }}
|
||||
- {uses: ./.github/actions/release-firmware, with: {board_version: v3.5-24V, url: '${{ steps.create_release.outputs.upload_url }}', token: '${{ secrets.GITHUB_TOKEN }}' }}
|
||||
- {uses: ./.github/actions/release-firmware, with: {board_version: v3.5-48V, url: '${{ steps.create_release.outputs.upload_url }}', token: '${{ secrets.GITHUB_TOKEN }}' }}
|
||||
- {uses: ./.github/actions/release-firmware, with: {board_version: v3.6-24V, url: '${{ steps.create_release.outputs.upload_url }}', token: '${{ secrets.GITHUB_TOKEN }}' }}
|
||||
- {uses: ./.github/actions/release-firmware, with: {board_version: v3.6-56V, url: '${{ steps.create_release.outputs.upload_url }}', token: '${{ secrets.GITHUB_TOKEN }}' }}
|
||||
Generated
+92
-115
File diff suppressed because it is too large
Load Diff
+12
-3
@@ -25,9 +25,6 @@ project = 'ODrive Documentation'
|
||||
copyright = '2021, ODrive Robotics'
|
||||
author = 'ODrive Robotics'
|
||||
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = '0.0'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
@@ -61,6 +58,11 @@ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
#
|
||||
# html_theme = 'alabaster'
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
html_theme_options = {
|
||||
'analytics_id':'UA-93396600-3',
|
||||
'style_external_links': True,
|
||||
'display_version': True,
|
||||
}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
@@ -72,3 +74,10 @@ fibre_interface_files = ['../Firmware/odrive-interface.yaml']
|
||||
autosummary_generate = False
|
||||
|
||||
intersphinx_mapping = {'python': ('https://docs.python.org/3', None)}
|
||||
|
||||
html_js_files = [
|
||||
'https://docs.odriverobotics.com/docsInject.js'
|
||||
]
|
||||
|
||||
version = "0.5.4"
|
||||
release = version
|
||||
|
||||
Reference in New Issue
Block a user