Skip to content

ci: publish research image from exact-main artifact - #332

Merged
proerror77 merged 1 commit into
mainfrom
codex/exact-main-artifact-reuse-317
Jul 24, 2026
Merged

ci: publish research image from exact-main artifact#332
proerror77 merged 1 commit into
mainfrom
codex/exact-main-artifact-reuse-317

Conversation

@proerror77

@proerror77 proerror77 commented Jul 24, 2026

Copy link
Copy Markdown
Owner

Change contract

A successful relevant main Prediction Markets CI run publishes one short-lived manifest-bound Research release artifact, and automated ACR packaging consumes exactly that authenticated run artifact without rebuilding.

Out of scope

Rust behavior, Docker image redesign, compiler/cache policy, cache-save timing, ACR Enterprise migration, self-hosted runners, collector deployment, and branch-protection policy.

Dependency / merge order

Depends on #316, merged via #329. No stacked PR remains; this PR targets main directly.

Focused validation

  • .github/scripts/test-research-image-release-artifact.sh
  • .github/scripts/test-acr-publish-workflow.sh
  • .github/scripts/test-select-rust-ci-scope.sh
  • bash -n and ShellCheck for all changed shell scripts
  • actionlint for ploy-ci.yml and acr-publish.yml
  • git diff --check origin/main...HEAD
  • Independent committed Standards and Spec reviews: PASS

Counterexamples cover failed/PR/non-main/partial source runs, implicit manual rebuild, missing/extra/tampered binaries, source/run/Cargo.lock mismatch, and irrelevant skipped Research jobs.

Rollout / rollback impact

Automated Research ACR publication begins only after a successful relevant main Prediction Markets CI run and uses its exact run ID and head SHA. Artifacts retain for one day. Missing, expired, malformed, or mismatched artifacts fail closed with no rebuild. Manual Research publication requires the explicit rebuild checkbox. Rollback is a workflow/script revert; existing image contents and runtime deployments are unchanged.

Scope exception

None. Eight files and 491 changed lines.

Closes #317

Summary by CodeRabbit

  • New Features

    • Improved image publishing to consistently use the selected source revision.
    • Added optional manual rebuilding of research runner binaries.
    • Added authenticated release manifests with binary and lockfile integrity checks.
    • Updated CI workflows to package, verify, and publish research image releases.
  • Bug Fixes

    • Prevented publishing from invalid, incomplete, or mismatched workflow results.
    • Improved validation of release contents, digests, source revisions, and artifact identifiers.
  • Tests

    • Added end-to-end coverage for publishing decisions and release artifact validation.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds source-selection logic for ACR publishing, authenticated research release manifests, exact-source artifact handling, and workflow assertions covering creation, verification, smoke consumption, and image revision binding.

Changes

ACR research release flow

Layer / File(s) Summary
Source selection and workflow triggers
.github/scripts/select-acr-publish-source.sh, .github/workflows/acr-publish.yml
Selects publish targets, research modes, source SHAs, and artifact run IDs from manual or successful upstream workflow events.
Release manifest creation and verification
.github/scripts/research-image-release-artifact.sh
Creates and validates a fixed-target JSON manifest containing lockfile and six binary SHA-256 digests.
CI release packaging and smoke consumption
.github/workflows/ploy-ci.yml
Packages research binaries as research-image-release artifacts and verifies them during image smoke testing.
ACR artifact publication and source binding
.github/workflows/acr-publish.yml
Rebuilds only for explicit research rebuild mode, otherwise downloads and verifies the selected release, then binds image metadata and generated documents to source_sha.
Workflow and artifact contract tests
.github/scripts/test-acr-publish-workflow.sh, .github/scripts/test-research-image-release-artifact.sh, deployment/aliyun/test-*.sh
Tests source-selection outcomes, manifest tampering failures, workflow wiring, artifact paths, and selected-source revision assertions.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PredictionMarketsCI
  participant SourceSelector
  participant ReleaseArtifact
  participant ACRPublish
  participant Docker
  PredictionMarketsCI->>SourceSelector: completed workflow result, head SHA, run ID
  SourceSelector->>ACRPublish: publish_target, research_mode, source_sha, artifact_run_id
  ACRPublish->>ReleaseArtifact: create or download and verify release
  ReleaseArtifact->>ACRPublish: verified research binaries
  ACRPublish->>Docker: build image with selected source revision
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: publishing Research images from the exact main artifact.
Description check ✅ Passed The description covers the required contract, out-of-scope items, merge order, validation, rollout/rollback, and scope exception.
Linked Issues check ✅ Passed The PR appears to satisfy #317 by adding manifest-bound artifacts, source-run selection, fail-closed verification, rebuild fallback, tests, and retention docs.
Out of Scope Changes check ✅ Passed No clear unrelated code changes are evident; the edits stay focused on artifact publication, selection, verification, workflows, and matching tests.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/exact-main-artifact-reuse-317

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread .github/workflows/acr-publish.yml Fixed
@proerror77
proerror77 force-pushed the codex/exact-main-artifact-reuse-317 branch 2 times, most recently from b291f5c to 098adf2 Compare July 24, 2026 04:19
@proerror77
proerror77 force-pushed the codex/exact-main-artifact-reuse-317 branch from 098adf2 to 80ba7f4 Compare July 24, 2026 04:48

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
.github/scripts/test-research-image-release-artifact.sh (1)

69-91: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Exercise malformed manifest rejection.

These cases mutate binaries and verifier inputs, but never corrupt or remove required fields from the manifest emitted by create. Add malformed-syntax and missing-binding/digest-field cases that must fail verification, preserving the fail-closed artifact contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/scripts/test-research-image-release-artifact.sh around lines 69 -
91, Extend assert_rejected and its invocation cases to corrupt the generated
manifest itself, covering malformed syntax and missing required binding or
digest fields. Ensure each mutated candidate is passed to artifact verify and
fails closed, while preserving the existing binary, source, run, and lock
mismatch cases.
.github/workflows/acr-publish.yml (1)

179-190: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Harden the repeated source_sha/run_id template interpolation into run: scripts.

zizmor flags direct ${{ needs.selector.outputs.* }} expansion inside run: at this site and recurring at lines 239-240, 376, 427, 485, and 505. The upstream regex validation (^[0-9a-f]{40}$ / ^[1-9][0-9]*$) in select-acr-publish-source.sh neutralizes real injection risk today, but as defense-in-depth it's cheap to route these through env: (as already done for the source-jobs/source steps) so a future relaxation of that regex can't reintroduce an injection vector.

♻️ Example for this site
+        env:
+          SOURCE_SHA: ${{ needs.selector.outputs.source_sha }}
+          ARTIFACT_RUN_ID: ${{ needs.selector.outputs.artifact_run_id }}
         run: |
           ...
-          ../.github/scripts/research-image-release-artifact.sh create research-release \
-            "${{ needs.selector.outputs.source_sha }}" \
-            "${{ needs.selector.outputs.artifact_run_id }}" .
+          ../.github/scripts/research-image-release-artifact.sh create research-release \
+            "$SOURCE_SHA" "$ARTIFACT_RUN_ID" .
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/acr-publish.yml around lines 179 - 190, Harden the
repeated template interpolations in the workflow’s run scripts by passing
needs.selector.outputs.source_sha and artifact_run_id through step-level env
variables, then reference those environment variables in the scripts. Apply this
consistently to the current release-artifact command and the recurring sites at
lines 239-240, 376, 427, 485, and 505, matching the existing source-jobs/source
pattern while preserving the validated values and behavior.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/acr-publish.yml:
- Around line 58-63: Update job_conclusion to explicitly check that matches
contains exactly one line before printing it; return a nonzero status when there
are zero or multiple matching jobs, so command substitution and the workflow
fail instead of writing an ambiguous GITHUB_OUTPUT value.

---

Nitpick comments:
In @.github/scripts/test-research-image-release-artifact.sh:
- Around line 69-91: Extend assert_rejected and its invocation cases to corrupt
the generated manifest itself, covering malformed syntax and missing required
binding or digest fields. Ensure each mutated candidate is passed to artifact
verify and fails closed, while preserving the existing binary, source, run, and
lock mismatch cases.

In @.github/workflows/acr-publish.yml:
- Around line 179-190: Harden the repeated template interpolations in the
workflow’s run scripts by passing needs.selector.outputs.source_sha and
artifact_run_id through step-level env variables, then reference those
environment variables in the scripts. Apply this consistently to the current
release-artifact command and the recurring sites at lines 239-240, 376, 427,
485, and 505, matching the existing source-jobs/source pattern while preserving
the validated values and behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bbf0a199-54da-4d81-80bf-c27581c7980f

📥 Commits

Reviewing files that changed from the base of the PR and between 9b02d2e and 80ba7f4.

📒 Files selected for processing (8)
  • .github/scripts/research-image-release-artifact.sh
  • .github/scripts/select-acr-publish-source.sh
  • .github/scripts/test-acr-publish-workflow.sh
  • .github/scripts/test-research-image-release-artifact.sh
  • .github/workflows/acr-publish.yml
  • .github/workflows/ploy-ci.yml
  • deployment/aliyun/test-polymarket-raw-ops-control-plane.sh
  • deployment/aliyun/test-rust-lob-control-plane.sh

Comment on lines +58 to +63
job_conclusion() {
local name=$1 matches
matches=$(awk -F '\t' -v name="$name" '$1 == name {print $2}' <<<"$jobs")
[[ -n "$matches" && "$matches" != *$'\n'* ]]
printf '%s\n' "$matches"
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does bash's set -epropagate into command substitution subshells by default, or does it requireshopt -s inherit_errexit?

💡 Result:

By default, Bash does not propagate the errexit (set -e) option into command substitution subshells [1][2]. When not in POSIX mode, Bash explicitly clears the errexit option within these subshells [1][2]. To change this behavior and force command substitution subshells to inherit the errexit setting from the parent shell, you must enable the inherit_errexit shell option using shopt -s inherit_errexit [3][4]. This option is automatically enabled when Bash is running in POSIX mode [3]. It is important to note that enabling inherit_errexit does not guarantee that the parent script will exit on every error within a command substitution [5][4]. The set -e option only causes the shell to exit when a command that fails is a "simple command" (or part of certain constructs) and its failure status is not otherwise handled or ignored [5]. If a command substitution is embedded within a larger command (e.g., echo $(false) or export var=$(false)), the containing command may still succeed because the command substitution's failure does not necessarily propagate to the status of the outer command [5][4]. To ensure the script halts on an error, the command substitution should typically be performed as a direct, standalone assignment (e.g., var=$(false)) [5][4].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show relevant workflow lines around the function and its call.
sed -n '45,80p' .github/workflows/acr-publish.yml

# Check whether the workflow contains errexit, inherit_errexit, or POSIX mode settings.
rg -n 'set -e|errexit|inherit_errexit|POSIX|shopt' .github/workflows/acr-publish.yml || true

# Behavioral probe: demonstrate the bare guard inside command substitution under bash.
bash - <<'BASH'
job_conclusion() {
  local name=$1 matches
  local jobs=$'ok\tgood'
  matches=$(awk -F '\t' -v name="$name" '$1 == name {print $2}' <<<"$jobs")
  [[ -n "$matches" && "$matches" != *$'\n'* ]]
  printf '%s\n' "$matches"
}
# This assignment succeeds even though the guard fails silently.
out=$(job_conclusion ok)
printf 'exit status and output for command-substitution call: exit=%s out=%q\n' "$?" "$out"
BASH

Repository: proerror77/monday

Length of output: 2092


Make job_conclusion fail when there are zero or multiple matching jobs.

The bare condition inside $(job_conclusion ...) succeeds without stopping execution when awk returns no line or several lines, so $GITHUB_OUTPUT can receive an ambiguous value. Add explicit error handling around the guard.

🔧 Suggested fix
   job_conclusion() {
     local name=$1 matches
     matches=$(awk -F '\t' -v name="$name" '$1 == name {print $2}' <<<"$jobs")
-    [[ -n "$matches" && "$matches" != *$'\n'* ]]
+    [[ -n "$matches" && "$matches" != *$'\n'* ]] || {
+      printf 'ambiguous or missing job conclusion for %s\n' "$name" >&2
+      exit 1
+    }
     printf '%s\n' "$matches"
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
job_conclusion() {
local name=$1 matches
matches=$(awk -F '\t' -v name="$name" '$1 == name {print $2}' <<<"$jobs")
[[ -n "$matches" && "$matches" != *$'\n'* ]]
printf '%s\n' "$matches"
}
job_conclusion() {
local name=$1 matches
matches=$(awk -F '\t' -v name="$name" '$1 == name {print $2}' <<<"$jobs")
[[ -n "$matches" && "$matches" != *$'\n'* ]] || {
printf 'ambiguous or missing job conclusion for %s\n' "$name" >&2
exit 1
}
printf '%s\n' "$matches"
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/acr-publish.yml around lines 58 - 63, Update
job_conclusion to explicitly check that matches contains exactly one line before
printing it; return a nonzero status when there are zero or multiple matching
jobs, so command substitution and the workflow fail instead of writing an
ambiguous GITHUB_OUTPUT value.

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.

Publish ACR images from the smoke-tested exact-main release artifact

2 participants