You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2026/10/20 10:46:25 UTC
(nuttx) 01/02: .github/workflows: Skip depends-on PRs that are already merged.
This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 4381d999f042ba22bf95a06126b06858e21a5c86
Author: Marco Casaroli <ma...@gmail.com>
AuthorDate: Mon Oct 19 10:21:41 2026 +0200
.github/workflows: Skip depends-on PRs that are already merged.
When a depends-on PR is merged, its commits are in master. Build and
the memory report then cherry-pick the PR head again, the cherry-pick
is empty or conflicts, and Fetch-Source fails. The author must remove
the depends-on line and start CI again.
Read the state of each dependency with the GitHub API. If the PR is
merged and its merge commit is in the checkout, skip the PR. Apply
open PRs, PRs merged into a different branch, and PRs whose merge
commit is not in the checkout as before. If the API call fails, apply
the dependency as before.
A PR that is closed without merge is now an error: CI does not apply
it, and the step fails with "closed without merge; remove it from
depends-on or reopen it". Before, CI applied such a PR silently.
The report marks a skipped dependency with "merged": true. A failure
report marks a closed dependency with "closed": true and the error
code dependency_closed. The comment shows "already merged, skipped",
"closed without merge", and the reason for the failure.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <ma...@gmail.com>
---
.github/workflows/build.yml | 37 ++++++++++++++++++++++++++++++--
.github/workflows/depends-on-comment.yml | 14 ++++++------
.github/workflows/membrowse-report.yml | 22 +++++++++++++++++++
3 files changed, 65 insertions(+), 8 deletions(-)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 84f4a9ffc07..b7c97ffeecd 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -146,6 +146,8 @@ jobs:
- name: Apply depends-on PRs
if: ${{ steps.gittargets.outputs.depends_on != '' }}
shell: bash
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -uo pipefail
@@ -153,9 +155,10 @@ jobs:
git config --global user.name "github-actions"
# Pass only fixed error codes to the trusted comment workflow.
+ # $3 and $4 name a dependency that is closed without merge.
mark_failed() {
echo "::error::could not apply $1 ($2)"
- python3 - "$2" <<'PY'
+ python3 - "$2" "${3:-}" "${4:-}" <<'PY'
import json, sys
p = "depends-on-report/result.json"
try:
@@ -164,6 +167,9 @@ jobs:
d = {"version": 1, "pr_number": None, "head_sha": None, "dependencies": [], "warnings": []}
d["status"] = "failed"
d["error_code"] = sys.argv[1]
+ for dep in d.get("dependencies", []):
+ if [dep.get("repo"), str(dep.get("number"))] == sys.argv[2:4]:
+ dep["closed"] = True
open(p, "w").write(json.dumps(d))
PY
}
@@ -205,8 +211,30 @@ jobs:
fi
DEP_SHA=$(git -C "$REPO_PATH" rev-parse "dep-${DEP_PR_NUM}")
+
+ # Skip a dependency whose merge commit is already in the checkout.
+ # Its commits are in the target branch and cannot be applied again.
+ # A dependency that is closed without merge is an error.
+ if ! DEP_INFO=$(gh api "repos/${DEP_REPO}/pulls/${DEP_PR_NUM}" \
+ --jq 'if .merged then "merged \(.merge_commit_sha)" else .state end'); then
+ echo "::warning::Could not read the state of ${DEP}; applying it."
+ DEP_INFO=""
+ fi
+ read -r DEP_STATE MERGE_SHA <<< "$DEP_INFO"
+ if [ "$DEP_STATE" = "merged" ] && \
+ git -C "$REPO_PATH" merge-base --is-ancestor "$MERGE_SHA" HEAD 2>/dev/null; then
+ echo "Dependency ${DEP} is merged as ${MERGE_SHA}; skipping it"
+ printf '%s\t%s\t%s\tmerged\n' "$DEP_REPO" "$DEP_PR_NUM" "$DEP_SHA" >> depends-on-report/applied.tsv
+ continue
+ fi
+
printf '%s\t%s\t%s\n' "$DEP_REPO" "$DEP_PR_NUM" "$DEP_SHA" >> depends-on-report/applied.tsv
+ if [ "$DEP_STATE" = "closed" ]; then
+ echo "::error::Dependency ${DEP} is closed without merge; remove it from depends-on or reopen it."
+ mark_failed "$DEP" "dependency_closed" "$DEP_REPO" "$DEP_PR_NUM"; exit 1
+ fi
+
# Stop on unrelated histories; HEAD..dep would otherwise include
# every dependency commit and could cherry-pick unrelated changes.
COMMON_BASE=$(git -C "$REPO_PATH" merge-base "dep-${DEP_PR_NUM}" HEAD || true)
@@ -237,12 +265,15 @@ jobs:
python3 - <<'PY'
import json
shas = {}
+ merged = set()
try:
with open("depends-on-report/applied.tsv", encoding="utf-8") as f:
for line in f:
p = line.rstrip("\n").split("\t")
- if len(p) == 3:
+ if len(p) in (3, 4):
shas[(p[0], p[1])] = p[2]
+ if len(p) == 4 and p[3] == "merged":
+ merged.add((p[0], p[1]))
except FileNotFoundError:
pass
with open("depends-on-report/result.json", encoding="utf-8") as f:
@@ -251,6 +282,8 @@ jobs:
key = (dep.get("repo"), str(dep.get("number")))
if key in shas:
dep["head_sha"] = shas[key]
+ if key in merged:
+ dep["merged"] = True
with open("depends-on-report/result.json", "w", encoding="utf-8") as f:
json.dump(d, f)
PY
diff --git a/.github/workflows/depends-on-comment.yml b/.github/workflows/depends-on-comment.yml
index b6ade4d341c..2e515bdfd18 100644
--- a/.github/workflows/depends-on-comment.yml
+++ b/.github/workflows/depends-on-comment.yml
@@ -135,6 +135,10 @@ jobs:
const runUrl = context.payload.workflow_run.html_url;
const shortSha = (s) =>
(typeof s === 'string' && /^[0-9a-f]{7,40}$/i.test(s)) ? ` @ ${s.slice(0, 10)}` : '';
+ const depLine = (d) =>
+ `- https://github.com/${d.repo}/pull/${d.number}${shortSha(d.head_sha)}` +
+ (d.merged === true ? ' (already merged, skipped)' : '') +
+ (d.closed === true ? ' ❌ **closed without merge**' : '');
let body;
if (status === 'ok') {
@@ -142,9 +146,7 @@ jobs:
core.info('status=ok but no valid dependencies after validation; skipping.');
return;
}
- const list = deps
- .map((d) => `- https://github.com/${d.repo}/pull/${d.number}${shortSha(d.head_sha)}`)
- .join('\n');
+ const list = deps.map(depLine).join('\n');
body =
`${marker}\n` +
`### 🔗 Cross-repo PR dependencies\n\n` +
@@ -157,9 +159,7 @@ jobs:
core.info('status=failed but no valid dependencies after validation; skipping.');
return;
}
- const list = deps
- .map((d) => `- https://github.com/${d.repo}/pull/${d.number}${shortSha(d.head_sha)}`)
- .join('\n');
+ const list = deps.map(depLine).join('\n');
// Render only fixed text selected by an allowed error code.
const REASONS = {
fetch_failed: 'the dependency PR could not be fetched (it may not exist)',
@@ -168,6 +168,8 @@ jobs:
cherry_pick_conflict: 'cherry-pick failed (if your PR has merge commits, rebase instead)',
unsupported_repo: 'the dependency repository is not supported',
report_parse_failed: 'the dependency report could not be read',
+ dependency_closed: 'a dependency PR is closed without merge; ' +
+ 'remove it from depends-on or reopen it',
};
const code = typeof report.error_code === 'string' ? report.error_code : '';
const reason = REASONS[code] ? `\n\nReason: ${REASONS[code]}` : '';
diff --git a/.github/workflows/membrowse-report.yml b/.github/workflows/membrowse-report.yml
index 07f35e2adf1..bafc4988e75 100644
--- a/.github/workflows/membrowse-report.yml
+++ b/.github/workflows/membrowse-report.yml
@@ -316,6 +316,28 @@ jobs:
fi
DEP_SHA=$(git -C "$REPO_PATH" rev-parse "dep-${DEP_NUM}")
+
+ # Skip a merged dependency and reject a closed one, as build.yml
+ # does.
+ if ! DEP_INFO=$(gh api "repos/${DEP_REPO}/pulls/${DEP_NUM}" \
+ --jq 'if .merged then "merged \(.merge_commit_sha)" else .state end'); then
+ echo "::warning::Could not read the state of ${DEP}; applying it."
+ DEP_INFO=""
+ fi
+ read -r DEP_STATE MERGE_SHA <<< "$DEP_INFO"
+ if [ "$DEP_STATE" = "merged" ] && \
+ git -C "$REPO_PATH" merge-base --is-ancestor "$MERGE_SHA" HEAD 2>/dev/null; then
+ echo "Dependency ${DEP} is merged as ${MERGE_SHA}; skipping it."
+ echo "- \`${DEP}\` @ \`${DEP_SHA}\` (already merged, skipped)" \
+ >> "${GITHUB_STEP_SUMMARY:-/dev/null}"
+ continue
+ fi
+
+ if [ "$DEP_STATE" = "closed" ]; then
+ echo "::error::Dependency ${DEP} is closed without merge; remove it from depends-on or reopen it."
+ exit 1
+ fi
+
if [ -z "$COMMITS" ]; then
echo "Dependency ${DEP} is already included."
echo "- \`${DEP}\` @ \`${DEP_SHA}\` (already in the checkout)" \