| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
K8s: Node template handle `hpa.platformName` different with default in `values.yaml` Signed-off-by: Viet Nguyen Duc <nguyenducviet4496@gmail.com> | 1 年前 | |
update: Selenium Grid 4.24.0 Signed-off-by: Viet Nguyen Duc <nguyenducviet4496@gmail.com> | 2 年前 | |
test(chart): parallel with autoscalingType deployment & job Signed-off-by: Viet Nguyen Duc <nguyenducviet4496@gmail.com> | 2 年前 | |
K8s: Replace Ingress NGINX with Traefik for default ingress controller (#3083) | 6 个月前 | |
update: Selenium Grid 4.25.0 Signed-off-by: Viet Nguyen Duc <nguyenducviet4496@gmail.com> | 1 年前 | |
ci: reliable multi-arch build setup — QEMU + skip Docker reinstall (#3204) * fix(ci): register QEMU/binfmt when INSTALL_DOCKER=false so arm64 Chrome builds The "Deploy specific Chrome version" workflow runs `INSTALL_DOCKER=false make setup_dev_env`, which short-circuits chart_setup_env.sh before the `tonistiigi/binfmt --install all` step that registers QEMU emulation. Since #3187 made Google Chrome multi-arch (linux/amd64,linux/arm64), the arm64 NodeChrome build now needs that emulation and fails with `exec /bin/sh: exec format error`. Register QEMU/binfmt (still gated by DOCKER_ENABLE_QEMU) in the INSTALL_DOCKER=false path as well, reusing the runner's pre-installed Docker. Firefox/deploy/nightly already work because they use INSTALL_DOCKER=true; Edge was unaffected only because it is amd64-only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ci: don't reinstall Docker by default in chart_setup_env (flaky/slow) The "Set up containerd image store feature" step runs chart_setup_env.sh, which reinstalled Docker CE + plugins from apt on every run even though GitHub-hosted runners already ship Docker/buildx/compose. That apt reinstall over the network is the slowest and flakiest part of the setup and frequently exceeds the retry action's 10-minute window (kill EPERM). Only (re)install Docker CE when a specific DOCKER_VERSION is requested that differs from the version already present on the runner; otherwise use the pre-installed Docker. The downstream version-match guard is preserved, so version-pinned jobs still fail fast if the expected version is not active. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ci: apt-get update up front so skipping Docker reinstall doesn't 404 Skipping the Docker CE reinstall also skipped its `apt-get update`, leaving a stale apt index. The later cross-compilation tools install then failed with "404 Not Found" fetching a superseded qemu-user-static .deb. Refresh the apt index once up front, independent of the Docker reinstall path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> | 1 个月前 | |
[ci] Build images once per PR and promote by tag instead of rebuilding (#3229) * [ci] Build images once per PR and promote by tag instead of rebuilding Every job in the PR suite built the images it needed, from scratch. Not just the four entries with build-all: every test target names image targets as Make prerequisites - `test_video: video hub chrome firefox edge chromium` - so all of them built something. That is 18 docker-test jobs, 9 k8s-scaling, 8 helm-chart and 2 k8s-dynamic-grid: 37 builds of the same images per pull request. Recent runs took 75-88 minutes. deploy.yml then built them a 38th time, so the artefact released was a rebuild of the tested source rather than the tested artefact. Build once, publish to GHCR, and have everything else pull. ghcr.io/<owner>/<image>:pr-<N> one set per pull request ghcr.io/<owner>/<image>:trunk-<sha> one set per trunk run ghcr.io/<owner>/<image>:main the last trunk set whose tests passed build-images.yml decides what a run needs: reuse-main nothing image-affecting changed, so run against :main and build nothing at all. Of the last 18 merges, 6 qualify. build-and-push build once, multi-arch, push the tag, every job pulls it build-in-job fork pull requests, which have no registry credentials, keep today's behaviour exactly Image-affecting means the 21 directories holding a Dockerfile, or the Makefile, which carries the build arguments and pinned versions. That last rule is deliberately coarse: an unnecessary build costs minutes, a missed one ships an untested image. Forks are detected by comparing head repository to this one, and never receive credentials. pull_request_target is not used - it would hand a registry write token to untrusted code. Test jobs pull and retag to the local names the compose files already expect, then set SKIP_BUILD=true. That turns every image-build target into a no-op via a single guarded block at the end of the Makefile, so the 48 build recipes and the 59 test targets are untouched and `make build` and `make test` behave exactly as before when the variable is unset. The block sits last because GNU Make lets the last definition of a target win. gen_certs, prepare_resources and update_go are deliberately not skipped: they produce working-tree files the tests read. :main is moved only after the full suite passes, by retagging the run-scoped trunk tag, so it always denotes a tested tree and the digest never changes. deploy.yml pulls :main and promotes it, falling back to building when :main does not exist yet - which it will not, on the first release after this lands. pr-* tags are deleted when the pull request closes, and swept weekly for anything that missed. The cleanup only ever removes tags matching pr-<digits>, and only when every tag on that manifest matches, so a shared or release tag cannot be caught by it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * [ci] Fix duplicate with: keys that failed the workflow at startup The first run of this branch failed before any job started: "This run likely failed because of a workflow file issue." Inserting the ci-* inputs put a second `with:` block in the helm-chart-test and k8s-dynamic-grid-test call sites, because their existing `with:` came after `secrets: inherit` rather than immediately after `uses:`: uses: ./.github/workflows/helm-chart-test.yml with: # inserted ci-mode: ... secrets: inherit with: # original, still there release: ... PyYAML's safe_load accepts duplicate mapping keys and silently keeps the last, so my validation passed while GitHub rejected the file - the same class of false-pass as the grep quoting bug: a check that could not see the defect it was meant to catch. Merge into the existing blocks, and validate with a loader that rejects duplicate keys instead of one that hides them. Also give docker-test `secrets: inherit`, so every called workflow can reach the registry the same way. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * [ci] Format the Makefile additions to mbake's canonical style `make lint_format_scripts` runs the formatters and fails if anything changed, so the committed file has to already be in canonical form. Also simplifies promote_ci_images: its `if ... ; \` continuation was something mbake kept re-indenting, so the gate could never have gone green. A plain `test -n ... || (echo; exit 1)` guard on its own line is stable, and reads better. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * [ci] Promote the PR's images on merge instead of rebuilding for main A merge rebuilt everything the pull request had already built and tested. Key the images on their own content instead, and the merge can reuse them. The tag becomes src-<hash>, where the hash covers every path that can change what ends up in an image: the 21 directories holding a Dockerfile, plus the Makefile, hashed by blob id. This works where matching on a pull request number would not. SeleniumHQ squash-merges, so the pull request commit is not an ancestor of trunk and is unreachable once the branch is deleted. The content hash is identical on both sides regardless. Verified against #3228: its head and its squash merge on trunk both hash to fd9b32eb0465, while a Makefile tag bump hashes to 36fcdfcb808a. So the decision collapses to one question - do images for this content already exist? yes reuse them. On a pull request that means an earlier run or another branch already built this content. On trunk it means the pull request just did, which is the promotion case: no rebuild, tests run against the same images, and promote-main retags them to :main. no build once and push. This also replaces the changed-path heuristic, which only approximated the same question and rebuilt whenever the Makefile was touched at all. Pull request builds additionally tag pr-<N>, so cleanup-pr-images.yml still has something to delete on close. The src-* tag is shared across pull requests and deliberately outlives any one of them, so cleanup never removes it. One note on the verification: the first attempt at checking the hash ran in zsh, which does not word-split unquoted variables, so `git ls-tree -- $PATHS` matched nothing and every commit hashed to the SHA-256 of an empty string. Re-run under bash, which is what CI uses, it gives the real answer above. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * [ci] Key images on the Selenium core too, so a PR build cannot be released Promoting a pull request's images to :main and then to a release was wrong, and would have shipped images built against the wrong Selenium core. get-latest-upstream resolves a different core depending on how it is called: release: false the latest Nightly upstream release (prerelease == true) release: true the latest stable release Pull requests build against nightly, deliberately - that is how an upcoming core gets tested. deploy.yml builds against stable. My build-images job asked for 'false', so every image it produced carried a nightly core. Promoting one of those to :main and releasing it would have published a stable release built on a nightly Selenium. The content hash made it worse rather than catching it: it covered the source files only, so the same tree built against a nightly core and a stable core produced the *same* src-<hash> tag. The two would have been interchangeable. So the core is now part of the key. The hash covers the image-affecting paths and the resolved BASE_VERSION, and decide resolves the core before hashing: pull request nightly core, as before trunk, release stable core Identical source now hashes to src-d61948d6378d against a 4.49.0-SNAPSHOT core and src-b9fa526b0f36 against 4.48.0, so the two can never collide and a pull request build can never be promoted as a release. That gives the intended flow. A merge no longer reuses the pull request's images: its stable-core hash is new, so trunk builds, tests, and promotes that to :main. deploy.yml now checks before trusting :main. It recomputes the hash for the release core and only promotes when :main resolves to the same digest as src-<hash>; a stale :main, from trunk moving on or the core changing underneath, falls through to a rebuild rather than releasing the wrong bits. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * [ci] Carry the release tag as well as the version to the build The build failed downloading the Selenium core. get-latest-upstream writes three variables: BASE_RELEASE=<upstream tag> nightly | selenium-4.48.0 BASE_VERSION=<version> 4.49.0-SNAPSHOT | 4.48.0 VERSION=<version> and Base/Dockerfile builds its download URL from both of them: .../releases/download/${RELEASE}/selenium-server-${VERSION}.jar Passing the resolved core from the decide job to the build job, I carried only BASE_VERSION. BASE_RELEASE therefore fell back to the Makefile default selenium-4.48.0 while BASE_VERSION was the nightly 4.49.0-SNAPSHOT, so the build asked for a jar that does not exist: selenium-4.48.0 + 4.48.0 -> 200 nightly + 4.49.0-SNAPSHOT -> 200 selenium-4.48.0 + 4.49.0-SNAPSHOT -> 404 <- what it asked for Carry all three. Splitting a resolved pair across jobs and reassembling half of it was the mistake; the comment at that step now says why all three have to travel together. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * [ci] Build each architecture natively instead of emulating arm64 The multi-arch build was heading past an hour. Building linux/amd64 and linux/arm64 on one amd64 runner means QEMU-emulating every arm64 layer, and for 26 images that is most of the run. Build each architecture on its own native runner, in parallel, and merge the results into a manifest list. The repo already uses ubuntu-24.04-arm for its arm64 tests, so the runners were there. Two native builds cost roughly one amd64 build rather than one plus an emulated one. build (amd64, ubuntu-24.04) -> src-<hash>-amd64 build (arm64, ubuntu-24.04-arm) -> src-<hash>-arm64 merge -> src-<hash> (manifest list) Edge and Chrome for Testing are amd64-only. The Makefile already skips them when PLATFORMS carries no linux/amd64, so the arm64 job never builds them; two changes follow from that: push_ci_images skips images this build did not produce, rather than failing on `docker tag` for one that was correctly never built. It still fails if it pushed nothing at all, so a genuinely empty build cannot pass quietly. merge_ci_images assembles the list from whichever architecture tags exist, so Edge and Chrome for Testing get a single-architecture list instead of an error. Test jobs pull src-<hash> and Docker selects the right architecture, so nothing in the test workflows changes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * [ci] Lowercase the registry owner before using it in an image reference push ghcr.io/SeleniumHQ/base:src-331808bba75d-arm64 Error parsing reference: ... repository name (SeleniumHQ/base) must be lowercase github.repository_owner is SeleniumHQ, and a registry reference has to be lowercase. Everywhere else in this repo already folds it: ghcr.io/$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') I used that in deploy.yml and then wrote the new workflow's registry as a top-level `env:` instead, where no shell runs and GitHub expressions have no lower() to reach for. Derive it once in the decide job, which already publishes `registry` as an output, and let build, merge and every test workflow read it from there. The top-level env is gone, so there is no second definition to drift. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * [ci] Authenticate to GHCR with the CI token, not GITHUB_TOKEN push ghcr.io/seleniumhq/base:src-331808bba75d-arm64 unexpected status from POST to https://ghcr.io/v2/seleniumhq/base/blobs/uploads/: 403 Forbidden The login succeeded and the push did not. GITHUB_TOKEN has no write access to these packages: they are org-level, pre-existing, and every workflow in this repo that publishes to GHCR authenticates with a PAT instead - echo "${{ secrets.SELENIUM_CI_TOKEN }}" | docker login ghcr.io \ -u "${{ secrets.SELENIUM_CI_USERNAME }}" --password-stdin deploy.yml, nightly.yml, build-ffmpeg.yml and all four release-*-versions.yml do it that way. I used GITHUB_TOKEN in the new steps and did not check what the working ones used. Pulls need it too: ghcr.io/seleniumhq/base returns 401 unauthenticated, so the packages are private and a read is no more anonymous than a write. All eight logins now use the PAT, falling back to GITHUB_TOKEN so nothing hard-fails if it is ever unset. Fork pull requests are unaffected - they build in-job and never touch the registry. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * [ci] Use each image's real local tag when pushing and pulling The merge job failed: no architecture tags for video. push_ci_images looked for $(NAME)/<image>:$(TAG_VERSION) for all 26 images, but video is not built with the grid tag. It is built as $(NAME)/video:$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) ffmpeg-8.1-20260905 and the compose files read it from VIDEO_TAG, which the test targets set to the same thing. So `docker image inspect` never found it, the skip-if-absent guard I added for the amd64-only images swallowed it, and the failure only surfaced two jobs later when merge had nothing to assemble. The guard was right for Edge and Chrome for Testing on arm64 and wrong here; it turned a missing image into silence. It now runs after the tag is resolved correctly, so it only skips images this architecture genuinely does not build. Both push and pull resolve the tag per image. Audited the other 25: video is the only one that differs, and ffmpeg is handled too so it is right if it is ever added to CI_IMAGES. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * [ci] Skip images that were never built for the runner's architecture pull ghcr.io/seleniumhq/node-chrome-for-testing:src-de73f4c3321a Error response from daemon: no matching manifest for linux/arm64/v8 in the manifest list entries Edge and Chrome for Testing are amd64-only. The Makefile already skips them when PLATFORMS carries no linux/amd64, so the arm64 build never produces them and their manifest list has no arm64 entry - confirmed on the published images: selenium/node-chrome amd64, arm64 selenium/node-chrome-for-testing amd64 pull_ci_images asked for all 26 regardless, so the arm64 test jobs failed on the first one that does not exist for them. Forcing --platform would be the wrong fix: it would pull an amd64 image onto an arm64 runner, which cannot run it. These images should not be pulled there at all, and the arm64 tests do not use them. So inspect the manifest first and skip only images with no entry for this architecture, reporting them. An image missing from the registry entirely stays a hard error - that means the build or the merge went wrong, and conflating the two is what let the missing video image surface two jobs late. The pull is also explicitly --platform linux/<arch> now, so it can never resolve to the wrong architecture by accident. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * [ci] Use this project's external scaler wherever a test uses an existing KEDA The chart has shipped the external scaler as its default since #3169, so that is what users run. The tests mostly did not: of eleven autoscaling targets, ten pinned TEST_EXTERNAL_SCALER=false and exercised KEDA's built-in selenium-grid scaler instead. That scaler still miscounts ongoing sessions upstream - the problem keda-scaler-include-ongoing-sessions exists to work around - and it shows up in these runs as Unable to find a free slot for request with the browser nodes sitting ready at 1/1. job_https needed three attempts to pass on trunk; the scaler, not the images, is why. So the suite was mostly covering a path users do not get, using a component with a known upstream defect. Default TEST_EXTERNAL_SCALER from TEST_EXISTING_KEDA: a test pointed at an existing KEDA install now gets this project's scaler, matching the chart. Three targets change behaviour - autoscaling_deployment, autoscaling_job and autoscaling_job_https. Everything without existing KEDA is untouched, and job_externalScaler already set it explicitly. The combination is not new: job_externalScaler has been running existing KEDA with the external scaler all along, and passes. Setting TEST_EXTERNAL_SCALER=false in a target still forces the built-in scaler, so a canary on upstream behaviour can be kept. No target does today, which is a deliberate loss of coverage for a scaler that is neither the default nor currently correct - worth revisiting if KEDA fixes it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * [ci] Make the image cleanup work with content-addressed tags The cleanup was written when the tag was pr-<N>, owned by one pull request. The primary tag then became src-<hash>, keyed on image content and shared, and I did not revisit the cleanup. It had quietly become a no-op. GHCR deletes versions - manifests - not individual tags, and one manifest carries both its src-<hash> tag and the pr-<N> alias of the pull request that built it. They are the same object, so pr-<N> cannot be removed while keeping src-<hash>. The old guard, "only delete when every tag is pr-*", therefore matched nothing and src-* tags would have accumulated for ever. Use the pr-<N> alias as the handle instead. A version is removed only when all of these hold: * it carries a pr-<N> tag whose pull request is closed * no pull request still open shares that manifest - two pull requests with identical image content get one manifest with both aliases on it * it is not what main points at, since that is the release promotion source * every tag on it is pr-* or src-*, so a release tag, latest or nightly can never be caught even if the API hands one back The trigger stays as it was: on close, merged or not, plus a weekly sweep for anything a failed run missed. Ten tests cover the rule directly, including the two cases that make it non-obvious - a manifest shared by an open and a closed pull request, and main protection applying per image rather than globally. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * [ci] Delete trunk images that main has superseded Trunk publishes src-<hash> and, once its tests pass, :main is retagged onto it. The previous trunk manifests kept their src-* tag for ever. They carry no pr-* alias - only a pull request build creates one - so the closed-pull-request sweep could never reach them. That was a slow leak with nothing to stop it. Prune them where it is safest: in promote-main, immediately after :main moves. At that moment everything older is definitively superseded. "Older than what :main points at" is the test, rather than an age in days. An age window would be arbitrary and could race - a manifest newer than the current main may be mid-promotion in a concurrent run. Comparing against main's own timestamp cannot: anything newer is left alone by construction. The same four protections as the pull-request sweep still apply. A manifest is removed only when every tag on it is src-*, so a pr-* alias hands it back to the other sweep and a release tag, latest or nightly is never touched. Eleven more tests, including the two that matter: a manifest newer than main is kept, and one carrying a pr-* alias is left alone. Three assert that SRC_TAG really requires a hex hash - it caught my own fixtures using src-old111, which is not hex and so was correctly ignored. Trunk runs with --no-pr-sweep rather than a --pr number no pull request can have. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * [ci] Alias every pull request build, and collect the manifests it leaves behind Two holes, both found by asking what happens to a pull request with several image-affecting commits. A tag names one manifest, so retagging pr-<N> onto each new build moves it. A pull request with N such commits leaves N-1 manifests carrying only src-*, and the closed-pull-request sweep needs a pr-* tag it no longer has. Nothing could ever remove them. Worse, the alias was created in the merge job, which only runs when we build. A pull request whose content matched an existing manifest went straight to reuse and got no alias at all. Its images then looked orphaned while it was still open, so closing the pull request that did build them would have deleted images another open one was actively testing against. Alias in its own job that also runs on reuse. Tagging is idempotent and several pull requests can alias one manifest, which is precisely how the cleanup tells a shared manifest from an abandoned one. With every in-use manifest aliased, an unaliased src-* is provably unused, so the weekly sweep can collect them by age. Seven days, and the age guard is only covering the minutes between a push and its alias landing - the aliasing, not the clock, is what makes it safe. On-close runs skip it, since that run only knows about one pull request. Six more tests, including the case that prompted this: three builds of one pull request, the newest aliased, the two older ones collected. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * [ci] Mark every pull request build durably, so closing it cleans up all of them Closing a pull request removed only its newest manifest. pr-<N> moves to each new build, so the earlier ones were left for the weekly orphan sweep to find by age. Recomputing the hashes at close time would not work, and it is worth writing down why: the hash covers BASE_VERSION, and for a pull request that is the nightly core, which moves. Replaying the calculation after the fact resolves a different nightly and a different hash. The mapping cannot be recovered from git, and the branch being deleted is beside the point. So record it at build time. Each build now writes two markers: pr-<N> moves to the newest build - "the current image for this PR" pr-<N>-<hash> written once, never moves The durable one makes close-time cleanup complete: every manifest a pull request ever used stays attributable to it. PR_TAG accepts both forms and takes the number from either, so the existing guards keep working unchanged - including the one that keeps a manifest two pull requests share until both are closed. Six more tests, including the case this came from: three commits, three manifests, all three removed on close; and its inverse, an open pull request keeping every build it has made. The age-based orphan sweep stays as a backstop for a build whose alias job did not run, but it is no longer the mechanism that catches this. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * CI: Fix the four review blockers in the build-once redesign Release images were single-arch. deploy.yml pulled :main per-arch and pushed from the local store, so every published release manifest was whichever architecture the runner happened to be. Reverted deploy.yml to trunk: it builds its own release images, as before. :main stays a cache for later trunk runs, nothing more. promote-main ran with the tests skipped. It gated on !failure(), and the three test jobs skip on '[skip test]' - which is exactly what the release bot commits, right after rewriting Base/, NodeChrome/, Video/ and the Makefile. A wholly untested manifest would have become :main. Now each of the three must report success. A half-finished merge wedged CI for ever. decide probed base:<tag>, and base is the first image merge_ci_images writes, so a cancelled merge - and cancel-in-progress makes that routine - left base:<tag> present and the rest missing. Every later run then chose reuse and hard-failed in pull_ci_images, with no way out but a hand-deleted tag. The probe is now a completeness marker written only after the whole set has merged, the merge is retried, and force-build is exposed on the workflow_dispatch as a manual override. The marker is a second tag on the manifest base:<tag> already is, so it costs no storage - but the cleanup had to learn it, or every base manifest would count as carrying a non-CI tag and be protected from deletion for ever. Nightly ran its tests against stable-core images. build-images resolved its core independently of the workflow that called it, so nightly.yml built stable images while its tests expected the nightly core. The core now comes from one `release` input threaded from build-test.yml, so the images and the tests can never disagree about what is under test. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * CI: Correct a stale comment about the content hash The hash now covers BASE_VERSION, so quoting a specific digest for #3228 no longer holds - the claim was written before the core was folded in. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * CI: Stop the merge deleting the images the merge is about to use Closing a pull request swept its images immediately, merged or not. On a merge that is precisely wrong: the merge commit hashes to the same content, so the trunk run starting seconds later chooses reuse and every test job pulls those manifests. The sweep raced it - hard-failing the pulls, or at best forcing the rebuild this design exists to avoid, since promote-main only claims them as :main at the end of the suite an hour later. Merged pull requests are now left to the weekly sweep, by which point :main protects them or a later trunk build has superseded them. Deletes now use SELENIUM_CI_TOKEN. The packages are org-level, so GITHUB_TOKEN 403s on a version delete - and the superseded prune runs under continue-on-error, so it would have failed in silence for ever. update_go joins SKIP_BUILD_TARGETS. It is a prerequisite of base, so the reuse path ran a `docker pull golang:latest` plus `go get -u` and `go mod tidy` for two modules in each of ~37 test jobs: minutes per job, a live-network flake in each, and a mutation of hashed sources after the tag had been decided. Nothing read at test time comes out of it. gen_certs and prepare_resources still run, as before. Also dropped a trailing echo in pull_ci_images that claimed all 26 images had been retagged even when the amd64-only ones were skipped. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * CI: Collect the per-architecture manifests, which nothing could reach Half of every image's CI tags were unreachable. The native build jobs push src-<hash>-amd64 and src-<hash>-arm64, merge_ci_images indexes them, and no sweep could see them again: they carry no pr-* alias, and src-<hash>- <arch> is not what SRC_TAG matches. On seleniumhq/base today that is 8 of 16 CI tags, and it grows by two per image per build - 52 manifests a run. They could not simply be matched either. A child is what the index points at, not a copy of it, so deleting one alone breaks an index that may still be in use. Removal is therefore by hash family: the sweeps still judge indexes only, and delete_family takes the index and its children together, index first, so an interrupted run leaves a collectable orphan rather than a broken index. The new tests drive the real functions through a recording stub instead of restating their rules, which is the only way a defect in delete_family could show up. The existing mirror now calls is_ci_tag rather than repeating it, and its duplicate version() helper is gone. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * CI: Never take a child manifest two indexes share Two hashes whose images build out byte-identical share one manifest, which then carries an arch tag for each of them. delete_family would have taken it with the first index and broken the second. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm * CI: Require SELENIUM_CI_TOKEN for the image deletes, with no fallback Falling back to GITHUB_TOKEN only converted a missing secret into a sweep that deletes nothing: the packages are org-level, so GITHUB_TOKEN 403s on a version delete, and the script catches those per version and reports them in the step summary nobody reads. Without the secret it now stops at "GH_TOKEN is required". Every context this runs in has the secret - pull_request_target, schedule and workflow_dispatch all carry repository secrets. The GHCR login steps keep their fallback, since reads work either way. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGLHB3pjY3mGZBu4TyUsrm --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> | 19 天前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 1 年前 | ||
| 2 年前 | ||
| 2 年前 | ||
| 6 个月前 | ||
| 1 年前 | ||
| 1 个月前 | ||
| 19 天前 |