|
|
|
@@ -1,183 +1,291 @@ |
|
|
|
name: Release |
|
|
|
# This file was autogenerated by dist: https://opensource.axo.dev/cargo-dist/ |
|
|
|
# |
|
|
|
# Copyright 2022-2024, axodotdev |
|
|
|
# SPDX-License-Identifier: MIT or Apache-2.0 |
|
|
|
# |
|
|
|
# CI that: |
|
|
|
# |
|
|
|
# * checks for a Git Tag that looks like a release |
|
|
|
# * builds artifacts with dist (archives, installers, hashes) |
|
|
|
# * uploads those artifacts to temporary workflow zip |
|
|
|
# * on success, uploads the artifacts to a GitHub Release |
|
|
|
# |
|
|
|
# Note that the GitHub Release will be created with a generated |
|
|
|
# title/body based on your changelogs. |
|
|
|
|
|
|
|
name: Release |
|
|
|
permissions: |
|
|
|
contents: write |
|
|
|
"contents": "write" |
|
|
|
|
|
|
|
# This task will run whenever you push a git tag that looks like a version |
|
|
|
# like "1.0.0", "v0.1.0-prerelease.1", "my-app/0.1.0", "releases/v1.0.0", etc. |
|
|
|
# Various formats will be parsed into a VERSION and an optional PACKAGE_NAME, where |
|
|
|
# PACKAGE_NAME must be the name of a Cargo package in your workspace, and VERSION |
|
|
|
# must be a Cargo-style SemVer Version (must have at least major.minor.patch). |
|
|
|
# |
|
|
|
# If PACKAGE_NAME is specified, then the announcement will be for that |
|
|
|
# package (erroring out if it doesn't have the given version or isn't dist-able). |
|
|
|
# |
|
|
|
# If PACKAGE_NAME isn't specified, then the announcement will be for all |
|
|
|
# (dist-able) packages in the workspace with that version (this mode is |
|
|
|
# intended for workspaces with only one dist-able package, or with all dist-able |
|
|
|
# packages versioned/released in lockstep). |
|
|
|
# |
|
|
|
# If you push multiple tags at once, separate instances of this workflow will |
|
|
|
# spin up, creating an independent announcement for each one. However, GitHub |
|
|
|
# will hard limit this to 3 tags per commit, as it will assume more tags is a |
|
|
|
# mistake. |
|
|
|
# |
|
|
|
# If there's a prerelease-style suffix to the version, then the release(s) |
|
|
|
# will be marked as a prerelease. |
|
|
|
on: |
|
|
|
release: |
|
|
|
types: |
|
|
|
- "published" |
|
|
|
workflow_dispatch: |
|
|
|
pull_request: |
|
|
|
push: |
|
|
|
tags: |
|
|
|
- '**[0-9]+.[0-9]+.[0-9]+*' |
|
|
|
|
|
|
|
jobs: |
|
|
|
cargo-release: |
|
|
|
name: "Cargo Release" |
|
|
|
|
|
|
|
strategy: |
|
|
|
matrix: |
|
|
|
platform: [ubuntu-22.04] |
|
|
|
fail-fast: false |
|
|
|
runs-on: ${{ matrix.platform }} |
|
|
|
|
|
|
|
# Run 'dist plan' (or host) to determine what tasks we need to do |
|
|
|
plan: |
|
|
|
runs-on: "ubuntu-20.04" |
|
|
|
outputs: |
|
|
|
val: ${{ steps.plan.outputs.manifest }} |
|
|
|
tag: ${{ !github.event.pull_request && github.ref_name || '' }} |
|
|
|
tag-flag: ${{ !github.event.pull_request && format('--tag={0}', github.ref_name) || '' }} |
|
|
|
publishing: ${{ !github.event.pull_request }} |
|
|
|
env: |
|
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|
|
|
steps: |
|
|
|
- uses: actions/checkout@v3 |
|
|
|
|
|
|
|
- uses: r7kamura/rust-problem-matchers@v1.1.0 |
|
|
|
- name: Free Disk Space (Ubuntu) |
|
|
|
uses: jlumbroso/free-disk-space@main |
|
|
|
if: runner.os == 'Linux' |
|
|
|
with: |
|
|
|
# this might remove tools that are actually needed, |
|
|
|
# if set to "true" but frees about 6 GB |
|
|
|
tool-cache: true |
|
|
|
|
|
|
|
# all of these default to true, but feel free to set to |
|
|
|
# "false" if necessary for your workflow |
|
|
|
android: true |
|
|
|
dotnet: true |
|
|
|
haskell: true |
|
|
|
large-packages: false |
|
|
|
docker-images: true |
|
|
|
swap-storage: true |
|
|
|
|
|
|
|
- name: "Publish packages on `crates.io`" |
|
|
|
if: runner.os == 'Linux' |
|
|
|
env: |
|
|
|
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} |
|
|
|
- uses: actions/checkout@v4 |
|
|
|
with: |
|
|
|
submodules: recursive |
|
|
|
- name: Install dist |
|
|
|
# we specify bash to get pipefail; it guards against the `curl` command |
|
|
|
# failing. otherwise `sh` won't catch that `curl` returned non-0 |
|
|
|
shell: bash |
|
|
|
run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.28.0/cargo-dist-installer.sh | sh" |
|
|
|
- name: Cache dist |
|
|
|
uses: actions/upload-artifact@v4 |
|
|
|
with: |
|
|
|
name: cargo-dist-cache |
|
|
|
path: ~/.cargo/bin/dist |
|
|
|
# sure would be cool if github gave us proper conditionals... |
|
|
|
# so here's a doubly-nested ternary-via-truthiness to try to provide the best possible |
|
|
|
# functionality based on whether this is a pull_request, and whether it's from a fork. |
|
|
|
# (PRs run on the *source* but secrets are usually on the *target* -- that's *good* |
|
|
|
# but also really annoying to build CI around when it needs secrets to work right.) |
|
|
|
- id: plan |
|
|
|
run: | |
|
|
|
dist ${{ (!github.event.pull_request && format('host --steps=create --tag={0}', github.ref_name)) || 'plan' }} --output-format=json > plan-dist-manifest.json |
|
|
|
echo "dist ran successfully" |
|
|
|
cat plan-dist-manifest.json |
|
|
|
echo "manifest=$(jq -c "." plan-dist-manifest.json)" >> "$GITHUB_OUTPUT" |
|
|
|
- name: "Upload dist-manifest.json" |
|
|
|
uses: actions/upload-artifact@v4 |
|
|
|
with: |
|
|
|
name: artifacts-plan-dist-manifest |
|
|
|
path: plan-dist-manifest.json |
|
|
|
|
|
|
|
# Publishing those crates from outer crates with no dependency to inner crates |
|
|
|
# As cargo is going to rebuild the crates based on published dependencies |
|
|
|
# we need to publish those outer crates first to be able to test the publication |
|
|
|
# of inner crates. |
|
|
|
# |
|
|
|
# We should preferably test pre-releases before testing releases as |
|
|
|
# cargo publish might catch release issues that the workspace manages to fix using |
|
|
|
# workspace crates. |
|
|
|
publish_if_not_exists() { |
|
|
|
local package_name=$1 |
|
|
|
local version=$(cargo metadata --no-deps --format-version=1 | jq -r '.packages[] | select(.name=="'"$package_name"'") | .version') |
|
|
|
|
|
|
|
if [[ -z $version ]]; then |
|
|
|
echo "error: package '$package_name' not found in the workspace." |
|
|
|
return 1 |
|
|
|
fi |
|
|
|
|
|
|
|
if cargo search "$package_name" | grep -q "^$package_name = \"$version\""; then |
|
|
|
echo "package '$package_name' version '$version' already exists on crates.io. skipping publish." |
|
|
|
else |
|
|
|
echo "publishing package '$package_name' version '$version'..." |
|
|
|
cargo publish --package "$package_name" |
|
|
|
fi |
|
|
|
} |
|
|
|
|
|
|
|
# the dora-message package is versioned separately, so this publish command might fail if the version is already published |
|
|
|
publish_if_not_exists dora-message |
|
|
|
|
|
|
|
# Publish libraries crates |
|
|
|
publish_if_not_exists dora-tracing |
|
|
|
publish_if_not_exists dora-metrics |
|
|
|
publish_if_not_exists dora-download |
|
|
|
publish_if_not_exists dora-core |
|
|
|
publish_if_not_exists communication-layer-pub-sub |
|
|
|
publish_if_not_exists communication-layer-request-reply |
|
|
|
publish_if_not_exists shared-memory-server |
|
|
|
publish_if_not_exists dora-arrow-convert |
|
|
|
|
|
|
|
# Publish rust API |
|
|
|
publish_if_not_exists dora-operator-api-macros |
|
|
|
publish_if_not_exists dora-operator-api-types |
|
|
|
publish_if_not_exists dora-operator-api |
|
|
|
publish_if_not_exists dora-node-api |
|
|
|
publish_if_not_exists dora-operator-api-python |
|
|
|
publish_if_not_exists dora-operator-api-c |
|
|
|
publish_if_not_exists dora-node-api-c |
|
|
|
|
|
|
|
# Publish binaries crates |
|
|
|
publish_if_not_exists dora-coordinator |
|
|
|
publish_if_not_exists dora-runtime |
|
|
|
publish_if_not_exists dora-daemon |
|
|
|
publish_if_not_exists dora-cli |
|
|
|
|
|
|
|
# Publish ROS2 bridge |
|
|
|
publish_if_not_exists dora-ros2-bridge-msg-gen |
|
|
|
publish_if_not_exists dora-ros2-bridge |
|
|
|
unix: |
|
|
|
runs-on: ${{ matrix.platform.runner }} |
|
|
|
# Build and packages all the platform-specific things |
|
|
|
build-local-artifacts: |
|
|
|
name: build-local-artifacts (${{ join(matrix.targets, ', ') }}) |
|
|
|
# Let the initial task tell us to not run (currently very blunt) |
|
|
|
needs: |
|
|
|
- plan |
|
|
|
if: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix.include != null && (needs.plan.outputs.publishing == 'true' || fromJson(needs.plan.outputs.val).ci.github.pr_run_mode == 'upload') }} |
|
|
|
strategy: |
|
|
|
matrix: |
|
|
|
platform: |
|
|
|
- runner: ubuntu-22.04 |
|
|
|
target: x86_64-unknown-linux-gnu |
|
|
|
- runner: ubuntu-22.04 |
|
|
|
target: i686-unknown-linux-gnu |
|
|
|
- runner: ubuntu-22.04 |
|
|
|
target: aarch64-unknown-linux-gnu |
|
|
|
- runner: ubuntu-22.04 |
|
|
|
target: aarch64-unknown-linux-musl |
|
|
|
- runner: ubuntu-22.04 |
|
|
|
target: armv7-unknown-linux-musleabihf |
|
|
|
- runner: macos-13 |
|
|
|
target: aarch64-apple-darwin |
|
|
|
- runner: macos-13 |
|
|
|
target: x86_64-apple-darwin |
|
|
|
fail-fast: false |
|
|
|
# Target platforms/runners are computed by dist in create-release. |
|
|
|
# Each member of the matrix has the following arguments: |
|
|
|
# |
|
|
|
# - runner: the github runner |
|
|
|
# - dist-args: cli flags to pass to dist |
|
|
|
# - install-dist: expression to run to install dist on the runner |
|
|
|
# |
|
|
|
# Typically there will be: |
|
|
|
# - 1 "global" task that builds universal installers |
|
|
|
# - N "local" tasks that build each platform's binaries and platform-specific installers |
|
|
|
matrix: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix }} |
|
|
|
runs-on: ${{ matrix.runner }} |
|
|
|
container: ${{ matrix.container && matrix.container.image || null }} |
|
|
|
env: |
|
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|
|
|
BUILD_MANIFEST_NAME: target/distrib/${{ join(matrix.targets, '-') }}-dist-manifest.json |
|
|
|
steps: |
|
|
|
- uses: actions/checkout@v3 |
|
|
|
- uses: r7kamura/rust-problem-matchers@v1.1.0 |
|
|
|
- name: "Add toolchains" |
|
|
|
run: rustup target add ${{ matrix.platform.target }} |
|
|
|
- name: "Build" |
|
|
|
uses: actions-rs/cargo@v1 |
|
|
|
with: |
|
|
|
use-cross: true |
|
|
|
command: build |
|
|
|
args: --release --target ${{ matrix.platform.target }} -p dora-cli |
|
|
|
- name: "Archive" |
|
|
|
run: zip -j -r ${{ matrix.platform.target }}.zip target/${{ matrix.platform.target }}/release/dora |
|
|
|
|
|
|
|
- name: "Upload asset" |
|
|
|
uses: actions/upload-release-asset@v1.0.1 |
|
|
|
env: |
|
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|
|
|
- name: enable windows longpaths |
|
|
|
run: | |
|
|
|
git config --global core.longpaths true |
|
|
|
- uses: actions/checkout@v4 |
|
|
|
with: |
|
|
|
upload_url: ${{ github.event.release.upload_url }} |
|
|
|
asset_path: ${{ matrix.platform.target }}.zip |
|
|
|
asset_name: dora-${{ github.ref_name }}-${{ matrix.platform.target }}.zip |
|
|
|
asset_content_type: application/zip |
|
|
|
|
|
|
|
windows-release: |
|
|
|
name: "Windows Release" |
|
|
|
|
|
|
|
strategy: |
|
|
|
matrix: |
|
|
|
platform: |
|
|
|
- runner: windows-2022 |
|
|
|
target: x86_64-pc-windows-msvc |
|
|
|
submodules: recursive |
|
|
|
- name: Install Rust non-interactively if not already installed |
|
|
|
if: ${{ matrix.container }} |
|
|
|
run: | |
|
|
|
if ! command -v cargo > /dev/null 2>&1; then |
|
|
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y |
|
|
|
echo "$HOME/.cargo/bin" >> $GITHUB_PATH |
|
|
|
fi |
|
|
|
- name: Install dist |
|
|
|
run: ${{ matrix.install_dist.run }} |
|
|
|
# Get the dist-manifest |
|
|
|
- name: Fetch local artifacts |
|
|
|
uses: actions/download-artifact@v4 |
|
|
|
with: |
|
|
|
pattern: artifacts-* |
|
|
|
path: target/distrib/ |
|
|
|
merge-multiple: true |
|
|
|
- name: Install dependencies |
|
|
|
run: | |
|
|
|
${{ matrix.packages_install }} |
|
|
|
- name: Build artifacts |
|
|
|
run: | |
|
|
|
# Actually do builds and make zips and whatnot |
|
|
|
dist build ${{ needs.plan.outputs.tag-flag }} --print=linkage --output-format=json ${{ matrix.dist_args }} > dist-manifest.json |
|
|
|
echo "dist ran successfully" |
|
|
|
- id: cargo-dist |
|
|
|
name: Post-build |
|
|
|
# We force bash here just because github makes it really hard to get values up |
|
|
|
# to "real" actions without writing to env-vars, and writing to env-vars has |
|
|
|
# inconsistent syntax between shell and powershell. |
|
|
|
shell: bash |
|
|
|
run: | |
|
|
|
# Parse out what we just built and upload it to scratch storage |
|
|
|
echo "paths<<EOF" >> "$GITHUB_OUTPUT" |
|
|
|
dist print-upload-files-from-manifest --manifest dist-manifest.json >> "$GITHUB_OUTPUT" |
|
|
|
echo "EOF" >> "$GITHUB_OUTPUT" |
|
|
|
|
|
|
|
fail-fast: false |
|
|
|
runs-on: ${{ matrix.platform.runner }} |
|
|
|
cp dist-manifest.json "$BUILD_MANIFEST_NAME" |
|
|
|
- name: "Upload artifacts" |
|
|
|
uses: actions/upload-artifact@v4 |
|
|
|
with: |
|
|
|
name: artifacts-build-local-${{ join(matrix.targets, '_') }} |
|
|
|
path: | |
|
|
|
${{ steps.cargo-dist.outputs.paths }} |
|
|
|
${{ env.BUILD_MANIFEST_NAME }} |
|
|
|
|
|
|
|
# Build and package all the platform-agnostic(ish) things |
|
|
|
build-global-artifacts: |
|
|
|
needs: |
|
|
|
- plan |
|
|
|
- build-local-artifacts |
|
|
|
runs-on: "ubuntu-20.04" |
|
|
|
env: |
|
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|
|
|
BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json |
|
|
|
steps: |
|
|
|
- uses: actions/checkout@v3 |
|
|
|
- uses: actions/checkout@v4 |
|
|
|
with: |
|
|
|
submodules: recursive |
|
|
|
- name: Install cached dist |
|
|
|
uses: actions/download-artifact@v4 |
|
|
|
with: |
|
|
|
name: cargo-dist-cache |
|
|
|
path: ~/.cargo/bin/ |
|
|
|
- run: chmod +x ~/.cargo/bin/dist |
|
|
|
# Get all the local artifacts for the global tasks to use (for e.g. checksums) |
|
|
|
- name: Fetch local artifacts |
|
|
|
uses: actions/download-artifact@v4 |
|
|
|
with: |
|
|
|
pattern: artifacts-* |
|
|
|
path: target/distrib/ |
|
|
|
merge-multiple: true |
|
|
|
- id: cargo-dist |
|
|
|
shell: bash |
|
|
|
run: | |
|
|
|
dist build ${{ needs.plan.outputs.tag-flag }} --output-format=json "--artifacts=global" > dist-manifest.json |
|
|
|
echo "dist ran successfully" |
|
|
|
|
|
|
|
- uses: r7kamura/rust-problem-matchers@v1.1.0 |
|
|
|
# Parse out what we just built and upload it to scratch storage |
|
|
|
echo "paths<<EOF" >> "$GITHUB_OUTPUT" |
|
|
|
jq --raw-output ".upload_files[]" dist-manifest.json >> "$GITHUB_OUTPUT" |
|
|
|
echo "EOF" >> "$GITHUB_OUTPUT" |
|
|
|
|
|
|
|
- name: "Build binaries" |
|
|
|
timeout-minutes: 60 |
|
|
|
run: "cargo build --release -p dora-cli" |
|
|
|
cp dist-manifest.json "$BUILD_MANIFEST_NAME" |
|
|
|
- name: "Upload artifacts" |
|
|
|
uses: actions/upload-artifact@v4 |
|
|
|
with: |
|
|
|
name: artifacts-build-global |
|
|
|
path: | |
|
|
|
${{ steps.cargo-dist.outputs.paths }} |
|
|
|
${{ env.BUILD_MANIFEST_NAME }} |
|
|
|
# Determines if we should publish/announce |
|
|
|
host: |
|
|
|
needs: |
|
|
|
- plan |
|
|
|
- build-local-artifacts |
|
|
|
- build-global-artifacts |
|
|
|
# Only run if we're "publishing", and only if local and global didn't fail (skipped is fine) |
|
|
|
if: ${{ always() && needs.plan.outputs.publishing == 'true' && (needs.build-global-artifacts.result == 'skipped' || needs.build-global-artifacts.result == 'success') && (needs.build-local-artifacts.result == 'skipped' || needs.build-local-artifacts.result == 'success') }} |
|
|
|
env: |
|
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|
|
|
runs-on: "ubuntu-20.04" |
|
|
|
outputs: |
|
|
|
val: ${{ steps.host.outputs.manifest }} |
|
|
|
steps: |
|
|
|
- uses: actions/checkout@v4 |
|
|
|
with: |
|
|
|
submodules: recursive |
|
|
|
- name: Install cached dist |
|
|
|
uses: actions/download-artifact@v4 |
|
|
|
with: |
|
|
|
name: cargo-dist-cache |
|
|
|
path: ~/.cargo/bin/ |
|
|
|
- run: chmod +x ~/.cargo/bin/dist |
|
|
|
# Fetch artifacts from scratch-storage |
|
|
|
- name: Fetch artifacts |
|
|
|
uses: actions/download-artifact@v4 |
|
|
|
with: |
|
|
|
pattern: artifacts-* |
|
|
|
path: target/distrib/ |
|
|
|
merge-multiple: true |
|
|
|
- id: host |
|
|
|
shell: bash |
|
|
|
run: | |
|
|
|
dist host ${{ needs.plan.outputs.tag-flag }} --steps=upload --steps=release --output-format=json > dist-manifest.json |
|
|
|
echo "artifacts uploaded and released successfully" |
|
|
|
cat dist-manifest.json |
|
|
|
echo "manifest=$(jq -c "." dist-manifest.json)" >> "$GITHUB_OUTPUT" |
|
|
|
- name: "Upload dist-manifest.json" |
|
|
|
uses: actions/upload-artifact@v4 |
|
|
|
with: |
|
|
|
# Overwrite the previous copy |
|
|
|
name: artifacts-dist-manifest |
|
|
|
path: dist-manifest.json |
|
|
|
# Create a GitHub Release while uploading all files to it |
|
|
|
- name: "Download GitHub Artifacts" |
|
|
|
uses: actions/download-artifact@v4 |
|
|
|
with: |
|
|
|
pattern: artifacts-* |
|
|
|
path: artifacts |
|
|
|
merge-multiple: true |
|
|
|
- name: Cleanup |
|
|
|
run: | |
|
|
|
# Remove the granular manifests |
|
|
|
rm -f artifacts/*-dist-manifest.json |
|
|
|
- name: Create GitHub Release |
|
|
|
env: |
|
|
|
PRERELEASE_FLAG: "${{ fromJson(steps.host.outputs.manifest).announcement_is_prerelease && '--prerelease' || '' }}" |
|
|
|
ANNOUNCEMENT_TITLE: "${{ fromJson(steps.host.outputs.manifest).announcement_title }}" |
|
|
|
ANNOUNCEMENT_BODY: "${{ fromJson(steps.host.outputs.manifest).announcement_github_body }}" |
|
|
|
RELEASE_COMMIT: "${{ github.sha }}" |
|
|
|
run: | |
|
|
|
# Write and read notes from a file to avoid quoting breaking things |
|
|
|
echo "$ANNOUNCEMENT_BODY" > $RUNNER_TEMP/notes.txt |
|
|
|
|
|
|
|
- name: Create Archive (Windows) |
|
|
|
if: runner.os == 'Windows' |
|
|
|
shell: powershell |
|
|
|
run: Compress-Archive -Path target/release/dora.exe -DestinationPath archive.zip |
|
|
|
gh release create "${{ needs.plan.outputs.tag }}" --target "$RELEASE_COMMIT" $PRERELEASE_FLAG --title "$ANNOUNCEMENT_TITLE" --notes-file "$RUNNER_TEMP/notes.txt" artifacts/* |
|
|
|
|
|
|
|
- name: "Upload release asset" |
|
|
|
uses: actions/upload-release-asset@v1.0.1 |
|
|
|
env: |
|
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|
|
|
announce: |
|
|
|
needs: |
|
|
|
- plan |
|
|
|
- host |
|
|
|
# use "always() && ..." to allow us to wait for all publish jobs while |
|
|
|
# still allowing individual publish jobs to skip themselves (for prereleases). |
|
|
|
# "host" however must run to completion, no skipping allowed! |
|
|
|
if: ${{ always() && needs.host.result == 'success' }} |
|
|
|
runs-on: "ubuntu-20.04" |
|
|
|
env: |
|
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|
|
|
steps: |
|
|
|
- uses: actions/checkout@v4 |
|
|
|
with: |
|
|
|
upload_url: ${{ github.event.release.upload_url }} |
|
|
|
asset_path: archive.zip |
|
|
|
asset_name: dora-${{ github.ref_name }}-${{ matrix.platform.target }}.zip |
|
|
|
asset_content_type: application/zip |
|
|
|
submodules: recursive |