From 9c12d7c0e2c656357aa8fef7222e5131896c4353 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Tue, 13 Oct 2026 10:06:45 -0400 Subject: [PATCH 1/2] Exclude -internal and release/ branches from workflow generator workflow --- ...ithub-actions-workflow-generator.README.md | 17 +----- .../run-github-actions-workflow-generator.yml | 60 ++----------------- 2 files changed, 8 insertions(+), 69 deletions(-) diff --git a/.github/workflows/run-github-actions-workflow-generator.README.md b/.github/workflows/run-github-actions-workflow-generator.README.md index b7624c7..3ecb75d 100644 --- a/.github/workflows/run-github-actions-workflow-generator.README.md +++ b/.github/workflows/run-github-actions-workflow-generator.README.md @@ -4,7 +4,7 @@ Runs the [github-actions-workflow-generator](https://github.com/spring-io/github ## What It Does -For every repository and branch tracked in [`config/projects.json`](../config/projects.json): +For every repository and `.x` branch tracked in [`config/projects.json`](../config/projects.json): 1. Copies `.github/actions/release-train-build/action.yml` and `.github/actions/release-train-test/action.yml` into the target repo from this repo (see [Release Train Actions](#release-train-actions)). 2. Copies `release-train-settings.xml` to the root of the target repo. @@ -15,6 +15,8 @@ The primary Java version passed to the generator is determined per-branch from ` - `8` if JDK 8 is listed in the branch's `jdkVersions` - `17` otherwise +`release/*` and `*-internal` branches are never processed, even when listed in `projects.json`. They are rebased onto the `.x` branches and pick up the regenerated workflow files that way. + ## Triggering the Workflow The workflow is triggered manually via **Actions → Run GitHub Actions Workflow Generator → Run workflow**. @@ -25,7 +27,6 @@ The workflow is triggered manually via **Actions → Run GitHub Actions Workflow |---|---|---|---| | `generator-version` | No | Latest release | Version of `github-actions-workflow-generator` to use (e.g. `0.0.5`). | | `sha` | No | Triggering commit | Commit SHA of this repo to copy release-train action files from. Useful for rolling out a specific version of the build/test logic. | -| `spring-release` | No | _(empty)_ | Spring release train version (e.g. `2026.1`). When set, also processes `release/[version]` branches found in the `spring-io/release-train` README for that version. See [Spring Release Branches](#spring-release-branches). | | `projects` | No | _(empty — all projects)_ | Comma-separated list of Spring Cloud project names to limit the run to (e.g. `spring-cloud-build,spring-cloud-config`). When empty, every project in `projects.json` is processed. | | `dry_run` | No | `true` | When true, reports which repos and branches would be updated and pushes nothing. Uncheck to actually commit and push. | | `token` | No | `GH_ACTIONS_REPO_TOKEN` | GitHub token with write access to all target repos. Falls back to the `GH_ACTIONS_REPO_TOKEN` organisation secret. | @@ -70,18 +71,6 @@ Useful when you want to roll out a specific version of the build/test action log sha: 348109524f9790dc1e20d48043fb1ef4765373b8 ``` -### Include active release-train branches - -``` -spring-release: 2026.1 -``` - -## Spring Release Branches - -When `spring-release` is set, the workflow fetches `README.adoc` from the `spring-io/release-train` repository at the specified ref (e.g. `2026.1`) and scans it for Spring Cloud entries. For each entry it finds a `release/[version]` branch in the corresponding commercial repository and runs the same generator steps against it. - -The primary JDK for a release branch is determined by deriving the parent branch from the version number (e.g. `release/3.1.15` → parent `3.1.x`) and looking up that branch's `jdkVersions` in `projects.json`. - ## Release Train Actions Each target repo receives a copy of the release-train action files directly from this repo. The source file for each action is chosen using a three-level lookup (first match wins): diff --git a/.github/workflows/run-github-actions-workflow-generator.yml b/.github/workflows/run-github-actions-workflow-generator.yml index 64c54b5..067ac69 100644 --- a/.github/workflows/run-github-actions-workflow-generator.yml +++ b/.github/workflows/run-github-actions-workflow-generator.yml @@ -15,11 +15,6 @@ on: required: false type: string default: '' - spring-release: - description: 'Spring release train version (e.g. 2026.1). When set, also processes release/[version] branches found in the spring-io/release-train README.adoc for that version.' - required: false - type: string - default: '' projects: description: 'Comma-separated list of Spring Cloud project names to run against (e.g. spring-cloud-build,spring-cloud-config). When empty, all projects in projects.json are processed.' required: false @@ -74,7 +69,6 @@ jobs: id: build-matrix env: GH_TOKEN: ${{ inputs.token || secrets.GH_ACTIONS_REPO_TOKEN }} - SPRING_RELEASE: ${{ inputs.spring-release }} PROJECTS_FILTER: ${{ inputs.projects }} run: | node - << 'JSEOF' @@ -112,11 +106,11 @@ jobs: const entries = []; const seen = new Set(); - function addEntry(repo, branch, typeKey, projectKey, jdkLookupBranch) { + function addEntry(repo, branch, typeKey, projectKey) { const key = `${repo}@${branch}`; if (seen.has(key)) return; seen.add(key); - const jdks = getJdks(projectKey, typeKey, jdkLookupBranch || branch); + const jdks = getJdks(projectKey, typeKey, branch); entries.push({ repo, branch, primary_jdk: primaryJdk(jdks) }); } @@ -131,58 +125,14 @@ jobs: ? `spring-cloud/${projectKey}-commercial` : `spring-cloud/${projectKey}`; for (const branch of (typeCfg.branches || {}).scheduled || []) { + // release/* and *-internal branches are rebased onto the .x branches and + // pick up the regenerated workflows that way, so never generate them directly. + if (branch.startsWith('release/') || branch.endsWith('-internal')) continue; addEntry(repo, branch, typeKey, projectKey); } } } - // Optionally add release/[version] branches from the Spring release train README - const springRelease = (process.env.SPRING_RELEASE || '').trim(); - if (springRelease) { - let readmeB64; - try { - readmeB64 = execFileSync('gh', [ - 'api', 'repos/spring-io/release-train/contents/README.adoc', - '-X', 'GET', '-f', `ref=${springRelease}`, '--jq', '.content' - ], { encoding: 'utf8' }).trim(); - } catch (err) { - console.error(`Warning: could not fetch README.adoc for spring release ${springRelease}: ${err.message}`); - } - if (readmeB64) { - const content = Buffer.from(readmeB64, 'base64').toString('utf8'); - let currentRepo = null; - let currentProjectKey = null; - for (const line of content.split('\n')) { - if (/^== /.test(line)) { - if (!line.includes('Spring Cloud')) { - currentRepo = null; - currentProjectKey = null; - } - continue; - } - const releasingMatch = line.match( - /\*\*Releasing from:\*\* https:\/\/github\.com\/spring-cloud\/([^\[]+)\[/ - ); - if (releasingMatch) { - const repoName = releasingMatch[1].trim().replace(/\/$/, ''); - currentRepo = `spring-cloud/${repoName}`; - currentProjectKey = repoName.replace(/-commercial$/, ''); - continue; - } - if (currentRepo) { - const versionMatch = line.match(/=== .+ (\d+\.\d+(?:\.\d+(?:\.\d+)?)?)\s*$/); - if (versionMatch) { - const version = versionMatch[1]; - const parts = version.split('.'); - const parentBranch = parts.slice(0, -1).join('.') + '.x'; - if (projectsFilter.size > 0 && !projectsFilter.has(currentProjectKey)) continue; - addEntry(currentRepo, `release/${version}`, 'commercial', currentProjectKey, parentBranch); - } - } - } - } - } - const matrix = { include: entries }; fs.appendFileSync(process.env.GITHUB_OUTPUT, `matrix=${JSON.stringify(matrix)}\n`); console.log(`Matrix built: ${entries.length} entries`); From 537f95f7d3a4e9536e3102649bfa4eca825846c8 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Tue, 13 Oct 2026 16:22:53 -0400 Subject: [PATCH 2/2] Add file changes to workflow summary --- .../generate-workflows-for-branch/action.yml | 15 ++++++++++++++- .../run-github-actions-workflow-generator.yml | 16 +++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/.github/actions/generate-workflows-for-branch/action.yml b/.github/actions/generate-workflows-for-branch/action.yml index 7e5afbe..5106b73 100644 --- a/.github/actions/generate-workflows-for-branch/action.yml +++ b/.github/actions/generate-workflows-for-branch/action.yml @@ -33,6 +33,11 @@ outputs: changed: description: "'true' if workflow files were changed and pushed (or would be, on a dry run), 'false' otherwise" value: ${{ steps.commit.outputs.changed }} + files: + description: > + JSON array of the files that were changed and pushed (or would be, on a dry run), + e.g. [{"status":"M","path":".github/workflows/ci.yml"}]. Empty array when nothing changed. + value: ${{ steps.commit.outputs.files }} runs: using: composite @@ -159,7 +164,15 @@ runs: if git diff --staged --quiet; then echo "No changes to commit for ${{ inputs.repo }}@${{ inputs.branch }}." echo "changed=false" >> "$GITHUB_OUTPUT" - elif [[ "$DRY_RUN" == "true" ]]; then + echo "files=[]" >> "$GITHUB_OUTPUT" + exit 0 + fi + + files=$(git diff --staged --name-status | jq -R -s -c \ + 'split("\n") | map(select(length > 0) | split("\t") | {status: .[0][0:1], path: .[-1]})') + echo "files=${files}" >> "$GITHUB_OUTPUT" + + if [[ "$DRY_RUN" == "true" ]]; then git diff --staged --stat echo "Dry run: would push changes to ${{ inputs.repo }}@${{ inputs.branch }}." echo "changed=true" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/run-github-actions-workflow-generator.yml b/.github/workflows/run-github-actions-workflow-generator.yml index 067ac69..dc06f16 100644 --- a/.github/workflows/run-github-actions-workflow-generator.yml +++ b/.github/workflows/run-github-actions-workflow-generator.yml @@ -170,11 +170,17 @@ jobs: REPO: ${{ matrix.repo }} BRANCH: ${{ matrix.branch }} CHANGED: ${{ steps.generate.outputs.changed }} + FILES: ${{ steps.generate.outputs.files }} run: | safe="${REPO//\//-}-${BRANCH//\//-}" safe="${safe//./-}" echo "safe-name=${safe}" >> "$GITHUB_OUTPUT" - echo '{"repo":"'"$REPO"'","branch":"'"$BRANCH"'","changed":'"${CHANGED:-false}"'}' \ + jq -n -c \ + --arg repo "$REPO" \ + --arg branch "$BRANCH" \ + --argjson changed "${CHANGED:-false}" \ + --argjson files "${FILES:-[]}" \ + '{repo: $repo, branch: $branch, changed: $changed, files: $files}' \ > "result-${safe}.json" - name: Upload result @@ -224,9 +230,13 @@ jobs: if (updated.length > 0) { md += `### ${dryRun ? 'Would update' : 'Updated'} (${updated.length})\n\n`; - md += '| Repository | Branch |\n|---|---|\n'; + const statusLabels = { A: 'added', M: 'modified', D: 'deleted', R: 'renamed', C: 'copied', T: 'type changed' }; + md += '| Repository | Branch | Files |\n|---|---|---|\n'; for (const r of updated) { - md += `| \`${r.repo}\` | \`${r.branch}\` |\n`; + const fileList = (r.files || []) + .map(f => `\`${f.path}\` (${statusLabels[f.status] || f.status})`) + .join('
') || '_unknown_'; + md += `| \`${r.repo}\` | \`${r.branch}\` | ${fileList} |\n`; } md += '\n'; } else {