ci: use Node 24 artifact uploader #976
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: {} | |
| pull_request: | |
| branches: [main] | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| # A newer main push must not cancel an older run once that run can enter publication. Branch and | |
| # pull-request runs still supersede older work for the same ref. | |
| cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} | |
| permissions: | |
| contents: read | |
| env: | |
| NODE_VERSION: "22.23.1" | |
| NPM_VERSION: "10.9.8" | |
| HAXE_VERSION: "4.3.7" | |
| jobs: | |
| security: | |
| name: Locked dependency + secret audit | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout full history for secret scanning | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup exact Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: Observe affected-test recommendation without changing CI coverage | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }} | |
| run: node scripts/ci/change-impact-selector.js --base "$BASE_SHA" --head "$GITHUB_SHA" | |
| - name: Setup exact Ruby and RubyGems for advisory scanning | |
| uses: ruby/setup-ruby@a30dfa457ad68707b8b910ac3a244714b61c0626 # v1.320.0 | |
| with: | |
| ruby-version: "3.4.10" | |
| rubygems: "3.6.9" | |
| bundler: none | |
| - name: Audit locked Node and Ruby dependencies | |
| run: | | |
| set -euo pipefail | |
| test "$(node --version)" = "v${NODE_VERSION}" | |
| test "$(npm --version)" = "${NPM_VERSION}" | |
| test "$(ruby --disable-gems -e 'print RUBY_VERSION')" = "3.4.10" | |
| test "$(gem --version)" = "3.6.9" | |
| npm ci --ignore-scripts --no-audit --no-fund | |
| npm audit | |
| gem install bundler-audit --version 0.9.3 --no-document | |
| npm run security:ruby-advisories | |
| - name: Scan full Git history for secrets | |
| uses: gitleaks/gitleaks-action@e0c47f4f8be36e29cdc102c57e68cb5cbf0e8d1e # v3 | |
| env: | |
| GITHUB_TOKEN: ${{ github.token }} | |
| haxe-format: | |
| name: Haxe formatter | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: Install npm dependencies | |
| run: npm ci --ignore-scripts --no-audit --no-fund | |
| - name: Install Haxe (pinned via lix) | |
| run: | | |
| set -euo pipefail | |
| npx lix download | |
| npx lix download haxe "${{ env.HAXE_VERSION }}" | |
| npx lix use haxe "${{ env.HAXE_VERSION }}" | |
| echo "$(pwd)/node_modules/.bin" >> "$GITHUB_PATH" | |
| export PATH="$(pwd)/node_modules/.bin:$PATH" | |
| haxe -version | |
| - name: Install Haxe formatter | |
| run: haxelib install formatter --quiet | |
| - name: Check Haxe formatting | |
| run: npm run format:haxe:check | |
| node-compatibility: | |
| name: Node.js compatibility / ${{ matrix.node_version }} | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| node_version: ["22.14.0", "22.23.1"] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: ${{ matrix.node_version }} | |
| - name: Verify Node.js and npm compatibility | |
| run: | | |
| set -euo pipefail | |
| test "$(node --version)" = "v${{ matrix.node_version }}" | |
| case "${{ matrix.node_version }}" in | |
| 22.14.0) test "$(npm --version)" = "10.9.2" ;; | |
| 22.23.1) test "$(npm --version)" = "10.9.8" ;; | |
| *) exit 1 ;; | |
| esac | |
| npm ci --ignore-scripts --no-audit --no-fund | |
| npm run ci:support-matrix | |
| npm run ci:version-sync | |
| npm run test:release-version-policy | |
| npm run test:release-workflow | |
| npm run test:release-hosting | |
| test: | |
| name: Ruby ${{ matrix.ruby_version }} / Haxe 4.3.7 | |
| runs-on: ubuntu-24.04 | |
| # This lane runs the full compiler, RailsHx, generator, snapshot, and package | |
| # suite across Ruby versions. Keep the cap above normal runtime so GitHub | |
| # does not cancel healthy runs while late snapshot/package checks are active. | |
| timeout-minutes: 45 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| ruby_version: ["3.3", "3.4", "4.0"] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: Setup Ruby | |
| uses: ruby/setup-ruby@a30dfa457ad68707b8b910ac3a244714b61c0626 # v1.320.0 | |
| with: | |
| ruby-version: ${{ matrix.ruby_version }} | |
| - name: Install npm dependencies | |
| run: npm ci --ignore-scripts --no-audit --no-fund | |
| - name: Install Haxe (pinned via lix) | |
| run: | | |
| set -euo pipefail | |
| npx lix download | |
| npx lix download haxe "${{ env.HAXE_VERSION }}" | |
| npx lix use haxe "${{ env.HAXE_VERSION }}" | |
| echo "$(pwd)/node_modules/.bin" >> "$GITHUB_PATH" | |
| export PATH="$(pwd)/node_modules/.bin:$PATH" | |
| haxe -version | |
| - name: Run full test suite | |
| run: npm test | |
| rails-browser: | |
| name: RailsHx browser sentinel | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: Setup Ruby | |
| uses: ruby/setup-ruby@a30dfa457ad68707b8b910ac3a244714b61c0626 # v1.320.0 | |
| with: | |
| ruby-version: "3.3" | |
| - name: Install npm dependencies | |
| run: npm ci --ignore-scripts --no-audit --no-fund | |
| - name: Install Haxe (pinned via lix) | |
| run: | | |
| set -euo pipefail | |
| npx lix download | |
| npx lix download haxe "${{ env.HAXE_VERSION }}" | |
| npx lix use haxe "${{ env.HAXE_VERSION }}" | |
| echo "$(pwd)/node_modules/.bin" >> "$GITHUB_PATH" | |
| export PATH="$(pwd)/node_modules/.bin:$PATH" | |
| haxe -version | |
| - name: Install Playwright Chromium | |
| run: ./node_modules/.bin/playwright install --with-deps chromium | |
| - name: Run RailsHx Playwright sentinel | |
| run: npm run test:todoapp-playwright | |
| rails-runtime: | |
| name: RailsHx runtime integration / Ruby ${{ matrix.ruby_version }} | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 20 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| ruby_version: ["3.3", "3.4", "4.0"] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: Setup Ruby | |
| uses: ruby/setup-ruby@a30dfa457ad68707b8b910ac3a244714b61c0626 # v1.320.0 | |
| with: | |
| ruby-version: ${{ matrix.ruby_version }} | |
| - name: Install npm dependencies | |
| run: npm ci --ignore-scripts --no-audit --no-fund | |
| - name: Install Haxe (pinned via lix) | |
| run: | | |
| set -euo pipefail | |
| npx lix download | |
| npx lix download haxe "${{ env.HAXE_VERSION }}" | |
| npx lix use haxe "${{ env.HAXE_VERSION }}" | |
| echo "$(pwd)/node_modules/.bin" >> "$GITHUB_PATH" | |
| export PATH="$(pwd)/node_modules/.bin:$PATH" | |
| haxe -version | |
| - name: Run mandatory Rails runtime lanes | |
| run: npm run test:rails-runtime | |
| rails-production: | |
| name: RailsHx production dogfood | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 25 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: Setup Ruby | |
| uses: ruby/setup-ruby@a30dfa457ad68707b8b910ac3a244714b61c0626 # v1.320.0 | |
| with: | |
| ruby-version: "3.3" | |
| - name: Install npm dependencies | |
| run: npm ci --ignore-scripts --no-audit --no-fund | |
| - name: Install Haxe (pinned via lix) | |
| run: | | |
| set -euo pipefail | |
| npx lix download | |
| npx lix download haxe "${{ env.HAXE_VERSION }}" | |
| npx lix use haxe "${{ env.HAXE_VERSION }}" | |
| echo "$(pwd)/node_modules/.bin" >> "$GITHUB_PATH" | |
| export PATH="$(pwd)/node_modules/.bin:$PATH" | |
| haxe -version | |
| - name: Run RailsHx production dogfood | |
| run: npm run test:todoapp-production | |
| - name: Measure stable viability workloads | |
| run: npm run benchmark:stable -- --require-rails | |
| release-contracts: | |
| name: Release contracts | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: Setup Ruby for public upgrade rehearsal | |
| uses: ruby/setup-ruby@a30dfa457ad68707b8b910ac3a244714b61c0626 # v1.320.0 | |
| with: | |
| ruby-version: "3.4.10" | |
| rubygems: "3.6.9" | |
| bundler: none | |
| - name: Install npm dependencies | |
| run: npm ci --ignore-scripts --no-audit --no-fund | |
| - name: Install exact Haxe toolchain for artifact contracts | |
| run: | | |
| set -euo pipefail | |
| # Haxe's install hook invokes `lix` by name, so the local binary must be visible | |
| # to child processes before either download begins. | |
| export PATH="$(pwd)/node_modules/.bin:$PATH" | |
| echo "$(pwd)/node_modules/.bin" >> "$GITHUB_PATH" | |
| ./node_modules/.bin/lix download | |
| ./node_modules/.bin/lix download haxe "${HAXE_VERSION}" | |
| ./node_modules/.bin/lix use haxe "${HAXE_VERSION}" | |
| test "$(haxe -version)" = "${HAXE_VERSION}" | |
| - name: Check version and release metadata | |
| run: | | |
| node scripts/ci/version-sync-check.js | |
| npm run test:release-version-policy | |
| npm run ci:release-contracts | |
| - name: Exercise public v0.4.0 upgrade and rollback | |
| run: npm run test:public-upgrade | |
| change-impact-observation: | |
| name: Change-impact observation | |
| needs: | |
| - security | |
| - haxe-format | |
| - node-compatibility | |
| - test | |
| - rails-browser | |
| - rails-runtime | |
| - rails-production | |
| - release-contracts | |
| # Run even when a backstop fails so the advisory report can distinguish an | |
| # omitted failure from an incomplete (cancelled/skipped) observation. | |
| if: ${{ always() }} | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 5 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout full history for change classification | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup exact Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: Correlate recommendations with unchanged full backstops | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }} | |
| CI_NEEDS_JSON: ${{ toJSON(needs) }} | |
| run: node scripts/ci/change-impact-observation.js --base "$BASE_SHA" --head "$GITHUB_SHA" | |
| - name: Retain the machine-readable observation for review | |
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 | |
| with: | |
| name: change-impact-observation-${{ github.run_id }}-${{ github.run_attempt }} | |
| path: test/.generated/change-impact/observation.json | |
| if-no-files-found: error | |
| include-hidden-files: true | |
| retention-days: 30 | |
| release: | |
| name: Release exact CI-tested commit | |
| needs: | |
| - security | |
| - haxe-format | |
| - node-compatibility | |
| - test | |
| - rails-browser | |
| - rails-runtime | |
| - rails-production | |
| - release-contracts | |
| - change-impact-observation | |
| # Referencing a status function disables GitHub's implicit success() filter. Every declared | |
| # dependency is then checked explicitly, so skipped/missing/failed/cancelled lanes still fail | |
| # closed while a scheduler-level aggregate status cannot silently skip an all-green release. | |
| if: >- | |
| ${{ | |
| !cancelled() | |
| && github.event_name == 'push' | |
| && github.ref == 'refs/heads/main' | |
| && github.repository == 'fullofcaffeine/reflaxe.ruby' | |
| && needs.security.result == 'success' | |
| && needs.haxe-format.result == 'success' | |
| && needs.node-compatibility.result == 'success' | |
| && needs.test.result == 'success' | |
| && needs.rails-browser.result == 'success' | |
| && needs.rails-runtime.result == 'success' | |
| && needs.rails-production.result == 'success' | |
| && needs.release-contracts.result == 'success' | |
| && needs.change-impact-observation.result == 'success' | |
| }} | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| permissions: | |
| contents: write | |
| concurrency: | |
| # The repair-only workflow added by the hosted-verification slice must use this exact group. | |
| group: release-${{ github.repository }} | |
| cancel-in-progress: false | |
| steps: | |
| - name: Checkout exact tested commit with full history | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.sha }} | |
| - name: Setup exact Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: "22.23.1" | |
| # setup-node v7 otherwise auto-enables npm caching when packageManager is declared. | |
| package-manager-cache: false | |
| - name: Setup exact Ruby and RubyGems | |
| uses: ruby/setup-ruby@a30dfa457ad68707b8b910ac3a244714b61c0626 # v1.320.0 | |
| with: | |
| ruby-version: "3.4.10" | |
| rubygems: "3.6.9" | |
| bundler: none | |
| - name: Verify exact release toolchain | |
| run: | | |
| set -euo pipefail | |
| test "$(node --version)" = "v22.23.1" | |
| test "$(npm --version)" = "10.9.8" | |
| test "$(ruby --disable-gems -e 'print RUBY_VERSION')" = "3.4.10" | |
| test "$(gem --version)" = "3.6.9" | |
| - name: Install and audit locked npm dependencies | |
| run: | | |
| set -euo pipefail | |
| npm ci --ignore-scripts --no-audit --no-fund | |
| npm audit | |
| - name: Install exact Haxe toolchain | |
| run: | | |
| set -euo pipefail | |
| # Haxe's install hook invokes `lix` by name, so the local binary must be visible | |
| # to child processes before either download begins. | |
| export PATH="$(pwd)/node_modules/.bin:$PATH" | |
| echo "$(pwd)/node_modules/.bin" >> "$GITHUB_PATH" | |
| ./node_modules/.bin/lix download | |
| ./node_modules/.bin/lix download haxe "4.3.7" | |
| ./node_modules/.bin/lix use haxe "4.3.7" | |
| test "$(haxe -version)" = "4.3.7" | |
| - name: Prepare historical prerelease transition | |
| run: node scripts/release/prepare-semver-transition.mjs | |
| - name: Derive, package, tag, and publish the tested SHA | |
| env: | |
| GITHUB_TOKEN: ${{ github.token }} | |
| GH_TOKEN: ${{ github.token }} | |
| run: ./node_modules/.bin/semantic-release |