From c1b398af1c92c057500731023017d207086d6682 Mon Sep 17 00:00:00 2001 From: David <12414531+DavidBellamy@users.noreply.github.com> Date: Fri, 17 Apr 2026 23:34:39 -0700 Subject: [PATCH] ci: daily 2am rebuild + preserve fork-local .github/workflows --- .github/workflows/maintain-deploy.yml | 45 +++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/.github/workflows/maintain-deploy.yml b/.github/workflows/maintain-deploy.yml index 53ba64fb3b..aade7f017c 100644 --- a/.github/workflows/maintain-deploy.yml +++ b/.github/workflows/maintain-deploy.yml @@ -2,7 +2,7 @@ name: Maintain deploy branch on: schedule: - - cron: '*/15 * * * *' + - cron: '0 2 * * *' workflow_dispatch: inputs: force: @@ -31,12 +31,36 @@ jobs: UPSTREAM_SHA=$(gh api "repos/${UPSTREAM}/commits/main" --jq '.sha' 2>/dev/null || echo "unknown") FORK_OWNER="${REPO%%/*}" - PR_STATE=$(gh api "repos/${UPSTREAM}/pulls?state=open&base=main&per_page=100" \ + NOT_BLOCKED='select(([.labels[].name] | index("blocked")) == null)' + + # Branches with open PRs against upstream (no blocked filter; upstream PRs always merge) + UPSTREAM_PR_STATE=$(gh api "repos/${UPSTREAM}/pulls?state=open&base=main&per_page=100" \ --jq "[.[] | select(.head.repo.owner.login == \"${FORK_OWNER}\")] | sort_by(.head.ref) | map(.head.ref + \"=\" + .head.sha) | join(\",\")") - BRANCHES=$(gh api "repos/${UPSTREAM}/pulls?state=open&base=main&per_page=100" \ + UPSTREAM_BRANCHES=$(gh api "repos/${UPSTREAM}/pulls?state=open&base=main&per_page=100" \ --jq "[.[] | select(.head.repo.owner.login == \"${FORK_OWNER}\")] | .[].head.ref" | tr '\n' ' ') + # Branches with open PRs against the fork's own main (fork-only changes), excluding blocked PRs + FORK_PR_STATE=$(gh api "repos/${REPO}/pulls?state=open&base=main&per_page=100" \ + --jq "[.[] | select(.head.repo.full_name == \"${REPO}\") | ${NOT_BLOCKED}] | sort_by(.head.ref) | map(.head.ref + \"=\" + .head.sha) | join(\",\")") + + FORK_BRANCHES=$(gh api "repos/${REPO}/pulls?state=open&base=main&per_page=100" \ + --jq "[.[] | select(.head.repo.full_name == \"${REPO}\") | ${NOT_BLOCKED}] | .[].head.ref" | tr '\n' ' ') + + # Deduplicate: upstream PRs first, then fork-only PRs + BRANCHES="$UPSTREAM_BRANCHES" + for fb in $FORK_BRANCHES; do + if ! echo " $UPSTREAM_BRANCHES " | grep -q " $fb "; then + BRANCHES="$BRANCHES $fb" + fi + done + + # Combine state fingerprints + PR_STATE="${UPSTREAM_PR_STATE}" + if [ -n "$FORK_PR_STATE" ]; then + PR_STATE="${PR_STATE:+${PR_STATE},}${FORK_PR_STATE}" + fi + STATE="${UPSTREAM_SHA}|${PR_STATE}" echo "state=$STATE" >> "$GITHUB_OUTPUT" echo "branches=$BRANCHES" >> "$GITHUB_OUTPUT" @@ -108,6 +132,21 @@ jobs: fi echo "FAILED_BRANCHES=$FAILED" >> "$GITHUB_ENV" + - name: Preserve fork-local .github/workflows + # GitHub Actions only reads workflow files on the branch where the trigger + # fires. Fork-local CI (e.g. release-binary.yml that triggers on push to + # deploy) lives on fork main, not upstream. Overlay fork-main workflows + # onto the deploy tree so those workflows survive the rebuild. + run: | + git fetch origin main + if git ls-tree -r origin/main -- .github/workflows/ 2>/dev/null | grep -q . + then + git checkout origin/main -- .github/workflows/ + git add .github/workflows/ + git diff --cached --quiet || \ + git commit -m "Deploy: preserve fork-local .github/workflows from main" + fi + - name: Stamp fingerprint and push env: STATE: ${{ needs.check.outputs.state }}