Skip to content

feat: added script to propagate new version to deco-sites - #1592

Open
aline-pereira wants to merge 2 commits into
mainfrom
feat/propagate-version-to-dependents
Open

feat: added script to propagate new version to deco-sites#1592
aline-pereira wants to merge 2 commits into
mainfrom
feat/propagate-version-to-dependents

Conversation

@aline-pereira

@aline-pereira aline-pereira commented May 20, 2026

Copy link
Copy Markdown
Contributor

What is this Contribution About?

Please provide a brief description of the changes or enhancements you are proposing in this pull request.

Adds a GitHub Actions workflow that automatically opens draft PRs in all deco-sites/* repositories whenever a new stable version of deco-cx/apps is released.

Trigger — fires on every stable version tag push (e.g. 0.151.2), ignoring prereleases (next.*)
Discovery — queries the GitHub code search API to find all repos in the deco-sites org whose deno.json references cdn.jsdelivr.net/gh/deco-cx/apps, so the list stays up to date automatically with no manual maintenance
Propagation — for each repo found, a bash script runs via the GitHub API (no cloning) and:
Reads the current deno.json from main
Replaces the existing apps version with the new one using sed
Creates or reuses the branch chore/bump-apps
Commits the updated file to that branch
Opens a new draft PR if none exists, or updates the title/body and converts the existing PR back to draft if one is already open


Summary by cubic

Automates propagating new stable deco-cx/apps versions to deco-sites/* by opening draft PRs per repo on tag push. Keeps sites in sync and removes manual bumps.

  • New Features
    • Adds propagate.yml workflow that runs on stable tag pushes (e.g. 0.151.2), ignoring next.*.
    • Discovers target repos via GitHub code search for deno.json referencing cdn.jsdelivr.net/gh/deco-cx/apps.
    • propagate.sh updates deno.json, creates/updates chore/bump-apps, commits, and opens or updates a PR, converting it to draft.
    • Ensures and applies the apps-bump label; PR body shows the new CDN URL and links release notes.
    • Skips repos already on the new version or missing the reference; uses the GitHub API only (no cloning) with retries/backoff.

Written for commit 484a4a2. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • New Features
    • Automated version-propagation workflow triggered on release tag pushes
    • Automatic discovery of dependent repositories and creation/updating of bump pull requests
    • Ensures bump branches, draft PRs, and labeling for coordinated cross-repo releases
    • Reliable API retry and logging for robust propagation across repositories

Review Change Stack

@github-actions

Copy link
Copy Markdown
Contributor

Tagging Options

Should a new tag be published when this PR is merged?

  • 👍 for Patch 0.151.2 update
  • 🎉 for Minor 0.152.0 update
  • 🚀 for Major 1.0.0 update

@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds a GitHub Actions workflow and a Bash script to discover deco-sites repositories and propagate a new deco-cx/apps@NEW_VERSION by updating deno.json, managing a bump branch, and creating or updating draft PRs with a label.

Changes

Version Propagation Automation

Layer / File(s) Summary
Script setup and GitHub API helpers
.github/scripts/propagate.sh (lines 1-67)
Strict Bash execution, required env validation, branch/label/CDN/API constants, temp-dir cleanup, logging, and REST helper + retry/backoff.
Main branch content validation and early exit
.github/scripts/propagate.sh (lines 69-97)
Fetches deno.json from main, verifies cdn.jsdelivr.net/gh/deco-cx/apps@ pattern, rewrites to NEW_VERSION, and exits if unchanged.
Working branch provisioning and state tracking
.github/scripts/propagate.sh (lines 98-133)
Ensures chore/bump-apps branch exists (creates from main if missing) and reads branch file content/SHA for comparison.
Conditional file update on branch
.github/scripts/propagate.sh (lines 134-152)
Skips when branch content matches rewritten content; otherwise base64-encodes and PUTs updated deno.json to the branch.
Label creation and ensure
.github/scripts/propagate.sh (lines 154-162)
Ensures apps-bump label exists, tolerating pre-existence errors (422) and continuing with warnings on other non-201 responses.
PR lifecycle: update/create and draft conversion
.github/scripts/propagate.sh (lines 163-227)
Lists open PRs for the branch, patches title/body and adds label to existing PRs (attempting GraphQL draft conversion), or creates a new draft PR and applies the label; logs final completion.
Workflow discovery and matrix dispatch
.github/workflows/propagate.yml (lines 1-45)
Triggers on semantic-version tag pushes, searches deco-sites for deno.json, deduplicates {owner,repo} pairs, outputs sites, and runs propagate.sh per site via matrix with NEW_VERSION and SITES_PAT.

🎯 4 (Complex) | ⏱️ ~60 minutes

🐰 A rabbit hops through versioned trees,
discovering sites with quiet breeze,
branches made and PRs set right,
labels gleam beneath the night,
version bumps tucked in soft moonlight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.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 accurately summarizes the main change: adding a script to propagate new versions to deco-sites repositories.
Description check ✅ Passed The description provides comprehensive details about the contribution, including trigger behavior, discovery mechanism, and propagation logic, but is missing the Issue Link section.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 feat/propagate-version-to-dependents

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


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 and usage tips.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/propagate.yml (1)

1-41: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Define least-privilege workflow permissions explicitly.

No permissions: block is defined, so the workflow inherits default token scopes. That is broader than needed for this job. The workflow only uses actions/checkout@v4 to retrieve the propagate script; please restrict GITHUB_TOKEN scopes explicitly.

Suggested hardening
 name: Propagate version to dependent sites
 
 on:
   push:
     tags:
       - '[0-9]+.[0-9]+.[0-9]+'   # stable versions only, ignores next.*
+
+permissions:
+  contents: read
🤖 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/propagate.yml around lines 1 - 41, Add an explicit
permissions block at the top of the workflow to enforce least-privilege (rather
than inheriting broad defaults); set only the minimal scopes needed by the jobs
(e.g., permissions: contents: read) since the job only uses actions/checkout@v4
and the GH CLI call uses a separate SITES_PAT, and ensure this permissions block
applies to the discover and propagate jobs that reference
GH_TOKEN/NEW_VERSION/SITE_OWNER/SITE_REPO.
🤖 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/scripts/propagate.sh:
- Around line 104-116: The code assumes the new branch has MAIN_FILE_SHA but if
main moved the PUT will use a stale sha; after creating the ref (create_body /
CREATE_REF_FILE) fetch the actual branch file SHA and assign it to
BRANCH_FILE_SHA before performing the PUT. Concretely: use api_retry to GET the
branch ref or the target file contents for refs/heads/${BRANCH_NAME} (e.g. GET
"/repos/${REPO}/contents/${TARGET_FILE}?ref=${BRANCH_NAME}" or GET
"/repos/${REPO}/git/refs/heads/${BRANCH_NAME}") and extract the .sha into
BRANCH_FILE_SHA (replacing the current assignment
BRANCH_FILE_SHA="${MAIN_FILE_SHA}") so the subsequent update uses the fresh SHA.
- Around line 180-210: The update branch that handles existing PRs (when
PR_NUMBER is set) never applies the label, so add the same labeling logic used
in the creation branch: construct add_label_body (using LABEL_NAME), set
ADD_LABEL_FILE in TMP_DIR, call api_retry POST
"/repos/${REPO}/issues/${PR_NUMBER}/labels" with that body, capture status and
log a warning on non-200; place this after the PR update/convert-to-draft steps
near the block that references PR_NUMBER, PR_NODE_ID, api_retry and PATCH_FILE
so reused PRs receive the label.
- Line 22: The helper log() currently writes to stdout so outputs get captured
into status=$(api_retry ...); change log() to write to stderr (e.g., use echo
... >&2) so retry/debug messages do not contaminate the captured status used in
comparisons; update the log() definition and keep existing callers (api_retry
and anywhere status is captured) unchanged.
- Around line 188-193: The GraphQL mutation built in draft_query uses string
interpolation and doesn't quote the ID and also ignores GraphQL errors; change
draft_query to use a variables-based mutation (e.g., mutation
ConvertToDraft($id: ID!) { convertPullRequestToDraft(input: {pullRequestId:
$id}) { pullRequest { isDraft } } } with a separate variables object containing
PR_NODE_ID) and send both the query and variables to api_retry, then after
api_retry returns (writing to DRAFT_FILE) parse the JSON response and check for
a non-empty .errors array in DRAFT_FILE in addition to the HTTP status; if
errors exist or status != 200, call log with the error details (and consider
failing/exit) so convertPullRequestToDraft failures aren't silent.

In @.github/workflows/propagate.yml:
- Line 33: Update the GitHub Actions checkout step that currently uses
"actions/checkout@v4" to pin the action to a specific commit SHA and disable
token persistence: replace the unpinned reference with the full commit SHA for
actions/checkout and add the input "persist-credentials: false" to the checkout
step so credentials are not stored in the workspace; locate the checkout step
(uses: actions/checkout@v4) and modify it accordingly.

---

Outside diff comments:
In @.github/workflows/propagate.yml:
- Around line 1-41: Add an explicit permissions block at the top of the workflow
to enforce least-privilege (rather than inheriting broad defaults); set only the
minimal scopes needed by the jobs (e.g., permissions: contents: read) since the
job only uses actions/checkout@v4 and the GH CLI call uses a separate SITES_PAT,
and ensure this permissions block applies to the discover and propagate jobs
that reference GH_TOKEN/NEW_VERSION/SITE_OWNER/SITE_REPO.
🪄 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

Run ID: fb66a21a-38dd-4f76-aa4e-d1ec76250339

📥 Commits

Reviewing files that changed from the base of the PR and between bb78556 and 9533455.

📒 Files selected for processing (2)
  • .github/scripts/propagate.sh
  • .github/workflows/propagate.yml

Comment thread .github/scripts/propagate.sh Outdated
Comment thread .github/scripts/propagate.sh Outdated
Comment thread .github/scripts/propagate.sh
Comment thread .github/scripts/propagate.sh Outdated
Comment on lines +188 to +193
if [[ -n "${PR_NODE_ID}" ]]; then
DRAFT_FILE="${TMP_DIR}/draft.json"
draft_query=$(jq -n --arg id "${PR_NODE_ID}" \
'{query: "mutation { convertPullRequestToDraft(input: {pullRequestId: \($id)}) { pullRequest { isDraft } } }"}')
status=$(api_retry POST "/graphql" "${draft_query}" "${DRAFT_FILE}")
[[ "${status}" == "200" ]] || log " Warning: could not convert PR to draft (HTTP ${status})"

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

jq -n --arg id 'PR_kwDOExample' \
  '{query: "mutation { convertPullRequestToDraft(input: {pullRequestId: \($id)}) { pullRequest { isDraft } } }"}' \
  | jq -r '.query'

# Expected: the rendered query contains `pullRequestId: PR_kwDOExample`
# without quotes, which is not a valid GraphQL string literal.

Repository: deco-cx/apps

Length of output: 163


🏁 Script executed:

# Read the actual file to see the context
cat -n .github/scripts/propagate.sh | sed -n '180,200p'

Repository: deco-cx/apps

Length of output: 1345


🏁 Script executed:

# Check if there are any tests for this script
fd -e sh -e bash -e test | xargs grep -l "propagate" | head -10

Repository: deco-cx/apps

Length of output: 38


🏁 Script executed:

# Search for other GraphQL mutations in the codebase to see patterns
rg "graphql.*mutation" --type sh -A 2 -B 2

Repository: deco-cx/apps

Length of output: 205


🏁 Script executed:

# Find and examine the api_retry function
rg "api_retry" -A 10 .github/scripts/propagate.sh

Repository: deco-cx/apps

Length of output: 5726


🏁 Script executed:

# Look for GraphQL query patterns in the file
cat -n .github/scripts/propagate.sh | grep -i "query\|graphql" -B 2 -A 2

Repository: deco-cx/apps

Length of output: 673


Fix invalid GraphQL mutation syntax and add error handling.

The GraphQL mutation uses string interpolation \($id) which produces an unquoted ID value (e.g., pullRequestId: PR_kwDOExample). GitHub's GraphQL API requires ID arguments as quoted strings. Additionally, error handling only checks the HTTP status code—GraphQL errors in the response body are ignored, causing silent failures when the mutation fails.

Use GraphQL variables instead of string interpolation, and inspect .errors in the response:

Suggested fix
-    draft_query=$(jq -n --arg id "${PR_NODE_ID}" \
-      '{query: "mutation { convertPullRequestToDraft(input: {pullRequestId: \($id)}) { pullRequest { isDraft } } }"}')
+    draft_query=$(jq -n --arg id "${PR_NODE_ID}" '
+      {
+        query: "mutation($id: ID!) { convertPullRequestToDraft(input: { pullRequestId: $id }) { pullRequest { isDraft } } }",
+        variables: { id: $id }
+      }')
     status=$(api_retry POST "/graphql" "${draft_query}" "${DRAFT_FILE}")
-    [[ "${status}" == "200" ]] || log "  Warning: could not convert PR to draft (HTTP ${status})"
+    if [[ "${status}" != "200" ]] || jq -e '.errors? // [] | length > 0' "${DRAFT_FILE}" >/dev/null; then
+      fail "Failed to convert PR to draft" "${DRAFT_FILE}"
+    fi
🤖 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/propagate.sh around lines 188 - 193, The GraphQL mutation
built in draft_query uses string interpolation and doesn't quote the ID and also
ignores GraphQL errors; change draft_query to use a variables-based mutation
(e.g., mutation ConvertToDraft($id: ID!) { convertPullRequestToDraft(input:
{pullRequestId: $id}) { pullRequest { isDraft } } } with a separate variables
object containing PR_NODE_ID) and send both the query and variables to
api_retry, then after api_retry returns (writing to DRAFT_FILE) parse the JSON
response and check for a non-empty .errors array in DRAFT_FILE in addition to
the HTTP status; if errors exist or status != 200, call log with the error
details (and consider failing/exit) so convertPullRequestToDraft failures aren't
silent.

Comment thread .github/workflows/propagate.yml Outdated

@cubic-dev-ai cubic-dev-ai 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.

2 issues found across 2 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread .github/scripts/propagate.sh Outdated
Comment thread .github/workflows/propagate.yml

@cubic-dev-ai cubic-dev-ai 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.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".github/scripts/propagate.sh">

<violation number="1" location=".github/scripts/propagate.sh:121">
P1: Content source stale after branch refresh. SHA comes from new branch, but NEW_CONTENT still from old main snapshot. This can overwrite newer deno.json edits. Rebuild NEW_CONTENT from branch content before commit.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

BRANCH_FILE="${TMP_DIR}/branch-file.json"
status=$(api_retry GET "/repos/${REPO}/contents/${APP_PATH}?ref=${BRANCH_NAME}" "" "${BRANCH_FILE}")
[[ "${status}" == "200" ]] || fail "Failed to read ${APP_PATH} from ${BRANCH_NAME} (HTTP ${status})" "${BRANCH_FILE}"
BRANCH_FILE_SHA=$(jq -r '.sha' "${BRANCH_FILE}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: Content source stale after branch refresh. SHA comes from new branch, but NEW_CONTENT still from old main snapshot. This can overwrite newer deno.json edits. Rebuild NEW_CONTENT from branch content before commit.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/scripts/propagate.sh, line 121:

<comment>Content source stale after branch refresh. SHA comes from new branch, but NEW_CONTENT still from old main snapshot. This can overwrite newer deno.json edits. Rebuild NEW_CONTENT from branch content before commit.</comment>

<file context>
@@ -113,7 +113,12 @@ if [[ "${status}" == "404" ]]; then
+  BRANCH_FILE="${TMP_DIR}/branch-file.json"
+  status=$(api_retry GET "/repos/${REPO}/contents/${APP_PATH}?ref=${BRANCH_NAME}" "" "${BRANCH_FILE}")
+  [[ "${status}" == "200" ]] || fail "Failed to read ${APP_PATH} from ${BRANCH_NAME} (HTTP ${status})" "${BRANCH_FILE}"
+  BRANCH_FILE_SHA=$(jq -r '.sha' "${BRANCH_FILE}")
 
 elif [[ "${status}" == "200" ]]; then
</file context>
Suggested change
BRANCH_FILE_SHA=$(jq -r '.sha' "${BRANCH_FILE}")
BRANCH_FILE_SHA=$(jq -r '.sha' "${BRANCH_FILE}")
CONTENT_ON_BRANCH="${TMP_DIR}/branch-content.txt"
jq -r '.content' "${BRANCH_FILE}" | base64 -d > "${CONTENT_ON_BRANCH}"
sed "s|${CDN_PATTERN}[^/]*/|${CDN_PATTERN}${NEW_VERSION}/|g" "${CONTENT_ON_BRANCH}" > "${NEW_CONTENT}"

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 3

🤖 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/scripts/propagate.sh:
- Around line 198-208: Ensure the script enforces that reopened PRs are actually
converted to draft: before running the mutation, query the PR's current isDraft
state (using PR_NODE_ID) and skip the mutation if it's already true; if not
already draft, run the draft mutation (as currently done via draft_query and
api_retry) and then verify the mutation result by checking DRAFT_FILE for
isDraft === true (not just absence of HTTP 200 or errors). If the post-mutation
check fails, call log with a clear error and exit non‑zero so the job fails;
reference PR_NODE_ID, DRAFT_FILE, draft_query, api_retry and log when
implementing these checks.
- Around line 117-121: The script currently only refreshes BRANCH_FILE_SHA but
continues to use NEW_CONTENT built from the earlier main snapshot, risking
overwrites; update the logic after obtaining BRANCH_FILE (and BRANCH_FILE_SHA)
to decode the file contents from BRANCH_FILE (e.g. base64-decode the .content
field), regenerate NEW_CONTENT from that decoded branch snapshot (rather than
the previous main snapshot), and then perform the PUT using the regenerated
NEW_CONTENT and BRANCH_FILE_SHA so the commit is based on the actual branch
snapshot.

In @.github/workflows/propagate.yml:
- Line 6: The push.tags pattern "[0-9]+.[0-9]+.[0-9]+" is written as a regex but
GitHub Actions uses glob syntax; replace that pattern with a proper glob such as
"*.*.*" or "v*" (or simply "*") in the push.tags entry and add a workflow step
that validates the actual tag value using a regex check (e.g., in a run step
using bash or node) if you need to enforce semantic-versioning; update the
pattern in the file and add the validation step to avoid relying on regex in
push.tags.
🪄 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

Run ID: 9994d4bc-46a8-48f3-af0b-ab1d08312fc8

📥 Commits

Reviewing files that changed from the base of the PR and between 9533455 and 484a4a2.

📒 Files selected for processing (2)
  • .github/scripts/propagate.sh
  • .github/workflows/propagate.yml

Comment on lines +117 to +121
# Re-fetch SHA from the new branch (main may have moved since we last read it)
BRANCH_FILE="${TMP_DIR}/branch-file.json"
status=$(api_retry GET "/repos/${REPO}/contents/${APP_PATH}?ref=${BRANCH_NAME}" "" "${BRANCH_FILE}")
[[ "${status}" == "200" ]] || fail "Failed to read ${APP_PATH} from ${BRANCH_NAME} (HTTP ${status})" "${BRANCH_FILE}"
BRANCH_FILE_SHA=$(jq -r '.sha' "${BRANCH_FILE}")

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.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Rebuild from the branch snapshot, not the earlier main snapshot.

These lines refresh only BRANCH_FILE_SHA. If main changes between Line 71 and Line 114, the later PUT writes NEW_CONTENT generated from the old main file onto a branch created from the newer main head, reverting unrelated deno.json edits. Decode BRANCH_FILE here and regenerate NEW_CONTENT from that content before committing.

Suggested fix
   BRANCH_FILE="${TMP_DIR}/branch-file.json"
   status=$(api_retry GET "/repos/${REPO}/contents/${APP_PATH}?ref=${BRANCH_NAME}" "" "${BRANCH_FILE}")
   [[ "${status}" == "200" ]] || fail "Failed to read ${APP_PATH} from ${BRANCH_NAME} (HTTP ${status})" "${BRANCH_FILE}"
   BRANCH_FILE_SHA=$(jq -r '.sha' "${BRANCH_FILE}")
+  CONTENT_ON_BRANCH="${TMP_DIR}/branch-content.txt"
+  jq -r '.content' "${BRANCH_FILE}" | base64 -d > "${CONTENT_ON_BRANCH}"
+  sed "s|${CDN_PATTERN}[^/]*/|${CDN_PATTERN}${NEW_VERSION}/|g" "${CONTENT_ON_BRANCH}" > "${NEW_CONTENT}"
🤖 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/propagate.sh around lines 117 - 121, The script currently
only refreshes BRANCH_FILE_SHA but continues to use NEW_CONTENT built from the
earlier main snapshot, risking overwrites; update the logic after obtaining
BRANCH_FILE (and BRANCH_FILE_SHA) to decode the file contents from BRANCH_FILE
(e.g. base64-decode the .content field), regenerate NEW_CONTENT from that
decoded branch snapshot (rather than the previous main snapshot), and then
perform the PUT using the regenerated NEW_CONTENT and BRANCH_FILE_SHA so the
commit is based on the actual branch snapshot.

Comment on lines +198 to +208
# Convert to draft via GraphQL (using variables to avoid unquoted ID)
if [[ -n "${PR_NODE_ID}" ]]; then
DRAFT_FILE="${TMP_DIR}/draft.json"
draft_query=$(jq -n --arg id "${PR_NODE_ID}" \
'{query: "mutation ConvertToDraft($id: ID!) { convertPullRequestToDraft(input: {pullRequestId: $id}) { pullRequest { isDraft } } }", variables: {id: $id}}')
status=$(api_retry POST "/graphql" "${draft_query}" "${DRAFT_FILE}")
if [[ "${status}" != "200" ]]; then
log " Warning: could not convert PR to draft (HTTP ${status})"
elif jq -e '.errors' "${DRAFT_FILE}" > /dev/null 2>&1; then
log " Warning: GraphQL error: $(jq -r '.errors[0].message // "unknown"' "${DRAFT_FILE}")"
fi

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Enforce the draft postcondition here.

Line 204 only warns on failure, so the job can succeed with a reused PR still ready for review. Since converting reopened PRs back to draft is part of this workflow's contract, skip this mutation when the PR is already draft and otherwise fail if the mutation does not leave it in draft state.

🤖 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/propagate.sh around lines 198 - 208, Ensure the script
enforces that reopened PRs are actually converted to draft: before running the
mutation, query the PR's current isDraft state (using PR_NODE_ID) and skip the
mutation if it's already true; if not already draft, run the draft mutation (as
currently done via draft_query and api_retry) and then verify the mutation
result by checking DRAFT_FILE for isDraft === true (not just absence of HTTP 200
or errors). If the post-mutation check fails, call log with a clear error and
exit non‑zero so the job fails; reference PR_NODE_ID, DRAFT_FILE, draft_query,
api_retry and log when implementing these checks.

on:
push:
tags:
- "[0-9]+.[0-9]+.[0-9]+" # stable versions only, ignores next.*

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.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

GitHub Actions official docs for on.push.tagspattern syntax: are these glob patterns or regexes, and would[0-9]+.[0-9]+.[0-9]+match0.151.2?

💡 Result:

GitHub Actions on.push.tags filters use glob patterns, not regular expressions [1][2][3]. The supported glob patterns allow for wildcard characters such as * (matches zero or more characters, excluding directory separators) and `` (matches zero or more characters, including directory separators) [1, 2, 4]. Because these are glob patterns, the syntax [0-9]+.[0-9]+.[0-9]+ will not function as a regex [11]. In a glob context, brackets `[]` are typically treated as literal characters or as part of glob character matching (depending on the implementation), but they do not provide the same quantifiers (`+`) or grouping capabilities found in regex [4][3]. Specifically, the pattern `[0-9]+.[0-9]+.[0-9]+` will not correctly match `0.151.2` as a semantic version pattern [3]. If you need to trigger a workflow based on complex versioning logic, the recommended approach is to use a broader glob pattern (such as `` or a prefix match like `v`) to trigger the workflow, and then use an `if` conditional within your job to validate the tag against a regex using the GitHub Actions context [5][6]: jobs: build: if: ${{ github.ref_type == 'tag' && contains(github.ref_name, 'your-regex-logic-here') }} # Alternatively, use a script step to perform regex validation runs-on: ubuntu-latest steps: - name: Validate Tag if: ${{ startsWith(github.ref, 'refs/tags/') }} run: | if [[ "${{ github.ref_name }}" =~ ^[0-9]+.[0-9]+.[0-9]+$ ]]; then echo "Tag matches" else echo "Tag does not match" exit 1 fi [6]

Citations:


Use a GitHub Actions tag glob, not a regex pattern.

push.tags patterns use glob syntax, not regular expressions. The pattern [0-9]+.[0-9]+.[0-9]+ will not match semantic version tags like 0.151.2 because the + characters are treated as literals. Replace with a valid glob (e.g., v* or *) and validate the tag inside the workflow with a regex check or script step.

🤖 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/propagate.yml at line 6, The push.tags pattern
"[0-9]+.[0-9]+.[0-9]+" is written as a regex but GitHub Actions uses glob
syntax; replace that pattern with a proper glob such as "*.*.*" or "v*" (or
simply "*") in the push.tags entry and add a workflow step that validates the
actual tag value using a regex check (e.g., in a run step using bash or node) if
you need to enforce semantic-versioning; update the pattern in the file and add
the validation step to avoid relying on regex in push.tags.

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.

1 participant