Skip to content
Open
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
86 changes: 76 additions & 10 deletions .github/workflows/agent-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ jobs:
runs-on: ${{ github.repository_owner == 'intel' && github.event_name == 'pull_request' && 'dokimi-ec2' || 'ubuntu-latest' }}
permissions:
contents: read
# The changes step reads this workflow's earlier runs (gh api).
actions: read
timeout-minutes: 15
env:
# Pinned, not `main` -- an upstream rename/restructure of
Expand All @@ -64,24 +66,72 @@ jobs:
with:
persist-credentials: false
fetch-depth: 0
# Whether a PR changes anything besides Markdown. A docs-only PR skips the
# steps below (the Docker smoke test cannot be affected by it); the benchmark
# job measures the docs, so it always runs. The job itself still takes a
# runner, as its steps are skipped, not the job.
# Docs-only runs skip the code steps (the benchmark still runs). A push diffs from the last verified smoke run, else all; docs are the Markdown in DOCS below.
# dokimi/data/, tests and .agent-eval count as code, and a base that moved since that run's merge also runs everything. Force pushes run all.
- id: changes
working-directory: .
# Explicit, so the step runs as `bash --noprofile --norc -eo pipefail`, the flags the test harness uses.
shell: bash
env:
EVENT: ${{ github.event_name }}
ACTION: ${{ github.event.action }}
BASE_REF: ${{ github.event.pull_request.base.ref }}
HEAD_REF: ${{ github.head_ref }}
REPO: ${{ github.repository }}
GH_TOKEN: ${{ github.token }}
BEFORE: ${{ github.event.before }}
AFTER: ${{ github.event.after }}
DOCS: '^([^/]+|dokimi/[^/]+|dokimi/docs/(.+/)?[^/]+|dokimi/changelog\.d/[^/]+|\.github/(.+/)?[^/]+)\.md$'
run: |
if [ "$EVENT" != pull_request ]; then echo code=true >> "$GITHUB_OUTPUT"; exit 0; fi
# The base branch's current tip (fetched by the checkout), not base.sha
# (the base when the PR was opened).
if git diff --name-only "origin/$BASE_REF"...HEAD | grep -qv '\.md$'; then
echo code=true >> "$GITHUB_OUTPUT"
set_code() { echo "code=$1" >> "$GITHUB_OUTPUT"; echo "changes: code=$1 ($2)"; }
# Newest commit reachable from AFTER whose smoke run passed (Verify pass rate succeeded): prints "<sha> <run id>",
# or nothing if none. An unreadable run list also prints nothing; the caller then runs everything.
last_verified() {
runs=$(gh api "repos/$REPO/actions/workflows/agent-quality.yml/runs" --method GET \
-f branch="$HEAD_REF" -f event=pull_request -f status=completed -f per_page=20 \
--jq '.workflow_runs[] | "\(.id) \(.head_sha)"') || return 0
while read -r id sha; do
[ -n "$id" ] || continue
git cat-file -e "$sha^{commit}" 2>/dev/null && git merge-base --is-ancestor "$sha" "$AFTER" 2>/dev/null || continue
verdict=$(gh api "repos/$REPO/actions/runs/$id/jobs" \
--jq '.jobs[] | select(.name | startswith("External catalog smoke test")) | .steps[] | select(.name == "Verify pass rate") | .conclusion') || continue
if [ "$verdict" = success ]; then echo "$sha $id"; return 0; fi
done <<< "$runs"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maintainability · low
Nit: declare shell: bash on the changes step. The new here-strings and ${from:0:7} expansion require Bash, but this step also runs on the self-hosted dokimi-ec2 runner without an explicit shell. GitHub's unspecified Linux shell can fall back to sh, which cannot parse these constructs. The new tests explicitly invoke Bash, so they do not cover that fallback.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 548027b.

The changes step now declares shell: bash. Its here-strings and ${from:0:7} need bash, and this also keeps the self-hosted runner off sh.

}
if [ "$EVENT" != pull_request ]; then set_code true "not a pull request"; exit 0; fi
# --no-renames: a rename from code to Markdown must count as the code it removes.
if [ "$ACTION" = synchronize ]; then
Comment thread
antonwolfy marked this conversation as resolved.
Resolved

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bug · medium
Must-fix: per-push scoping can leave code unchecked. Push A changes code and starts the smoke test. Push B, docs-only, arrives. The concurrency group has cancel-in-progress for PRs, so it cancels A's run. B's run sees only docs, skips every step and reports success. The head commit is green and the code from A never went through the Docker smoke test. If A's run had already failed, B's green run hides that failure in the same way. Fix: decide from the whole PR (base...HEAD) for every PR event, which is the old behaviour. If you want the per-push skip, apply it only when the previous run for BEFORE succeeded.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6c1ed98d: option 3. A docs-only push now skips the code steps only when everything since the newest commit whose smoke run passed its code steps is documentation.

What changed in .github/workflows/agent-quality.yml:

  • The changes step diffs from that passed commit, not from before. It finds the commit through the Actions API (actions: read on the smoke job): the newest completed run of this branch whose Verify pass rate step succeeded, reachable from the push.
  • A run that was cancelled by the next push, or that failed, does not count, so the code it carried runs again.
  • With no passed run, or an unreadable run list, everything runs.

Pinned by dokimi/tests/test_agent_quality_changes_scope.py. It runs the step as the workflow has it, with gh stubbed. Before the change, the cancelled-run, failed-run, no-passed-run and unreadable-API cases returned code=false. After it, all six scope cases and the permission check pass, including docs after a passed run (still skips).

The cancellation itself is GitHub's concurrency behaviour; I have not run this on Actions.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bug · medium
Per-push scoping can turn the check green without the code ever being smoke-tested. The concurrency group cancels the in-flight run on each new push. So code push A starts the smoke test, a docs-only push B cancels it, and B's run skips every step and reports success. The head commit then shows a green check although the Docker smoke test never passed on that code. The same happens if A's run had already failed and B is docs-only. Required checks are not enforced today, so this is not blocking, but the result is misleading. Options: keep the whole-PR scope for the smoke job (base...HEAD), or only use push scope when the previous run for BEFORE succeeded.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6c1ed98 (already on this branch): a docs-only push skips the code steps only after the newest passed smoke run, and cancelled or failed runs do not count. The cancelled, failed, no-passed-run and unreadable-API scenarios in test_agent_quality_changes_scope.py pin it (18 passed on 7d654b3).

if ! { [ -n "$BEFORE" ] && [ -n "$AFTER" ] \
&& git cat-file -e "$BEFORE^{commit}" && git cat-file -e "$AFTER^{commit}" \
&& git merge-base --is-ancestor "$BEFORE" "$AFTER"; } 2>/dev/null; then
set_code true "force push, or the commits are not fetched"; exit 0
fi
# Diffed from the last passed run's commit, not from BEFORE: a run this push
# cancelled or that failed verified nothing, so its code is diffed again.
read -r from verified_run <<< "$(last_verified)" || true
if [ -z "$from" ]; then set_code true "push: no passed smoke run to diff from"; exit 0; fi
# The diff above does not show base changes: the run tested its merge with the base it was built on.
# Skip only if origin/$BASE_REF is still that base (the smoke job records it; no record means run everything).
dl=$(mktemp -d)
tested_base=$(gh run download "$verified_run" -R "$REPO" -n external-catalog-smoke-runs -D "$dl" >/dev/null 2>&1 && cat "$dl/base.sha") || tested_base=
base=$(git rev-parse --verify -q "origin/$BASE_REF") || base=
if [ -z "$tested_base" ] || [ "$tested_base" != "$base" ]; then
set_code true "push: the base moved since ${from:0:7}, or that run did not record it"; exit 0
fi
scope="push since ${from:0:7}"
files=$(git -c core.quotepath=false diff --no-renames --name-only "$from" "$AFTER") \

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bug · medium
Must-fix: this diff ignores changes to the PR's base branch since the successful smoke run. Checkout uses the default PR merge commit, so if V passes against main=M1, main then receives a code change M2, and the PR pushes only README.md, V..AFTER contains only docs and this job skips testing the new merge with M2. Head ancestry alone does not establish that the checked-out code was verified. Record/validate the base revision (or compare the previously tested merge tree with the current checkout) before allowing the skip, and add a scenario where the base changes between the successful run and the docs-only push.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 548027b, and the base it records is corrected in af61af9.

Agreed. A docs-only push diffs from the last passed run's commit, but the checkout is the merge with the base as it was when the merge was built, so a base move after that run went untested. The smoke job records the first parent of its merge checkout (the base tip the merge was built on) in logs/external-catalog-smoke/base.sha, which goes into the run artifact, and only when that parent is on origin/<base>. The changes step downloads that file from the passed run and skips only if it equals the current origin/<base>. A missing record or a failed download runs the code.

New tests: a base-moved scenario and a no-record scenario, both code=true. The record step is tested on a merge built on an older base after main moved (it records the older base), on a PR head with a stale record (nothing recorded), and on a PR head that merges a PR commit (nothing recorded).

|| { set_code true "push diff failed"; exit 0; }
else
echo code=false >> "$GITHUB_OUTPUT"
# The base branch's current tip (fetched by the checkout), not the event's pull_request.base.sha
# (the base when the PR was opened).
scope=pr
files=$(git -c core.quotepath=false diff --no-renames --name-only "origin/$BASE_REF"...HEAD) \
|| { set_code true "PR diff failed"; exit 0; }
fi
if [ -z "$files" ]; then set_code true "$scope diff is empty"; exit 0; fi
# A here-string, not a pipe: grep -q may exit early, and under pipefail the pipe's printf would get SIGPIPE.
if grep -qvE "$DOCS" <<< "$files"; then set_code true "$scope changes code"; exit 0; fi
set_code false "$scope changes only documentation"
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
if: steps.changes.outputs.code == 'true'
with:
Expand Down Expand Up @@ -121,6 +171,22 @@ jobs:
--tasks-root "${{ runner.temp }}/uxl-skills/evaluation/harbor/tasks" \
--harnesses docker-oracle,docker-probe \
--out-json "${{ github.workspace }}/logs/external-catalog-smoke/runs.json"
# The base the merge commit (refs/pull/N/merge) was built on, its first parent; not origin/$BASE_REF, which may have moved since.
# A PR that does not merge records nothing. A later docs-only push skips only while origin/$BASE_REF is still this one.
- name: Record the base this run tested
if: steps.changes.outputs.code == 'true' && github.event_name == 'pull_request'
env:
BASE_REF: ${{ github.event.pull_request.base.ref }}
RECORD: ${{ github.workspace }}/logs/external-catalog-smoke/base.sha
run: |
# The checkout is the PR's merge commit; its first parent is the base tip the merge was built on.
# Recorded only if that parent is on origin/<base>; else nothing, so the next push runs everything.
rm -f "$RECORD"
if git rev-parse --verify -q HEAD^2 > /dev/null \
&& parent=$(git rev-parse --verify HEAD^1) \
&& git merge-base --is-ancestor "$parent" "origin/$BASE_REF"; then
echo "$parent" > "$RECORD"
fi
# Every cell passed and none errored (an errored cell leaves pass_rate's
# denominator, so pass_rate alone would read 1.0), and the probe's fetch
# was denied by the egress proxy; see scripts/check_smoke_runs.py.
Expand Down
Loading
Loading