From 01d8e4347faeb42865af660b0689cad6e53462cd Mon Sep 17 00:00:00 2001 From: Zhengchao An Date: Sat, 12 Sep 2026 11:26:12 +0800 Subject: [PATCH] fix(ci): bind nightly lanes to one resolved source (#7688) --- .github/workflows/nightly-gnu.yml | 32 +++++++++++++++++++++++++++---- scripts/test_nightly_candidate.py | 20 ++++++++++++++++--- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/.github/workflows/nightly-gnu.yml b/.github/workflows/nightly-gnu.yml index 868ccbaa6..4809d3b42 100644 --- a/.github/workflows/nightly-gnu.yml +++ b/.github/workflows/nightly-gnu.yml @@ -42,18 +42,39 @@ env: NIGHTLY_BUILD_REF: ${{ github.event_name == 'schedule' && (vars.NIGHTLY_BRANCH || 'main') || (inputs.branch || github.ref_name) }} jobs: + resolve-source: + name: Resolve nightly source + runs-on: ubuntu-latest + timeout-minutes: 10 + outputs: + source_sha: ${{ steps.source.outputs.sha }} + source_ref: ${{ steps.source.outputs.ref }} + steps: + - name: Checkout selected source + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 + with: + persist-credentials: false + ref: ${{ env.NIGHTLY_BUILD_REF }} + - name: Record immutable source + id: source + run: | + echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + echo "ref=${NIGHTLY_BUILD_REF}" >> "$GITHUB_OUTPUT" + build: + needs: resolve-source name: Build x86_64 GNU runs-on: sm-standard-4 timeout-minutes: 150 env: + NIGHTLY_BUILD_REF: ${{ needs.resolve-source.outputs.source_ref }} FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" steps: - name: Checkout repository uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 with: persist-credentials: false - ref: ${{ env.NIGHTLY_BUILD_REF }} + ref: ${{ needs.resolve-source.outputs.source_sha }} - name: Setup Rust environment uses: ./.github/actions/setup @@ -334,9 +355,10 @@ jobs: CANDIDATE_FILE="${RUNNER_TEMP}/nightly-candidate-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}.json" jq -n --arg source_sha "${SOURCE_SHA}" \ + --arg workflow_sha "${GITHUB_SHA}" --arg source_ref "${NIGHTLY_BUILD_REF}" \ --argjson build_run_id "${GITHUB_RUN_ID}" --argjson build_run_attempt "${GITHUB_RUN_ATTEMPT}" \ --arg package_url "${CANDIDATE_URL}" --arg package_sha256 "${DEB_SHA256}" \ - '{schema: 1, source_sha: $source_sha, build_run_id: $build_run_id, build_run_attempt: $build_run_attempt, package_url: $package_url, package_sha256: $package_sha256}' \ + '{schema: 2, workflow_sha: $workflow_sha, source_ref: $source_ref, source_sha: $source_sha, build_run_id: $build_run_id, build_run_attempt: $build_run_attempt, package_url: $package_url, package_sha256: $package_sha256}' \ > "${CANDIDATE_FILE}" echo "candidate_file=${CANDIDATE_FILE}" >> "${GITHUB_OUTPUT}" @@ -378,6 +400,7 @@ jobs: # self-hosted fleet is heterogeneous — a docker-dependent workflow has been # burned by it before (see the banner in e2e-s3tests.yml, rustfs/backlog#1149). kms-vault-lane: + needs: resolve-source name: KMS live Vault lane runs-on: ubuntu-latest timeout-minutes: 90 @@ -399,7 +422,7 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 with: persist-credentials: false - ref: ${{ env.NIGHTLY_BUILD_REF }} + ref: ${{ needs.resolve-source.outputs.source_sha }} - name: Setup Rust environment uses: ./.github/actions/setup @@ -477,6 +500,7 @@ jobs: # flake cannot mask the main lane's verdict, and vice versa. The script # provisions and tears down its own Docker cluster. kms-vault-ha-failover: + needs: resolve-source name: KMS Vault HA failover lane runs-on: ubuntu-latest timeout-minutes: 60 @@ -488,7 +512,7 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 with: persist-credentials: false - ref: ${{ env.NIGHTLY_BUILD_REF }} + ref: ${{ needs.resolve-source.outputs.source_sha }} - name: Setup Rust environment uses: ./.github/actions/setup diff --git a/scripts/test_nightly_candidate.py b/scripts/test_nightly_candidate.py index a1dca2405..9821300bb 100644 --- a/scripts/test_nightly_candidate.py +++ b/scripts/test_nightly_candidate.py @@ -96,7 +96,7 @@ SH ''') self.env = dict(os.environ, BASH_ENV=str(self.shims), DEB_FILE=self.package.name, R2_ACCESS_KEY_ID="fake-access", R2_SECRET_ACCESS_KEY="fake-secret", R2_ENDPOINT="https://r2.example.invalid", R2_BUCKET="test-bucket", - RUNNER_TEMP=str(self.root), GITHUB_SHA=self.sha, GITHUB_RUN_ID="12345", GITHUB_RUN_ATTEMPT="1", GITHUB_OUTPUT=str(self.output), + RUNNER_TEMP=str(self.root), GITHUB_SHA=self.sha, NIGHTLY_BUILD_REF="main", GITHUB_RUN_ID="12345", GITHUB_RUN_ATTEMPT="1", GITHUB_OUTPUT=str(self.output), FAKE_STORE=str(self.store), FAKE_AWS_LOG=str(self.root / "aws.log"), FAKE_CURL_LOG=str(self.root / "curl.log"), FAKE_INSTALLED=str(self.root / "installed"), FAKE_MODE="success") source = WORKFLOW.read_text() job = yaml_block(source.splitlines(), "build", 2) @@ -123,7 +123,7 @@ SH result = self.run_publish() self.assertEqual(result.returncode, 0, result.stderr) manifest = self.manifest() - self.assertEqual(manifest, {"schema": 1, "source_sha": self.sha, "build_run_id": 12345, "build_run_attempt": 1, + self.assertEqual(manifest, {"schema": 2, "workflow_sha": self.sha, "source_ref": "main", "source_sha": self.sha, "build_run_id": 12345, "build_run_attempt": 1, "package_sha256": self.digest, "package_url": f"https://dl.rustfs.com/artifacts/rustfs/packages/nightly/runs/12345/1/{self.digest}/rustfs.deb"}) for path in (f"runs/12345/1/{self.digest}/rustfs.deb", self.package.name, "rustfs-nightly-latest.deb"): self.assertEqual((self.store / "artifacts/rustfs/packages/nightly" / path).read_bytes(), self.package.read_bytes()) @@ -167,9 +167,23 @@ SH # With a ref override (NIGHTLY_BRANCH variable / dispatch `branch` # input) the checked-out HEAD intentionally differs from GITHUB_SHA; # the candidate manifest must record the tree that was built. - result = self.run_publish(GITHUB_SHA="f" * 40) + result = self.run_publish(GITHUB_SHA="f" * 40, NIGHTLY_BUILD_REF="release") self.assertEqual(result.returncode, 0, result.stderr) self.assertEqual(self.manifest()["source_sha"], self.sha) + self.assertEqual(self.manifest()["workflow_sha"], "f" * 40) + self.assertEqual(self.manifest()["source_ref"], "release") + + def test_every_lane_uses_the_same_resolved_source(self): + lines = WORKFLOW.read_text().splitlines() + resolver = "\n".join(yaml_block(lines, "resolve-source", 2)) + self.assertIn("ref: ${{ env.NIGHTLY_BUILD_REF }}", resolver) + self.assertIn('git rev-parse HEAD', resolver) + for lane in ("build", "kms-vault-lane", "kms-vault-ha-failover"): + with self.subTest(lane=lane): + job = "\n".join(yaml_block(lines, lane, 2)) + self.assertIn("needs: resolve-source", job) + self.assertIn("ref: ${{ needs.resolve-source.outputs.source_sha }}", job) + self.assertNotIn("ref: ${{ env.NIGHTLY_BUILD_REF }}", job) def test_same_date_builds_and_reruns_keep_distinct_candidates(self): urls = []