Skip to content

ci: add gate, preflight and verification to testing image release - #718

Open
nvasiu wants to merge 2 commits into
mainfrom
gate-ecr-release
Open

ci: add gate, preflight and verification to testing image release#718
nvasiu wants to merge 2 commits into
mainfrom
gate-ecr-release

Conversation

@nvasiu

@nvasiu nvasiu commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Issue #, if available:

Related to #716

Description of changes:

The ecr-release.yml action would previously run for every monorepo release, regardless if the release included a new version for the testing package or not. So it was possible for this action to publish the latest changes of the testing package before they were released. This PR updates the action to be safer.

.github/workflows/ecr-release.yml

  • Add a preflight job to parse the release tag, verify the tag matches the source, check if the version already exists in public ECR, and emit a plan.
  • Gates the build on the above preflight checks.
  • Add a post-publish verification that polls public ECR (polls 10 times with 15s wait = 150s total) and confirms that the new version was published.

.github/scripts/parse_testing_version.py

  • Separate script for parsing the testing version from a release tag.

.github/scripts/tests/test_parse_testing_version.py

  • Unit testing for the parsing script.

.github/workflows/test-parser.yml

  • Wire the new script and test into the script-test workflow.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@nvasiu
nvasiu deployed to ai-pr-review-runtime September 10, 2026 23:21 — with GitHub Actions Active
@nvasiu
nvasiu deployed to ai-pr-review-runtime September 10, 2026 23:29 — with GitHub Actions Active
Comment thread .github/workflows/ecr-release.yml Outdated
@github-actions

This comment has been minimized.

@nvasiu nvasiu changed the title ci: gate testing image publish on testing release ci: add gate, preflight and verification to testing image release Sep 11, 2026
@nvasiu
nvasiu deployed to ai-pr-review-runtime September 11, 2026 18:35 — with GitHub Actions Active
Comment on lines +75 to +81
if aws ecr-public describe-images \
--region "${{ env.aws_region }}" \
--repository-name "$repo_name" \
--image-ids imageTag="v${VERSION}" >/dev/null 2>&1; then
echo "exists=true" >> "$GITHUB_OUTPUT"
else
echo "exists=false" >> "$GITHUB_OUTPUT"

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.

Codex AI review · Finding arf_v1_ilnzykk7t6nru3bdky4dlegmro

Every describe-images failure—not just a missing tag—is converted to exists=false. Missing permissions, throttling, or service errors can therefore proceed to overwrite an existing mutable version tag or fail only after building. Treat only ImageNotFoundException as absent and fail preflight for all other errors.

--repository-name "$repo_name" \
--image-ids imageTag="latest" \
--query 'imageDetails[0].imageDigest' --output text 2>/dev/null || true)"
if [[ "$latest_digest" != "$version_digest" ]]; then

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.

Codex AI review · Finding arf_v1_fdnghwehki3bd75myykb7emh2e

OCI index digests include descriptor order. The version manifest is created x86_64 then arm64, while latest is created arm64 then x86_64, so their top-level digests differ despite containing the same images. This marks successful publishes as failed. Create both tags from one identically ordered manifest or compare their child platform digests.

Comment on lines +267 to +271
latest_digest="$(aws ecr-public describe-images \
--region "${{ env.aws_region }}" \
--repository-name "$repo_name" \
--image-ids imageTag="latest" \
--query 'imageDetails[0].imageDigest' --output text 2>/dev/null || true)"

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.

Codex AI review · Finding arf_v1_vbr4zrftdaxr75tg7x2l4btewl

The version tag is retried, but latest, which is pushed afterward, is queried only once. ECR can expose the version before the latest update, causing intermittent failures with an old or empty digest. Poll both tags within the same deadline before failing.

Comment on lines +8 to +13
_PATTERN = re.compile(r"testing-v[0-9]+\.[0-9]+\.[0-9]+([^,]*)")


def parse_testing_version(release_tag: str) -> str:
"""Return the testing version named by the release tag, or empty if none."""
match = _PATTERN.search(release_tag)

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.

Codex AI review · Finding arf_v1_4yrwtgbfg6esv2mdlgeyix4gi5

The unanchored pattern and search() treat tags such as not-testing-v1.2.1 or sdk-v2.0.0,mytesting-v1.2.1 as testing releases. If that version matches source, an unrelated malformed release publishes the image. Split on commas and full-match a testing-v... component, with regression tests for invalid prefixes.

@github-actions

Copy link
Copy Markdown
Contributor

Codex AI review

Found four release-automation defects affecting publication safety and verification reliability.

Reviewed commit 44d8ed03d3ba8954121e4d3c198252aa4e44a4c0. Workflow run

@yaythomas yaythomas left a comment

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.

The preflight and verification confirm that an image tag exists. They do not confirm the image contains what the release names. The Dockerfile installs aws-durable-execution-sdk-python>=1.0.0, resolved at build time and unbounded, so two builds of one testing version can produce different images, and skip-if-exists assumes a version identifies one artifact.

(The other three points are on the relevant lines.)

Comment on lines +75 to +81
if aws ecr-public describe-images \
--region "${{ env.aws_region }}" \
--repository-name "$repo_name" \
--image-ids imageTag="v${VERSION}" >/dev/null 2>&1; then
echo "exists=true" >> "$GITHUB_OUTPUT"
else
echo "exists=false" >> "$GITHUB_OUTPUT"

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.

Every nonzero exit becomes exists=false, which means publish. A missing IAM permission, a throttle, a network error, and a genuinely absent tag all result in publish here?


# Matches a testing-v<x.y.z> entry in the release tag, stopping at a comma
# so combined tags like "sdk-v2.0.0,testing-v2.0.0" resolve to the testing part.
_PATTERN = re.compile(r"testing-v[0-9]+\.[0-9]+\.[0-9]+([^,]*)")

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.

resolve_layer_sdk_version.py already parses release tags, using split(",") plus startswith("sdk-v"). parse_testing_version.py uses an unanchored regex with a ([^,]*) suffix capture. The logic is also not equivalent.

Comment on lines +267 to +273
latest_digest="$(aws ecr-public describe-images \
--region "${{ env.aws_region }}" \
--repository-name "$repo_name" \
--image-ids imageTag="latest" \
--query 'imageDetails[0].imageDigest' --output text 2>/dev/null || true)"
if [[ "$latest_digest" != "$version_digest" ]]; then
echo "::error::latest on public ECR points at $latest_digest but v$VERSION is $version_digest."

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.

verify-publish only confirms latest points at the version just pushed, not that it points at the newest version, so a backport release like testing-v1.1.3 cut after 1.2.1 would move latest backwards and still pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants