From e5b43190558e36169b10949969bad8c8998d5eee Mon Sep 17 00:00:00 2001 From: Colin S <3526918+cbs228@users.noreply.github.com> Date: Sun, 19 Jan 2025 17:40:09 -0600 Subject: [PATCH] ci: use only one workflow everywhere MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At least once in every developer's lifetime, you will craft the *perfect* PR that passes all its tests with flying colors. You click that big green merge button with complete confidence… … only to have the post-merge "update the rolling release" job fail hideously, requiring an immediate fix or revert. Blame is passed. Ire is raised. To minimize the chance of this happening, we reduce our CI jobs down to a single workflow. We go ahead and run *all* the release tasks, even for PRs, to make sure they will succeed if we run them "for real." The only jobs that are skipped are the ones which update tags and publish new releases/packages. Everything else runs. --- .github/workflows/rust_test.yml | 211 -------------- .../{rust_release.yml => workflow.yml} | 269 ++++++++++-------- 2 files changed, 148 insertions(+), 332 deletions(-) delete mode 100644 .github/workflows/rust_test.yml rename .github/workflows/{rust_release.yml => workflow.yml} (52%) diff --git a/.github/workflows/rust_test.yml b/.github/workflows/rust_test.yml deleted file mode 100644 index 86f45c4..0000000 --- a/.github/workflows/rust_test.yml +++ /dev/null @@ -1,211 +0,0 @@ -name: Test - -on: - push: - branches: [ "release/**" ] - pull_request: - branches: [ "develop" ] - -env: - CARGO_TERM_COLOR: always - RUST_BACKTRACE: 1 - -jobs: - # lints - check: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Checking for whitespace errors (PRs only) - if: github.event.pull_request.base.sha - run: | - git diff --check "${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}" || { - echo >&2 "Your pull request introduces whitespace errors,"; - echo >&2 "which is not allowed. Please run:"; - echo >&2; - echo >&2 " git rebase --whitespace=fix"; - echo >&2 " git push -f"; - echo >&2; - echo >&2 "to correct and resubmit."; - exit 1; - } - - - name: Checking for cargo-fmt errors - run: | - cargo fmt --check || { \ - echo >&2 "Your pull request does not conform to cargo-fmt"; - echo >&2 "Rust format, which is not allowed. Please run:"; - echo >&2; - echo >&2 " cargo fmt"; - echo >&2 " git commit -a --amend"; - echo >&2 " git push -f"; - echo >&2; - echo >&2 "to correct and resubmit. If \`cargo fmt\` touches"; - echo >&2 "code which is not part of your MR, please let us"; - echo >&2 "know in the comments."; - exit 1; - } - - # run `cargo vendor` and cache it - vendor_sources: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - - uses: actions/cache@v4 - name: Update crate cargo-vendor cache - id: vendor_cache - with: - path: | - .cargo - vendor - key: cargo-vendor-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - cargo-vendor - enableCrossOsArchive: true - - - uses: actions/cache@v4 - name: Update cargo registry cache - if: steps.vendor_cache.outputs.cache-hit != 'true' - with: - path: | - ~/.cargo/bin/ - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - key: ${{ runner.os }}-cargo-cache-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-cargo-cache - - - name: Vendor sources - if: steps.vendor_cache.outputs.cache-hit != 'true' - run: | - mkdir -p .cargo - mkdir -p vendor - cargo vendor --versioned-dirs --locked >.cargo/config.toml - - - name: Check compiler lints - run: cargo check --workspace - continue-on-error: true - - test_sameold: - strategy: - matrix: - os: [ubuntu-latest, windows-latest, macos-latest] - features: ['', 'chrono'] - - runs-on: ${{ matrix.os }} - - needs: vendor_sources - - env: - CARGO_NET_OFFLINE: "true" - - steps: - - uses: actions/checkout@v3 - - - name: Record environment - shell: bash - run: cargo version - - - uses: actions/cache/restore@v4 - name: Restore crate cargo-vendor cache - with: - path: | - .cargo - vendor - key: cargo-vendor-${{ hashFiles('**/Cargo.lock') }} - enableCrossOsArchive: true - fail-on-cache-miss: true - - - name: Build and test sameold - shell: bash - run: | - cargo test --frozen -p sameold --verbose --no-default-features --features "${{ matrix.features }}" - - test_samedec: - strategy: - matrix: - os: [ubuntu-latest, windows-latest, macos-latest] - - runs-on: ${{ matrix.os }} - - needs: vendor_sources - - env: - CARGO_NET_OFFLINE: "true" - - steps: - - uses: actions/checkout@v3 - - - name: Record environment - shell: bash - run: cargo version - - - uses: actions/cache/restore@v4 - name: Restore crate cargo-vendor cache - with: - path: | - .cargo - vendor - key: cargo-vendor-${{ hashFiles('**/Cargo.lock') }} - enableCrossOsArchive: true - fail-on-cache-miss: true - - - name: Build and unit-test samedec - shell: bash - run: | - cargo test --frozen -p samedec --verbose - - - name: Run integration tests - shell: bash - run: | - pushd sample && ./test.sh && popd - - - name: Cross-compile macOS target for x86_64 (apple only) - shell: bash - if: ${{ matrix.os == 'macos-latest' }} - run: | - rustup target add x86_64-apple-darwin && \ - cargo test --frozen -p samedec --verbose --target=x86_64-apple-darwin - - # Linux builds within our containerized release environment - test_samedec_containerized: - runs-on: ubuntu-latest - - needs: vendor_sources - - container: - image: ghcr.io/cbs228/sameold/builder/x86_64-unknown-linux-gnu:latest - credentials: - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - env: - CARGO_NET_OFFLINE: "true" - CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse - - steps: - - uses: actions/checkout@v3 - - - uses: actions/cache/restore@v4 - name: Restore crate cargo-vendor cache - with: - path: | - .cargo - vendor - key: cargo-vendor-${{ hashFiles('**/Cargo.lock') }} - enableCrossOsArchive: true - fail-on-cache-miss: true - - - name: Cross-compile and cross-test - run: cargo test --frozen --verbose - - - name: Run integration tests on debug-mode build - run: | - cargo run -p samedec -- --version && - cd sample && ./test.sh diff --git a/.github/workflows/rust_release.yml b/.github/workflows/workflow.yml similarity index 52% rename from .github/workflows/rust_release.yml rename to .github/workflows/workflow.yml index 1a898a9..78117cb 100644 --- a/.github/workflows/rust_release.yml +++ b/.github/workflows/workflow.yml @@ -1,9 +1,11 @@ -name: Release +name: Build and Release on: push: branches: [ "release/**", "develop", "staging/**" ] tags: [ "samedec-*" ] + pull_request: + branches: [ "develop" ] permissions: contents: write @@ -13,12 +15,46 @@ env: RUST_BACKTRACE: 1 jobs: - # run `cargo vendor` and cache it - vendor_sources: + # perform basic code quality checks, + # then run `cargo vendor` and cache it + check_and_vendor: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Checking for whitespace errors (PRs only) + if: github.event.pull_request.base.sha + run: | + git diff --check "${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}" || { + echo >&2 "Your pull request introduces whitespace errors,"; + echo >&2 "which is not allowed. Please run:"; + echo >&2; + echo >&2 " git rebase --whitespace=fix"; + echo >&2 " git push -f"; + echo >&2; + echo >&2 "to correct and resubmit."; + exit 1; + } + + - name: Checking for cargo-fmt errors (PRs only) + if: github.event.pull_request.base.sha + run: | + cargo fmt --check || { \ + echo >&2 "Your pull request does not conform to cargo-fmt"; + echo >&2 "Rust format, which is not allowed. Please run:"; + echo >&2; + echo >&2 " cargo fmt"; + echo >&2 " git commit -a --amend"; + echo >&2 " git push -f"; + echo >&2; + echo >&2 "to correct and resubmit. If \`cargo fmt\` touches"; + echo >&2 "code which is not part of your MR, please let us"; + echo >&2 "know in the comments."; + exit 1; + } - uses: actions/cache@v4 name: Update crate cargo-vendor cache @@ -27,9 +63,8 @@ jobs: path: | .cargo vendor - key: cargo-vendor-release-${{ hashFiles('**/Cargo.lock') }} + key: cargo-vendor-${{ hashFiles('**/Cargo.lock') }} restore-keys: | - cargo-vendor-release cargo-vendor enableCrossOsArchive: true @@ -42,9 +77,8 @@ jobs: ~/.cargo/registry/index/ ~/.cargo/registry/cache/ ~/.cargo/git/db/ - key: ${{ runner.os }}-cargo-cache-release-${{ hashFiles('**/Cargo.lock') }} + key: ${{ runner.os }}-cargo-cache-${{ hashFiles('**/Cargo.lock') }} restore-keys: | - ${{ runner.os }}-cargo-cache-release ${{ runner.os }}-cargo-cache - name: Vendor sources @@ -54,11 +88,54 @@ jobs: mkdir -p vendor cargo vendor --versioned-dirs --locked >.cargo/config.toml - # Linux builds, with Docker and qemu as required - release_linux: + # test sameold with all crate feature combinations, + # in our Linux container + test_sameold: + strategy: + matrix: + features: ['', 'chrono'] + + runs-on: ubuntu-latest + + needs: check_and_vendor + + container: + image: ghcr.io/cbs228/sameold/builder/x86_64-unknown-linux-gnu:latest + credentials: + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + env: + CARGO_NET_OFFLINE: "true" + CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse + + steps: + - uses: actions/checkout@v3 + + - name: Record environment + run: cargo version + + - uses: actions/cache/restore@v4 + name: Restore crate cargo-vendor cache + with: + path: | + .cargo + vendor + key: cargo-vendor-${{ hashFiles('**/Cargo.lock') }} + enableCrossOsArchive: true + fail-on-cache-miss: true + + - name: Build and test sameold + shell: bash + run: | + cargo test --frozen -p sameold --verbose --no-default-features --features "${{ matrix.features }}" + + # Test and release samedec on Linux, via containers + release_samedec_linux: runs-on: ubuntu-latest - needs: vendor_sources + needs: check_and_vendor + + name: linux-${{ matrix.target }} strategy: matrix: @@ -87,11 +164,15 @@ jobs: path: | .cargo vendor - key: cargo-vendor-release-${{ hashFiles('**/Cargo.lock') }} + key: cargo-vendor-${{ hashFiles('**/Cargo.lock') }} enableCrossOsArchive: true fail-on-cache-miss: true - - name: Cross-compile, cross-test, and install + - name: "debug: cross-compile and cross-test" + run: | + cargo test --offline --frozen --workspace + + - name: "release: cross-compile, cross-test, and install" run: | cargo test --offline --frozen --release --workspace && cargo install --offline --frozen --path=crates/samedec @@ -99,21 +180,20 @@ jobs: - name: Run integration tests on release-mode build run: | qemu-run-maybe samedec --version && - cd sample && - ./test.sh qemu-run-maybe samedec + ./sample/test.sh qemu-run-maybe samedec - name: Copy artifact run: | cp /install/bin/samedec /install/bin/samedec-${{ matrix.target }} - name: Store artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: samedec-${{ matrix.target }} path: /install/bin/samedec-${{ matrix.target }} retention-days: 3 - - name: Upload tagged release + - name: Upload tagged release (tags only) uses: svenstaro/upload-release-action@v2 if: startsWith(github.ref, 'refs/tags/samedec-') with: @@ -121,7 +201,7 @@ jobs: file: /install/bin/samedec-${{ matrix.target }} overwrite: true - - name: Update tag for nightly release + - name: Update tag for nightly release (develop-branch only) uses: richardsimko/update-tag@v1 if: github.ref == 'refs/heads/develop' with: @@ -129,7 +209,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Upload nightly release + - name: Upload nightly release (develop-branch only) uses: svenstaro/upload-release-action@v2 if: github.ref == 'refs/heads/develop' with: @@ -140,19 +220,40 @@ jobs: file: /install/bin/samedec-${{ matrix.target }} overwrite: true - # Win32 build, on whatever machine github has available - release_windows: - runs-on: windows-latest - - needs: vendor_sources + # MacOS and Windows builds + release_samedec_nonlinux: + strategy: + matrix: + include: + - os: windows-latest + os_short: windows + target: x86_64-pc-windows-msvc + rustflags: '-C strip=symbols -C target-feature=+crt-static' + dotexe: '.exe' + - os: macos-latest + os_short: macos + target: aarch64-apple-darwin + rustflags: '-C strip=symbols' + dotexe: '' + - os: macos-latest + os_short: macos + target: x86_64-apple-darwin + rustflags: '-C strip=symbols' + dotexe: '' + + runs-on: ${{ matrix.os }} + + name: ${{ matrix.os_short }}-${{ matrix.target }} + + needs: check_and_vendor env: - CARGO_BUILD_TARGET: x86_64-pc-windows-msvc + CARGO_BUILD_TARGET: ${{ matrix.target }} CARGO_NET_OFFLINE: "true" CARGO_INSTALL_ROOT: "install/" - RUSTFLAGS: '-C strip=symbols -C target-feature=+crt-static' - samedec_exe: 'install/bin/samedec.exe' - samedec_target_exe: install/bin/samedec-x86_64-pc-windows-msvc.exe + RUSTFLAGS: ${{ matrix.rustflags }} + samedec_exe: "install/bin/samedec${{ matrix.dotexe }}" + samedec_target_exe: "install/bin/samedec-${{ matrix.target}}${{ matrix.dotexe }}" steps: - uses: actions/checkout@v3 @@ -167,28 +268,30 @@ jobs: path: | .cargo vendor - key: cargo-vendor-release-${{ hashFiles('**/Cargo.lock') }} + key: cargo-vendor-${{ hashFiles('**/Cargo.lock') }} enableCrossOsArchive: true fail-on-cache-miss: true - - name: Build + - name: "debug: compile and test" shell: bash run: | - mkdir -p 'install' && - cargo build --offline --tests --frozen --release --workspace + rustup target add "${CARGO_BUILD_TARGET}" && + cargo test --offline --frozen --workspace - - name: Test and install + - name: "release: cross-compile, cross-test, and install" shell: bash run: | + mkdir -p "${CARGO_INSTALL_ROOT}" && + export PATH="$(realpath ${CARGO_INSTALL_ROOT})/bin:${PATH}" cargo test --offline --frozen --release --workspace && cargo install --offline --frozen --path=crates/samedec - - name: Run integration tests + - name: Run integration tests on release-mode build shell: bash run: | - pushd sample && - ./test.sh && - popd + export PATH="$(realpath ${CARGO_INSTALL_ROOT})/bin:${PATH}" + samedec --version && + pushd ./sample && ./test.sh samedec && popd - name: Copy artifact shell: bash @@ -196,13 +299,13 @@ jobs: cp "$samedec_exe" "$samedec_target_exe" - name: Store artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: samedec-${{ env.CARGO_BUILD_TARGET }} path: ${{ env.samedec_target_exe }} retention-days: 3 - - name: Upload tagged release + - name: Upload tagged release (tags only) uses: svenstaro/upload-release-action@v2 if: startsWith(github.ref, 'refs/tags/samedec-') with: @@ -210,91 +313,15 @@ jobs: file: ${{ env.samedec_target_exe }} overwrite: true - - name: Upload nightly release - uses: svenstaro/upload-release-action@v2 + - name: Update tag for nightly release (develop-branch only) + uses: richardsimko/update-tag@v1 if: github.ref == 'refs/heads/develop' with: - tag: "latest" - release_name: "Nightly Release" - body: "This is a rolling release built from the latest `develop` branch." - prerelease: true - file: ${{ env.samedec_target_exe }} - overwrite: true - - # MacOS build, aarch64 - release_macos: - runs-on: macos-latest - - needs: vendor_sources - - strategy: - matrix: - include: - - target: aarch64-apple-darwin - - target: x86_64-apple-darwin - - env: - CARGO_BUILD_TARGET: ${{ matrix.target }} - CARGO_NET_OFFLINE: "true" - CARGO_INSTALL_ROOT: "install/" - RUSTFLAGS: '-C strip=symbols' - samedec_exe: 'install/bin/samedec' - samedec_target_exe: install/bin/samedec-${{ matrix.target }} - - steps: - - uses: actions/checkout@v3 - - - name: Record environment - run: cargo version - - - uses: actions/cache/restore@v4 - name: Restore crate cargo-vendor cache - with: - path: | - .cargo - vendor - key: cargo-vendor-release-${{ hashFiles('**/Cargo.lock') }} - enableCrossOsArchive: true - fail-on-cache-miss: true - - - name: Build - run: | - mkdir -p 'install' && - rustup target add "$CARGO_BUILD_TARGET" && - cargo fetch --locked && - cargo build --offline --tests --frozen --release --workspace - - - name: Test and install - run: | - cargo test --offline --frozen --release --workspace && - cargo install --offline --frozen --path=crates/samedec - - - name: Run integration tests - run: | - pushd sample && - ./test.sh && - popd - - - name: Copy artifact - run: | - cp "$samedec_exe" "$samedec_target_exe" - - - name: Store artifact - uses: actions/upload-artifact@v3 - with: - name: samedec-${{ env.CARGO_BUILD_TARGET }} - path: ${{ env.samedec_target_exe }} - retention-days: 3 - - - name: Upload tagged release - uses: svenstaro/upload-release-action@v2 - if: startsWith(github.ref, 'refs/tags/samedec-') - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - file: ${{ env.samedec_target_exe }} - overwrite: true + tag_name: latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Upload nightly release + - name: Upload nightly release (develop-only) uses: svenstaro/upload-release-action@v2 if: github.ref == 'refs/heads/develop' with: