diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 63c555f63..5f39fe992 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -50,12 +50,18 @@ on: - "**/*.svg" - ".gitignore" - ".dockerignore" + - "flake.lock" schedule: - cron: "0 1 * * 0" # Weekly on Sunday 01:00 UTC (staggered after the ci.yml midnight cron) workflow_dispatch: inputs: build_docker: - description: "Build and push Docker images after binary build" + # Advisory only. docker.yml triggers on workflow_run and its job-level + # condition requires the triggering event to be a tag push, so a manual + # dispatch of this workflow never produces images regardless of this + # value. Kept because the summary step reports it; wiring it up would + # mean teaching docker.yml's version parser a second event shape. + description: "Build and push Docker images after binary build (ignored: dispatch runs never reach docker.yml)" required: false default: true type: boolean diff --git a/.github/workflows/ci-docs-only.yml b/.github/workflows/ci-docs-only.yml index 01e0db124..cdb9de7e0 100644 --- a/.github/workflows/ci-docs-only.yml +++ b/.github/workflows/ci-docs-only.yml @@ -53,6 +53,7 @@ on: - ".github/workflows/build.yml" - ".github/workflows/docker.yml" - ".github/workflows/audit.yml" + - "flake.lock" permissions: contents: read @@ -110,6 +111,8 @@ jobs: - name: Check no planning docs committed run: ./scripts/check_no_planning_docs.sh + - name: Check CI paths stay in sync + run: ./scripts/check_ci_paths_sync.sh test-and-lint: name: Test and Lint diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e2a346cd0..085ed83a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,6 +33,7 @@ on: - ".github/workflows/build.yml" - ".github/workflows/docker.yml" - ".github/workflows/audit.yml" + - "flake.lock" pull_request: types: [ opened, synchronize, reopened, closed ] branches: [ main ] @@ -54,6 +55,7 @@ on: - ".github/workflows/build.yml" - ".github/workflows/docker.yml" - ".github/workflows/audit.yml" + - "flake.lock" merge_group: types: [ checks_requested ] schedule: @@ -142,6 +144,8 @@ jobs: - name: Check no planning docs committed run: ./scripts/check_no_planning_docs.sh + - name: Check CI paths stay in sync + run: ./scripts/check_ci_paths_sync.sh test-and-lint: name: Test and Lint diff --git a/.github/workflows/e2e-s3tests.yml b/.github/workflows/e2e-s3tests.yml index 23598e803..ce26fc235 100644 --- a/.github/workflows/e2e-s3tests.yml +++ b/.github/workflows/e2e-s3tests.yml @@ -45,6 +45,13 @@ # The PR gate (ci.yml s3-implemented-tests) is unaffected: it avoids Docker # via DEPLOY_MODE=binary and defers all pip setup to run.sh's self-bootstrap. +# DISABLED. This workflow is switched off in the repository's Actions settings +# (state: disabled_manually) and does not run on any trigger, including its cron +# and workflow_dispatch. That state lives in GitHub's UI and is invisible when +# reading this file, which has already misled at least one audit — hence this +# banner. Re-enabling is a UI action; anyone doing so should first check that the +# workflow still matches the current CI layout. See rustfs/backlog#1603. +# name: e2e-s3tests on: diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index 3fe5ab0de..1082da1de 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -12,6 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +# DISABLED. This workflow is switched off in the repository's Actions settings +# (state: disabled_manually) and does not run on any trigger, including its cron +# and workflow_dispatch. That state lives in GitHub's UI and is invisible when +# reading this file, which has already misled at least one audit — hence this +# banner. Re-enabling is a UI action; anyone doing so should first check that the +# workflow still matches the current CI layout. See rustfs/backlog#1603. +# name: Fuzz on: diff --git a/.github/workflows/issue-translator.yml b/.github/workflows/issue-translator.yml index 1bb98a956..04a57563d 100644 --- a/.github/workflows/issue-translator.yml +++ b/.github/workflows/issue-translator.yml @@ -12,6 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +# DISABLED. This workflow is switched off in the repository's Actions settings +# (state: disabled_manually) and does not run on any trigger, including its cron +# and workflow_dispatch. That state lives in GitHub's UI and is invisible when +# reading this file, which has already misled at least one audit — hence this +# banner. Re-enabling is a UI action; anyone doing so should first check that the +# workflow still matches the current CI layout. See rustfs/backlog#1603. +# name: "issue-translator" on: issue_comment: diff --git a/.github/workflows/minio-interop.yml b/.github/workflows/minio-interop.yml index 585dca543..b043b84a1 100644 --- a/.github/workflows/minio-interop.yml +++ b/.github/workflows/minio-interop.yml @@ -23,6 +23,13 @@ # Runner: GitHub-hosted `ubuntu-latest`. It reliably ships Docker + Python, # unlike the self-hosted fleet, whose pods drift in Docker/pip availability # (see the infra note in e2e-s3tests.yml). Nightly + manual only. +# DISABLED. This workflow is switched off in the repository's Actions settings +# (state: disabled_manually) and does not run on any trigger, including its cron +# and workflow_dispatch. That state lives in GitHub's UI and is invisible when +# reading this file, which has already misled at least one audit — hence this +# banner. Re-enabling is a UI action; anyone doing so should first check that the +# workflow still matches the current CI layout. See rustfs/backlog#1603. +# name: minio-interop on: diff --git a/.github/workflows/mint.yml b/.github/workflows/mint.yml index a7ca90658..20f449310 100644 --- a/.github/workflows/mint.yml +++ b/.github/workflows/mint.yml @@ -45,6 +45,13 @@ # docker-capable self-hosted `dind-sm-standard-2` label was the alternative but # has fewer cores and reintroduces fleet-state risk for no reliability gain. +# DISABLED. This workflow is switched off in the repository's Actions settings +# (state: disabled_manually) and does not run on any trigger, including its cron +# and workflow_dispatch. That state lives in GitHub's UI and is invisible when +# reading this file, which has already misled at least one audit — hence this +# banner. Re-enabling is a UI action; anyone doing so should first check that the +# workflow still matches the current CI layout. See rustfs/backlog#1603. +# name: mint on: diff --git a/.github/workflows/nix-flake-update.yml b/.github/workflows/nix-flake-update.yml index 9857d0b55..8a5ec5ba6 100644 --- a/.github/workflows/nix-flake-update.yml +++ b/.github/workflows/nix-flake-update.yml @@ -19,9 +19,12 @@ on: schedule: - cron: '0 5 * * 0' # Weekly on Sunday 05:00 UTC (staggered after the midnight ci/build crons) +# GITHUB_TOKEN only needs to read the repository here: the branch push and the +# pull request are both created by update-flake-lock using the +# FLAKE_UPDATE_TOKEN PAT below, not by this token. Leaving write on it hands a +# repo-write credential to an unattended weekly job that does not use it. permissions: - contents: write - pull-requests: write + contents: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 85829ef47..6dc80ef3d 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -12,6 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +# DISABLED. This workflow is switched off in the repository's Actions settings +# (state: disabled_manually) and does not run on any trigger, including its cron +# and workflow_dispatch. That state lives in GitHub's UI and is invisible when +# reading this file, which has already misled at least one audit — hence this +# banner. Re-enabling is a UI action; anyone doing so should first check that the +# workflow still matches the current CI layout. See rustfs/backlog#1603. +# name: Nix CI on: diff --git a/.github/workflows/performance-ab.yml b/.github/workflows/performance-ab.yml index 7a831303c..ad3e6f1c6 100644 --- a/.github/workflows/performance-ab.yml +++ b/.github/workflows/performance-ab.yml @@ -22,6 +22,13 @@ # a deliberate correctness cost (e.g. the #4221 fsync durability fix) is # recorded but does not block (rustfs/backlog#935 correction 1). +# DISABLED. This workflow is switched off in the repository's Actions settings +# (state: disabled_manually) and does not run on any trigger, including its cron +# and workflow_dispatch. That state lives in GitHub's UI and is invisible when +# reading this file, which has already misled at least one audit — hence this +# banner. Re-enabling is a UI action; anyone doing so should first check that the +# workflow still matches the current CI layout. See rustfs/backlog#1603. +# name: Performance A/B on: diff --git a/.github/workflows/schedule-failure-alert-drill.yml b/.github/workflows/schedule-failure-alert-drill.yml index 8154e1c79..648cfb94c 100644 --- a/.github/workflows/schedule-failure-alert-drill.yml +++ b/.github/workflows/schedule-failure-alert-drill.yml @@ -24,6 +24,13 @@ # The run itself is expected to end red (the forced failure); only the # alert-on-failure job result matters. +# DISABLED. This workflow is switched off in the repository's Actions settings +# (state: disabled_manually) and does not run on any trigger, including its cron +# and workflow_dispatch. That state lives in GitHub's UI and is invisible when +# reading this file, which has already misled at least one audit — hence this +# banner. Re-enabling is a UI action; anyone doing so should first check that the +# workflow still matches the current CI layout. See rustfs/backlog#1603. +# name: Schedule Failure Alert Drill on: diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 3152e720d..6eb903db8 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -12,6 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +# DISABLED. This workflow is switched off in the repository's Actions settings +# (state: disabled_manually) and does not run on any trigger, including its cron +# and workflow_dispatch. That state lives in GitHub's UI and is invisible when +# reading this file, which has already misled at least one audit — hence this +# banner. Re-enabling is a UI action; anyone doing so should first check that the +# workflow still matches the current CI layout. See rustfs/backlog#1603. +# name: "Mark stale issues" on: schedule: diff --git a/scripts/check_ci_paths_sync.sh b/scripts/check_ci_paths_sync.sh new file mode 100755 index 000000000..152129fd4 --- /dev/null +++ b/scripts/check_ci_paths_sync.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +# ci.yml's pull_request paths-ignore and ci-docs-only.yml's paths must be equal. +# +# ci-docs-only.yml exists to report the required checks for pull requests that +# ci.yml skips. The two lists are the complement of each other, so any drift +# breaks one of two ways, both silent: +# +# - an entry only in ci.yml's paths-ignore: a PR touching only those files +# triggers neither workflow, nobody reports "Test and Lint" or "Quick +# Checks", and the PR waits on a required check forever; +# - an entry only in ci-docs-only.yml's paths: both workflows run, which is +# merely wasteful — but it also means the lists no longer describe the same +# intent, and the next edit is made against a wrong assumption. +# +# The push paths-ignore in ci.yml is deliberately NOT compared: no required +# check is reported for push events, so it does not have to pair with anything. +# +# Also asserts ci-docs-only.yml still declares both companion job names, since a +# rename there produces exactly the permanent-pending failure above. +# +# Usage: scripts/check_ci_paths_sync.sh +set -euo pipefail + +cd "$(dirname "$0")/.." + +CI=".github/workflows/ci.yml" +DOCS=".github/workflows/ci-docs-only.yml" + +# Print the quoted list items that follow $2 within the block introduced by $1. +# Both files keep these as a flat list of quoted scalars, so no YAML parser is +# needed and the script stays dependency-free like its check_* siblings. +extract() { + local file="$1" event="$2" key="$3" + awk -v event="$event" -v key="$key" ' + $0 ~ "^ " event ":[[:space:]]*$" { in_event = 1; next } + in_event && /^ [a-z_]+:[[:space:]]*$/ { in_event = 0 } + in_event && $0 ~ "^ " key ":[[:space:]]*$" { in_list = 1; next } + in_list { + if ($0 ~ /^ - /) { + item = $0 + sub(/^ - /, "", item) + gsub(/^"|"$/, "", item) + print item + next + } + if ($0 !~ /^[[:space:]]*#/ && $0 !~ /^[[:space:]]*$/) in_list = 0 + } + ' "$file" | sort +} + +ci_list="$(extract "$CI" "pull_request" "paths-ignore")" +docs_list="$(extract "$DOCS" "pull_request" "paths")" + +if [ -z "$ci_list" ] || [ -z "$docs_list" ]; then + echo "ERROR: could not read one of the path lists — did the file structure change?" >&2 + echo " $CI pull_request.paths-ignore: $(printf '%s' "$ci_list" | grep -c . || true) entries" >&2 + echo " $DOCS pull_request.paths: $(printf '%s' "$docs_list" | grep -c . || true) entries" >&2 + exit 1 +fi + +status=0 + +if ! diff_out="$(diff <(printf '%s\n' "$ci_list") <(printf '%s\n' "$docs_list"))"; then + echo "ERROR: $CI pull_request paths-ignore and $DOCS paths have drifted." >&2 + echo " '<' is only in $CI, '>' is only in $DOCS:" >&2 + printf '%s\n' "$diff_out" | sed 's/^/ /' >&2 + status=1 +fi + +for job_name in "Test and Lint" "Quick Checks"; do + if ! grep -q "name: ${job_name}\$" "$DOCS"; then + echo "ERROR: $DOCS no longer declares a job named '${job_name}'." >&2 + echo " It is a required status check; without a companion job here, a" >&2 + echo " docs-only PR waits on it forever." >&2 + status=1 + fi +done + +if [ "$status" -ne 0 ]; then + exit 1 +fi + +echo "OK: ci.yml and ci-docs-only.yml path lists agree ($(printf '%s\n' "$ci_list" | wc -l | tr -d ' ') entries)"