Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 56 additions & 2 deletions .github/workflows/rc-docs-sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ jobs:

input_product = os.environ.get("INPUT_PRODUCT") or ""
input_rc_tag = os.environ.get("INPUT_RC_TAG") or ""
queue, seed_actions = [], []
queue, seed_actions, superseded_actions = [], [], []

products_to_sweep = [input_product] if input_product else list(PRODUCTS.keys())
for slug in products_to_sweep:
Expand Down Expand Up @@ -165,6 +165,34 @@ jobs:
continue
last_key = sort_key(processed_markers[-1])
rcs_to_process = sorted([t for t in rc_tags if sort_key(t) > last_key], key=sort_key)
# Within each base version, collapse to just the latest unprocessed
# RC and mark earlier ones in that group as superseded — earlier RCs
# in the same base would otherwise fan out as separate matrix
# entries and produce duplicate PRs (see GH run 26561237947, which
# opened #400 and #401 for the same filter introduced in 27.8-RC1
# and re-emitted in 27.8-RC2). Collapsing is *per base version* so
# if two cycles' RCs are simultaneously unprocessed (e.g. workflow
# missed 27.8-RC1 and 27.9-RC1), each base still gets its own
# queue entry diffed against its own previous-stable. Explicit
# workflow_dispatch with input_rc_tag bypasses this collapse.
if len(rcs_to_process) > 1:
by_base = {}
for rc in rcs_to_process:
by_base.setdefault(base_version(rc), []).append(rc)
collapsed = []
for base, group in by_base.items():
group_sorted = sorted(group, key=sort_key)
latest_in_group = group_sorted[-1]
for skipped in group_sorted[:-1]:
superseded_actions.append({
"issue": tracking_issue,
"product": slug,
"rc_tag": skipped,
"superseded_by": latest_in_group,
"display_name": product["display_name"],
})
collapsed.append(latest_in_group)
rcs_to_process = sorted(collapsed, key=sort_key)

for rc_tag in rcs_to_process:
# Prefer the most recent already-processed RC of the same base version as
Expand Down Expand Up @@ -200,13 +228,14 @@ jobs:
"tracking_issue": tracking_issue,
})

print(json.dumps({"queue": queue, "seeds": seed_actions}))
print(json.dumps({"queue": queue, "seeds": seed_actions, "superseded": superseded_actions}))
PY
cat queue.json
# Emit queue as compact JSON for matrix consumption.
echo "queue_json=$(jq -c '.queue' queue.json)" >> "$GITHUB_OUTPUT"
echo "count=$(jq '.queue | length' queue.json)" >> "$GITHUB_OUTPUT"
echo "seed_count=$(jq '.seeds | length' queue.json)" >> "$GITHUB_OUTPUT"
echo "superseded_count=$(jq '.superseded | length' queue.json)" >> "$GITHUB_OUTPUT"

- name: Seed first-run tracking issues
if: steps.queue.outputs.seed_count != '0'
Expand All @@ -225,6 +254,31 @@ jobs:
**First-run seed for ${display}** — RC tag \`${rc_tag}\` recorded as the baseline. No historical RCs will be processed automatically. To backfill a specific RC, use \`workflow_dispatch\` with \`product=${product}\` and the desired \`rc_tag\`."
done

- name: Mark superseded RCs (latest-only-per-run)
if: steps.queue.outputs.superseded_count != '0'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
run: |
set -euo pipefail
jq -c '.superseded[]' queue.json | while read -r entry; do
issue=$(echo "$entry" | jq -r .issue)
product=$(echo "$entry" | jq -r .product)
rc_tag=$(echo "$entry" | jq -r .rc_tag)
superseded_by=$(echo "$entry" | jq -r .superseded_by)
display=$(echo "$entry" | jq -r .display_name)
base_version="${rc_tag%-RC*}"
# Idempotency: skip if a marker for this RC already exists.
if gh issue view "$issue" --json comments --jq '.comments[].body' \
| grep -Eq "<!--[[:space:]]*rc-docs-sync:v1[[:space:]]+product=${product}[[:space:]]+rc_tag=${rc_tag}[[:space:]]*-->"; then
echo "Marker for ${product} ${rc_tag} already exists; skipping superseded marker."
continue
fi
gh issue comment "$issue" --body "<!-- rc-docs-sync:v1 product=${product} rc_tag=${rc_tag} -->
Comment thread
enricobattocchi marked this conversation as resolved.
Outdated

**${display} ${base_version}** (RC \`${rc_tag}\`) — superseded by \`${superseded_by}\` in the same sync run. The later RC was processed against the same diff base, so any net public-surface changes are covered there. This RC was not individually processed."
done

- name: Note when queue is empty
if: steps.queue.outputs.count == '0'
run: echo "No new RC tags to process this run."
Expand Down