mirror of
https://github.com/docker/docker-agent.git
synced 2026-11-04 10:02:15 +00:00
Two independent improvements to the weekly models.dev snapshot refresh (.github/workflows/update-models.yml), which previously opened PRs with an unsigned commit attributed to whoever happened to trigger the run, and a static, uninformative PR body. Signed commits --------------- Add `sign-commits: true` to the existing `peter-evans/create-pull-request` step. This builds the commit through GitHub's API instead of a local `git push`, so it is Verified regardless of which token creates it. On the default `GITHUB_TOKEN` (used explicitly via `token: github.token` for clarity) the commit author/committer becomes `github-actions[bot]` consistently, rather than the human who happened to run the workflow. `persist-credentials: false` is set on checkout as a minor hardening measure, since `create-pull-request` is given its token explicitly and never needs checkout's persisted git credential. Semantic catalog diff, no AI ----------------------------- `pkg/modelsdev/snapshot.json` is a single-line, multi-megabyte JSON file, so its raw git diff is one useless line — this is why the PR body was static. Instead: - `.github/scripts/models-delta.jq` computes a structural added/removed/changed diff between two snapshot.json files. - `.github/scripts/models-delta-render.jq` renders that diff to markdown tables, with a `safe()`/`safe_diff()` sanitiser clamping every third-party (models.dev) string to a short, bounded, control-character-free charset before it reaches the PR body — that body is consumed by this repo's automated PR-review pipeline, so untrusted text needs bounding before it gets there. - `scripts/models-delta.sh` is the single wrapper around both jq scripts; a new `task models-delta` target and the workflow's "Compute catalog delta" step both call it, so the diff logic exists in exactly one place. With no arguments it diffs HEAD's pkg/modelsdev/snapshot.json against the working tree — the same comparison the workflow makes after `task update-models`, so the local and CI code paths never drift apart. - The workflow uses the rendered markdown as the PR body/title/commit subject. The delta step is `continue-on-error: true` with a static-body fallback step, so a jq/shell bug degrades the PR text instead of silently skipping the weekly refresh. A refresh still opens a PR even when only snapshot_date.txt changed (no catalog content diff), preserving today's behaviour and avoiding any interaction with the check-models-fresh staleness test. - `scripts/models-delta-test.sh` is a golden-fixture regression test for the two jq scripts (fixtures under .github/scripts/testdata/), since they have no Go-test equivalent and only run for real, unattended, once a week. `.github/workflows/models-delta-lint.yml` runs it (plus shellcheck) as its own path-filtered workflow — mirrors the repo's existing docs-lint.yml pattern — rather than unconditionally on every PR via ci.yml's blanket lint job. - A concurrency group and a canonical-repo job guard prevent an overlapping workflow_dispatch from racing the weekly schedule run. Phase 3 of the original proposal (an LLM-written PR summary via docker/docker-agent-action) is deferred to a future change.
81 lines
2.2 KiB
Bash
Executable File
81 lines
2.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# scripts/models-delta.sh — semantic diff of the models.dev catalog snapshot.
|
|
#
|
|
# Usage:
|
|
# scripts/models-delta.sh [--json-out FILE] [OLD NEW]
|
|
#
|
|
# With no positional arguments, compares the version of
|
|
# pkg/modelsdev/snapshot.json at HEAD against the current working-tree copy —
|
|
# i.e. "what would `task update-models` change if I committed it right now".
|
|
# This is also exactly what the update-models workflow runs after refreshing
|
|
# the snapshot, so the local and CI code paths never drift apart.
|
|
#
|
|
# OLD and NEW, when given, are paths to two snapshot.json files to compare
|
|
# instead (e.g. two saved copies from different runs).
|
|
#
|
|
# The rendered markdown always goes to stdout. --json-out additionally writes
|
|
# the structural delta (added/removed/changed) as JSON, which the workflow
|
|
# uses to compute counts and a commit subject without re-running jq.
|
|
set -euo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
DELTA_JQ="$ROOT/.github/scripts/models-delta.jq"
|
|
RENDER_JQ="$ROOT/.github/scripts/models-delta-render.jq"
|
|
|
|
json_out=""
|
|
positional=()
|
|
end_of_opts=false
|
|
while [ $# -gt 0 ]; do
|
|
if [ "$end_of_opts" = false ]; then
|
|
case "$1" in
|
|
--json-out)
|
|
[ $# -ge 2 ] || { echo "models-delta.sh: --json-out requires a path" >&2; exit 2; }
|
|
json_out="$2"
|
|
shift 2
|
|
continue
|
|
;;
|
|
--)
|
|
end_of_opts=true
|
|
shift
|
|
continue
|
|
;;
|
|
-*)
|
|
echo "models-delta.sh: unknown option $1" >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
fi
|
|
positional+=("$1")
|
|
shift
|
|
done
|
|
|
|
old="${positional[0]:-}"
|
|
new="${positional[1]:-}"
|
|
|
|
cleanup_old=""
|
|
delta_json=""
|
|
trap '[ -n "$cleanup_old" ] && rm -f "$cleanup_old"; [ -n "$delta_json" ] && rm -f "$delta_json"' EXIT
|
|
|
|
if [ -z "$old" ]; then
|
|
cleanup_old="$(mktemp)"
|
|
old="$cleanup_old"
|
|
git -C "$ROOT" show "HEAD:pkg/modelsdev/snapshot.json" > "$old"
|
|
fi
|
|
if [ -z "$new" ]; then
|
|
new="$ROOT/pkg/modelsdev/snapshot.json"
|
|
fi
|
|
|
|
for f in "$old" "$new"; do
|
|
[ -r "$f" ] || { echo "models-delta.sh: cannot read $f" >&2; exit 1; }
|
|
done
|
|
|
|
delta_json="$(mktemp)"
|
|
|
|
jq -n --slurpfile old "$old" --slurpfile new "$new" -f "$DELTA_JQ" > "$delta_json"
|
|
|
|
if [ -n "$json_out" ]; then
|
|
cp "$delta_json" "$json_out"
|
|
fi
|
|
|
|
jq -r -f "$RENDER_JQ" "$delta_json"
|