Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .github/workflows/ci-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Regression guard for the flaky "Lint GitHub Actions" download in ci.yml
# (issue #894): every curl download in ci.yml must carry bounded retries so a
# transient GitHub Releases blip retries instead of failing the job.
# See test/workflows/ci/install-resilience.bats.
name: CI Workflow Tests

on:
pull_request:
paths:
- '.github/workflows/ci.yml'
- 'test/workflows/ci/**'
- '.github/workflows/ci-tests.yml'
push:
branches: [main]
paths:
- '.github/workflows/ci.yml'
- 'test/workflows/ci/**'
- '.github/workflows/ci-tests.yml'

permissions: {}

concurrency:
group: ci-tests-${{ github.ref }}
cancel-in-progress: true

jobs:
test:
name: bats
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
Comment thread
don-petry marked this conversation as resolved.
with:
persist-credentials: false

- name: Install bats
run: |
set -euo pipefail
for attempt in {1..3}; do
if sudo apt-get update -qq && sudo apt-get install -y --no-install-recommends bats; then
exit 0
fi
if [ "$attempt" -lt 3 ]; then
echo "Apt install failed, retrying in 5 seconds..." >&2
sleep 5
fi
done
echo "Apt install failed after 3 attempts" >&2
exit 1

Comment thread
qodo-code-review[bot] marked this conversation as resolved.
- name: bats
run: bats --print-output-on-failure test/workflows/ci/
9 changes: 8 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,14 @@ jobs:
# Install actionlint via verified download (pinned version + checksum)
ACTIONLINT_VERSION="1.7.7"
ACTIONLINT_SHA="023070a287cd8cccd71515fedc843f1985bf96c436b7effaecce67290e7e0757"
curl -sLo actionlint.tar.gz "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"
# Bounded retries so a transient GitHub Releases 5xx / connection blip
# retries instead of failing the job (guards the fleet failure-rate
# metric — see test/workflows/ci/install-resilience.bats, issue #894).
curl -sSfL --proto '=https' --proto-redir '=https' \
--connect-timeout 10 --max-time 60 \
--retry 3 --retry-delay 2 --retry-connrefused --retry-all-errors \
-o actionlint.tar.gz \
"https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"
echo "${ACTIONLINT_SHA} actionlint.tar.gz" | sha256sum -c -
tar xzf actionlint.tar.gz actionlint
chmod +x actionlint
Expand Down
10 changes: 10 additions & 0 deletions test/workflows/ci/helpers/setup.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
# Common test helpers for the ci.yml bats suite.
# Mirrors the pattern in test/workflows/pr-review-mention/helpers/setup.bash.

# Repo root, regardless of where bats is invoked from.
TT_REPO_ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../../../.." && pwd)"
export TT_REPO_ROOT

TT_WORKFLOW="${TT_REPO_ROOT}/.github/workflows/ci.yml"
export TT_WORKFLOW
52 changes: 52 additions & 0 deletions test/workflows/ci/install-resilience.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env bats
# Regression guard for the flaky "Lint GitHub Actions" step in
# .github/workflows/ci.yml.
#
# Pins issue #894: ci.yml intermittently fails (~14% of runs) because the pinned
# rhysd/actionlint binary is fetched from GitHub Releases — which redirects to
# objects.githubusercontent.com — with a bare `curl` that aborts on the first
# transient network/5xx blip. This is the same failure mode fixed for
# pr-review-mention-tests.yml under #739. AGENTS.md requires CI to be reliable;
# the one unavoidable network fetch must therefore retry on transient errors.
# These tests assert every download in ci.yml carries bounded curl retries, so a
# future edit can't silently reintroduce a bare download.

load 'helpers/setup'

@test "install: the ci workflow exists" {
[ -f "$TT_WORKFLOW" ]
}

@test "install: every curl download in ci.yml uses bounded retries" {
[ -f "$TT_WORKFLOW" ]

# Parse the workflow joining backslash-continued lines so that a curl command
# split across multiple lines is treated as a single logical invocation.
# This avoids false failures when flags appear on continuation lines, and
# avoids false passes when a bare `curl` is split from its flags.
local curls=()
local current=""
while IFS= read -r line || [[ -n "$line" ]]; do
line="${line%$'\r'}"
if [[ "$line" == *\\ ]]; then
current+="${line%\\} "
Comment thread
don-petry marked this conversation as resolved.
else
current+="$line"
if [[ "$current" == *curl* ]] && ! [[ "$current" =~ ^[[:space:]]*# ]] && ! [[ "$current" =~ ^[[:space:]]*-?[[:space:]]*(name|uses|with): ]]; then
curls+=("$current")
fi
current=""
fi
done < "$TT_WORKFLOW"

# At least one curl invocation must be present so the test remains meaningful.
[ "${#curls[@]}" -ge 1 ]
for cmd in "${curls[@]}"; do
# A finite retry budget (not unbounded) so a truly-down mirror still fails fast.
[[ "$cmd" =~ --retry[[:space:]=][1-9] ]]
# Retry on connection refused, which curl otherwise treats as non-transient.
[[ "$cmd" == *"--retry-connrefused"* ]]
# Retry on transient HTTP 5xx too, not just connection-level errors.
[[ "$cmd" == *"--retry-all-errors"* ]]
Comment thread
coderabbitai[bot] marked this conversation as resolved.
done
}
Loading