From 4b80fc102b4211f4f390c72bb54776886182185c Mon Sep 17 00:00:00 2001 From: Dennis Diatlov Date: Thu, 7 Nov 2024 10:11:28 +0000 Subject: [PATCH] build(rs): automate Rust releases (#632) --- .github/actions/free-disk-space/action.yml | 22 ++ .github/actions/install-wasm-utils/action.yml | 18 ++ .github/workflows/ci.yml | 154 ----------- .github/workflows/{ci-net.yml => net-ci.yml} | 3 +- .github/workflows/rs-ci.yml | 64 +++++ .github/workflows/rs-release.yml | 246 ++++++++++++++++++ .github/workflows/rs-run-cli-tests.yml | 47 ++++ .github/workflows/rs-run-ws-tests.yml | 41 +++ templates/set-vars.rhai | 2 +- 9 files changed, 441 insertions(+), 156 deletions(-) create mode 100644 .github/actions/free-disk-space/action.yml create mode 100644 .github/actions/install-wasm-utils/action.yml delete mode 100644 .github/workflows/ci.yml rename .github/workflows/{ci-net.yml => net-ci.yml} (93%) create mode 100644 .github/workflows/rs-ci.yml create mode 100644 .github/workflows/rs-release.yml create mode 100644 .github/workflows/rs-run-cli-tests.yml create mode 100644 .github/workflows/rs-run-ws-tests.yml diff --git a/.github/actions/free-disk-space/action.yml b/.github/actions/free-disk-space/action.yml new file mode 100644 index 00000000..cb6f145a --- /dev/null +++ b/.github/actions/free-disk-space/action.yml @@ -0,0 +1,22 @@ +name: Free Disk Space +description: Preconfigured action to free up disk space on GitHub Actions runners +# Inputs might be added in the future, but for now, the defaults should be sufficient + +runs: + using: composite + + steps: + - name: Free Disk Space + uses: jlumbroso/free-disk-space@main + with: + # this might remove tools that are actually needed, + # if set to "true" but frees about 6 GB + tool-cache: false + # all of these default to true, but feel free to set to + # "false" if necessary for your workflow + android: true + dotnet: false + haskell: true + large-packages: false + docker-images: true + swap-storage: true diff --git a/.github/actions/install-wasm-utils/action.yml b/.github/actions/install-wasm-utils/action.yml new file mode 100644 index 00000000..91c44f66 --- /dev/null +++ b/.github/actions/install-wasm-utils/action.yml @@ -0,0 +1,18 @@ +name: Install WASM Utils from Binaryen +description: Install wasm-opt and other utilities from Binaryen +inputs: + binaryen_version: + description: "Binaryen Version" + required: false + default: "111" + +runs: + using: composite + + steps: + - name: Install wasm-opt + shell: bash + run: | + BINARYEN_VERSION=version_${{ inputs.binaryen_version }} + sudo wget -c https://github.com/WebAssembly/binaryen/releases/download/$BINARYEN_VERSION/binaryen-$BINARYEN_VERSION-x86_64-linux.tar.gz -O - | sudo tar -xz -C . + sudo cp binaryen-$BINARYEN_VERSION/bin/wasm-opt /usr/bin/ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 82024716..00000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,154 +0,0 @@ -name: CI (Rust) - -on: - push: - branches: [master] - paths: - - '.cargo/**' - - '.github/workflows/ci.yml' - - 'examples/**' - - 'rs/**' - - 'templates/**' - - 'Cargo.lock' - - 'Cargo.toml' - - 'rust-toolchain.toml' - pull_request: - paths: - - '.cargo/**' - - '.github/workflows/ci.yml' - - 'examples/**' - - 'rs/**' - - 'templates/**' - - 'Cargo.lock' - - 'Cargo.toml' - - 'rust-toolchain.toml' - -env: - BINARYEN_VERSION: version_111 - CARGO_TERM_COLOR: always - -jobs: - check: - name: Check Code - runs-on: ubuntu-latest - - steps: - - name: Free Disk Space - uses: jlumbroso/free-disk-space@main - with: - # this might remove tools that are actually needed, - # if set to "true" but frees about 6 GB - tool-cache: false - - # all of these default to true, but feel free to set to - # "false" if necessary for your workflow - android: true - dotnet: false - haskell: true - large-packages: false - docker-images: true - swap-storage: true - - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Install wasm-opt - run: | - sudo wget -c https://github.com/WebAssembly/binaryen/releases/download/$BINARYEN_VERSION/binaryen-$BINARYEN_VERSION-x86_64-linux.tar.gz -O - | sudo tar -xz -C . - sudo cp binaryen-$BINARYEN_VERSION/bin/wasm-opt /usr/bin/ - - - name: Check Code Formatting - run: __GEAR_WASM_BUILDER_NO_FEATURES_TRACKING=1 cargo fmt --all --check - - - name: Check Code With Clippy - run: __GEAR_WASM_BUILDER_NO_FEATURES_TRACKING=1 cargo clippy --workspace --all-targets --locked -- -D warnings - - - name: Check IDL Parser For WASM With Clippy - run: __GEAR_WASM_BUILDER_NO_FEATURES_TRACKING=1 cargo clippy -p sails-idl-parser --all-targets --locked --target=wasm32-unknown-unknown -- -D warnings - - test: - name: Run Tests - runs-on: ubuntu-latest - - steps: - - name: Free Disk Space - uses: jlumbroso/free-disk-space@main - with: - # this might remove tools that are actually needed, - # if set to "true" but frees about 6 GB - tool-cache: false - - # all of these default to true, but feel free to set to - # "false" if necessary for your workflow - android: true - dotnet: false - haskell: true - large-packages: false - docker-images: true - swap-storage: true - - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Install wasm-opt - run: | - sudo wget -c https://github.com/WebAssembly/binaryen/releases/download/$BINARYEN_VERSION/binaryen-$BINARYEN_VERSION-x86_64-linux.tar.gz -O - | sudo tar -xz -C . - sudo cp binaryen-$BINARYEN_VERSION/bin/wasm-opt /usr/bin/ - - - name: Download Gear Node - run: | - sudo wget -O ./gear https://github.com/gear-tech/gear/releases/download/v1.6.0/gear - sudo chmod +x gear - sudo mv gear /usr/bin/ - - - name: Run Tests - env: - GEAR_PATH: /usr/bin/gear - run: __GEAR_WASM_BUILDER_NO_FEATURES_TRACKING=1 cargo test --workspace --all-targets --locked --no-fail-fast -- --include-ignored - - test-cli: - name: Run CLI Tests - runs-on: ubuntu-latest - - steps: - - name: Free Disk Space - uses: jlumbroso/free-disk-space@main - with: - # this might remove tools that are actually needed, - # if set to "true" but frees about 6 GB - tool-cache: false - - # all of these default to true, but feel free to set to - # "false" if necessary for your workflow - android: true - dotnet: false - haskell: true - large-packages: false - docker-images: true - swap-storage: true - - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Install wasm-opt - run: | - sudo wget -c https://github.com/WebAssembly/binaryen/releases/download/$BINARYEN_VERSION/binaryen-$BINARYEN_VERSION-x86_64-linux.tar.gz -O - | sudo tar -xz -C . - sudo cp binaryen-$BINARYEN_VERSION/bin/wasm-opt /usr/bin/ - - - name: Build CLI - run: | - cargo build -p sails-cli - - - name: Generate MyDemo via CLI - run: | - SAILS_CLI_TEMPLATES_BRANCH=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}} ./target/debug/cargo-sails sails program ~/tmp --name my-demo - - - name: Run Tests on MyDemo - run: | - cd ~/tmp/my-demo - cargo test -p my-demo - - - name: Generate IDL from MyDemo via CLI - run: | - ./target/debug/cargo-sails sails idl --manifest-path ~/tmp/my-demo/Cargo.toml - diff ~/tmp/my-demo/target/my-demo-app.idl ~/tmp/my-demo/target/wasm32-unknown-unknown/debug/my_demo.idl diff --git a/.github/workflows/ci-net.yml b/.github/workflows/net-ci.yml similarity index 93% rename from .github/workflows/ci-net.yml rename to .github/workflows/net-ci.yml index 2dd61066..3f0208af 100644 --- a/.github/workflows/ci-net.yml +++ b/.github/workflows/net-ci.yml @@ -1,4 +1,4 @@ -name: CI (.Net) +name: '[net] CI (.Net)' on: push: @@ -17,6 +17,7 @@ on: jobs: check: + name: Check Code runs-on: ubuntu-latest defaults: run: diff --git a/.github/workflows/rs-ci.yml b/.github/workflows/rs-ci.yml new file mode 100644 index 00000000..294cbcad --- /dev/null +++ b/.github/workflows/rs-ci.yml @@ -0,0 +1,64 @@ +name: '[rs] CI (Rust)' + +on: + push: + branches: [master] + paths: + - '.cargo/**' + - '.github/workflows/rs-*.yml' # No biggie to trigger this on changes in rs-release.yml + - 'examples/**' + - 'rs/**' + - 'templates/**' + - 'Cargo.lock' + - 'Cargo.toml' + - 'rust-toolchain.toml' + pull_request: + paths: + - '.cargo/**' + - '.github/workflows/rs-*.yml' # No biggie to trigger this on changes in rs-release.yml + - 'examples/**' + - 'rs/**' + - 'templates/**' + - 'Cargo.lock' + - 'Cargo.toml' + - 'rust-toolchain.toml' + +env: + CARGO_TERM_COLOR: always + +jobs: + check: + name: Check Code + runs-on: ubuntu-latest + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Free Disk Space + uses: ./.github/actions/free-disk-space + + - name: Install wasm-opt + uses: ./.github/actions/install-wasm-utils + + - name: Check Code Formatting + run: | + __GEAR_WASM_BUILDER_NO_FEATURES_TRACKING=1 cargo fmt --all --check + + - name: Check Code With Clippy + run: | + __GEAR_WASM_BUILDER_NO_FEATURES_TRACKING=1 cargo clippy --workspace --all-targets --locked -- -D warnings + + - name: Check IDL Parser For WASM With Clippy + run: | + __GEAR_WASM_BUILDER_NO_FEATURES_TRACKING=1 cargo clippy -p sails-idl-parser --all-targets --locked --target=wasm32-unknown-unknown -- -D warnings + + test: + name: Run Workflow Tests + uses: ./.github/workflows/rs-run-ws-tests.yml + with: + gear_node_version: 1.6.0 + + test-cli: + name: Run CLI Tests + uses: ./.github/workflows/rs-run-cli-tests.yml diff --git a/.github/workflows/rs-release.yml b/.github/workflows/rs-release.yml new file mode 100644 index 00000000..dacbbba2 --- /dev/null +++ b/.github/workflows/rs-release.yml @@ -0,0 +1,246 @@ +# This workflow is triggered by a tag that matches the pattern rs/v*-rc. +# Essentially it does the following: +# - gathers release info including its version using created tag +# - applies version to the workspace and updates crates dependencies +# - runs all tests before going further +# - builds assets for the release: IDL Parser for WASM +# - publishes 'sails-*' crates to crates.io +# - amends contract template with the new version and runs tests against it +# - crates PR with the changes, release tag and draft release +# Merging PR and pubslishing release is supposed to be done manually. +name: '[rs] Release (Rust)' + +on: + push: + tags: + - 'rs/v*-rc' + +env: + # see https://api.github.com/users/github-actions%5Bbot%5D + GITHUB_USER_NAME: github-actions[bot] + GITHUB_USER_EMAIL: 41898282+github-actions[bot]@users.noreply.github.com + # crates in order of dependency (topological order), first the ones that are not dependent on any other + SAILS_CRATES: | + sails-idl-meta + sails-idl-parser + sails-idl-gen + sails-client-gen + sails-macros-core + sails-macros + sails-rs + sails-cli + +jobs: + prepare: + name: Prepare Release + runs-on: ubuntu-latest + permissions: + contents: write + defaults: + run: + shell: bash + outputs: + rc_branch: ${{ steps.release_branch.outputs.rc_branch }} + r_version: ${{ steps.release_info.outputs.version }} + r_tag: rs/v${{ steps.release_info.outputs.version }} + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract Release Info + id: release_info + run: | + RELEASE_TAG=${GITHUB_REF#refs/tags/} + VERSION=${RELEASE_TAG#rs/v} + VERSION="${VERSION%-rc}" + if [[ ! $VERSION =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "'$VERSION' is not a valid semver version" + exit 1 + fi + echo "Version: $VERSION" + echo "version=$VERSION" >> $GITHUB_OUTPUT + + - name: Set Workspace Version + run: | + sed -i "s/^version = \".*\"/version = \"${{ steps.release_info.outputs.version }}\"/" Cargo.toml + + - name: Update Workspace Dependencies + run: | + cargo update + + - name: Create Release Branch + id: release_branch + run: | + RC_BRANCH="rc/rs/v${{ steps.release_info.outputs.version }}" + git config --global user.name "$GITHUB_USER_NAME" + git config --global user.email "$GITHUB_USER_EMAIL" + git checkout -b "$RC_BRANCH" + git add Cargo.toml + git add Cargo.lock + git commit -m "build(rs): update version to v${{ steps.release_info.outputs.version }}" + git push origin "$RC_BRANCH" + echo "rc_branch=$RC_BRANCH" >> $GITHUB_OUTPUT + + ws_tests: + name: Run Workspace Tests + needs: + - prepare + uses: ./.github/workflows/rs-run-ws-tests.yml + with: + sources_ref: ${{ needs.prepare.outputs.rc_branch }} + gear_node_version: 1.6.0 + + cli_tests: + name: Run CLI Tests + needs: + - prepare + uses: ./.github/workflows/rs-run-cli-tests.yml + with: + sources_ref: ${{ needs.prepare.outputs.rc_branch }} + + assets: + name: Build Assets + runs-on: ubuntu-latest + needs: + - prepare + defaults: + run: + shell: bash + + steps: + - name: Checkout Code from Release Branch + uses: actions/checkout@v4 + with: + ref: ${{ needs.prepare.outputs.rc_branch }} + + - name: Install wasm-opt + uses: ./.github/actions/install-wasm-utils + + - name: Build IDL Parser for WASM + run: | + cargo build -p sails-idl-parser --target wasm32-unknown-unknown --release + mkdir -p ./assets/sails_idl_parser + wasm-opt -O4 -o ./assets/sails_idl_parser/sails_idl_parser.wasm ./target/wasm32-unknown-unknown/release/sails_idl_parser.wasm + + - name: Upload Assets + uses: actions/upload-artifact@v4 + with: + name: sails-assets + path: ./assets/ + + publish: + name: Publish Crates + runs-on: ubuntu-latest + needs: + - prepare + - ws_tests + - cli_tests + defaults: + run: + shell: bash + + steps: + - name: Checkout Code from Release Branch + uses: actions/checkout@v4 + with: + ref: ${{ needs.prepare.outputs.rc_branch }} + + - name: Publish Crates + run: | + VERSION=${{ needs.prepare.outputs.r_version }} + for SAILS_CRATE in $SAILS_CRATES; do + sed -i "/^\s*${SAILS_CRATE} = {.*}/ s/}/, version = \"=${VERSION}\" }/" Cargo.toml + done + cargo login ${{ secrets.CRATES_IO_TOKEN }} + for SAILS_CRATE in $SAILS_CRATES; do + cargo publish -p $SAILS_CRATE + done + git checkout -- . + + - name: Update Contract Template + run: | + VERSION=${{ needs.prepare.outputs.r_version }} + sed -i -E "s/(variable::set\(\"sails-rs-version\", \")([^\"]+)(\"\);)/\1$VERSION\3/" templates/set-vars.rhai + git config --global user.name "$GITHUB_USER_NAME" + git config --global user.email "$GITHUB_USER_EMAIL" + git add templates/set-vars.rhai + git commit -m "build(tmpl): update version to v${{ needs.prepare.outputs.r_version }} in contract template" + git push origin "${{ needs.prepare.outputs.rc_branch }}" + + cli_tests_after_publish: + name: Run CLI Tests After Publish + needs: + - prepare + - publish + uses: ./.github/workflows/rs-run-cli-tests.yml + with: + sources_ref: ${{ needs.prepare.outputs.rc_branch }} + + release: + name: Create Release + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + needs: + - prepare + - cli_tests_after_publish + - assets + defaults: + run: + shell: bash + env: + R_NAME: Sails-RS v${{ needs.prepare.outputs.r_version }} + + steps: + - name: Checkout Code from Release Branch + uses: actions/checkout@v4 + with: + ref: ${{ needs.prepare.outputs.rc_branch }} + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Download Assets + uses: actions/download-artifact@v4 + with: + name: sails-assets + path: ./assets + + - name: Create Release Tag + run: | + R_TAG=${{ needs.prepare.outputs.r_tag }} + git config --global user.name "$GITHUB_USER_NAME" + git config --global user.email "$GITHUB_USER_EMAIL" + git tag -a "$R_TAG" -m "Release v${{ needs.prepare.outputs.r_version }}" + git push origin "$R_TAG" + + - name: Install GitHub CLI + run: sudo apt-get install -y gh + + - name: Create Sync PR + id: sync_pr + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | gh auth login --with-token + PR_URL=$(gh pr create \ + --title "release: sync $R_NAME to master" \ + --body "This PR was created by GitHub Actions" \ + --base master \ + --head ${{ needs.prepare.outputs.rc_branch }}) + echo "url=$PR_URL" >> $GITHUB_OUTPUT + + - name: Create Draft Release + uses: softprops/action-gh-release@v2 + with: + name: ${{ env.R_NAME }} + tag_name: ${{ needs.prepare.outputs.r_tag }} + draft: true + body: | + :exclamation: This is a draft release. + :exclamation: Please write/generate change notes and publish the release. + :exclamation: Please also check this [PR](${{ steps.sync_pr.outputs.url }}) to sync the changes to master. + fail_on_unmatched_files: true + files: | + ./assets/sails_idl_parser/sails_idl_parser.wasm + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/rs-run-cli-tests.yml b/.github/workflows/rs-run-cli-tests.yml new file mode 100644 index 00000000..55eda334 --- /dev/null +++ b/.github/workflows/rs-run-cli-tests.yml @@ -0,0 +1,47 @@ +name: '[rs] Run CLI Tests' + +on: + workflow_call: + inputs: + sources_ref: + description: 'Sources Ref' + type: string + required: false + +jobs: + test_cli: + name: Run CLI Tests + runs-on: ubuntu-latest + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + with: + ref: ${{ inputs.sources_ref }} + + - name: Free Disk Space + uses: ./.github/actions/free-disk-space + + - name: Install wasm-opt + uses: ./.github/actions/install-wasm-utils + + - name: Build CLI + run: | + cargo build -p sails-cli + + - name: Generate MyDemo via CLI + run: | + TEMPLATES_BRANCH=${{ inputs.sources_ref }} + TEMPLATES_BRANCH=${TEMPLATES_BRANCH:-${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}} + echo "TEMPLATES_BRANCH: $TEMPLATES_BRANCH" + SAILS_CLI_TEMPLATES_BRANCH=${TEMPLATES_BRANCH} ./target/debug/cargo-sails sails program ~/tmp --name my-demo + + - name: Run Tests on MyDemo + run: | + cd ~/tmp/my-demo + cargo test -p my-demo + + - name: Generate IDL from MyDemo via CLI + run: | + ./target/debug/cargo-sails sails idl --manifest-path ~/tmp/my-demo/Cargo.toml + diff ~/tmp/my-demo/target/my-demo-app.idl ~/tmp/my-demo/target/wasm32-unknown-unknown/debug/my_demo.idl diff --git a/.github/workflows/rs-run-ws-tests.yml b/.github/workflows/rs-run-ws-tests.yml new file mode 100644 index 00000000..cc0497a5 --- /dev/null +++ b/.github/workflows/rs-run-ws-tests.yml @@ -0,0 +1,41 @@ +name: '[rs] Run Workspace Tests' + +on: + workflow_call: + inputs: + sources_ref: + description: 'Sources Ref' + type: string + required: false + gear_node_version: + description: 'Gear Node Version' + required: true + type: string + +jobs: + test_ws: + name: Run Workspace Tests + runs-on: ubuntu-latest + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + with: + ref: ${{ inputs.sources_ref }} + + - name: Free Disk Space + uses: ./.github/actions/free-disk-space + + - name: Install wasm-opt + uses: ./.github/actions/install-wasm-utils + + - name: Download Gear Node + run: | + sudo wget -O ./gear https://github.com/gear-tech/gear/releases/download/v${{ inputs.gear_node_version }}/gear + sudo chmod +x gear + sudo mv gear /usr/bin/ + + - name: Run Tests + env: + GEAR_PATH: /usr/bin/gear + run: __GEAR_WASM_BUILDER_NO_FEATURES_TRACKING=1 cargo test --workspace --all-targets --locked --no-fail-fast -- --include-ignored diff --git a/templates/set-vars.rhai b/templates/set-vars.rhai index 313406f9..f98b9dde 100644 --- a/templates/set-vars.rhai +++ b/templates/set-vars.rhai @@ -32,7 +32,7 @@ variable::set("mocks-feature-name", "mocks"); // Set versions of used crates variable::set("mockall-version", "0.12"); -variable::set("sails-rs-version", "0.6.2"); +variable::set("sails-rs-version", "0.6.2"); // NB: This version is updated autmatically by GH release workflow variable::set("tokio-version", "1.41"); fn is_kebab_case(name) {