Merge pull request #165 from speakeasy-api/guide/issue-164-gmail #25
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Go module regen | |
| # After guides (or schema) land on main, regenerate go/ and open/update a PR. | |
| # The regen branch is machine-owned — do not push human fixes there; fix on a | |
| # follow-up commit via a new guide change or workflow_dispatch after main is fixed. | |
| # Humans merge the PR; go-module-release then cuts go/vX.Y.Z. | |
| on: | |
| push: | |
| branches: [main] | |
| paths: | |
| - 'guides/**' | |
| - 'schema/**' | |
| workflow_dispatch: | |
| concurrency: | |
| group: go-module-regen | |
| cancel-in-progress: false | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| issues: write | |
| jobs: | |
| regen: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Require AGENT_PAT | |
| env: | |
| AGENT_PAT: ${{ secrets.AGENT_PAT }} | |
| run: | | |
| set -euo pipefail | |
| if [ -z "${AGENT_PAT}" ]; then | |
| echo "AGENT_PAT is required so chore/go-module-regen PRs trigger Go module CI." | |
| echo "GITHUB_TOKEN-authored PRs do not fire pull_request workflows." | |
| exit 1 | |
| fi | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.AGENT_PAT }} | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: go/go.mod | |
| cache-dependency-path: | | |
| go/go.mod | |
| go/internal/gen/go.sum | |
| - name: Regenerate publishable tree | |
| working-directory: go/internal/gen | |
| run: go run . | |
| - name: Detect drift | |
| id: drift | |
| run: | | |
| set -euo pipefail | |
| if [ -n "$(git status --porcelain -- go/)" ]; then | |
| echo "dirty=true" >> "$GITHUB_OUTPUT" | |
| git status --porcelain -- go/ | |
| else | |
| echo "dirty=false" >> "$GITHUB_OUTPUT" | |
| echo "go/ already in sync with guides/" | |
| fi | |
| - name: Open or update regen PR | |
| if: steps.drift.outputs.dirty == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.AGENT_PAT }} | |
| BRANCH: chore/go-module-regen | |
| run: | | |
| set -euo pipefail | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git checkout -B "$BRANCH" | |
| git add -A -- go/ | |
| git commit -m "Sync Go module embed with guides." | |
| # Machine-owned branch: lease fails loudly if the remote moved under us. | |
| git fetch origin "refs/heads/${BRANCH}:refs/remotes/origin/${BRANCH}" 2>/dev/null || true | |
| git push -u origin "HEAD:refs/heads/${BRANCH}" --force-with-lease | |
| # Guide-level + other go/ drift vs main (aggregated across open regen PR). | |
| base_guides="${RUNNER_TEMP:-/tmp}/go-module-regen-guides-base.txt" | |
| head_guides="${RUNNER_TEMP:-/tmp}/go-module-regen-guides-head.txt" | |
| git ls-tree -d --name-only "origin/main:go/generated/guides" 2>/dev/null \ | |
| | sort -u > "$base_guides" || : > "$base_guides" | |
| if [ -d go/generated/guides ]; then | |
| find go/generated/guides -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | sort -u > "$head_guides" | |
| else | |
| : > "$head_guides" | |
| fi | |
| mapfile -t added_guides < <(comm -13 "$base_guides" "$head_guides") | |
| mapfile -t removed_guides < <(comm -23 "$base_guides" "$head_guides") | |
| updated_guides=() | |
| while IFS= read -r slug; do | |
| [ -z "$slug" ] && continue | |
| if ! git diff --quiet "origin/main" -- "go/generated/guides/${slug}"; then | |
| updated_guides+=("$slug") | |
| fi | |
| done < <(comm -12 "$base_guides" "$head_guides") | |
| mapfile -t other_files < <( | |
| git diff --name-only "origin/main" -- go/ \ | |
| | grep -v '^go/generated/guides/' \ | |
| | sort -u || true | |
| ) | |
| fmt_backticks() { | |
| local out="" s | |
| for s in "$@"; do | |
| [ -z "$s" ] && continue | |
| if [ -n "$out" ]; then out+=", "; fi | |
| out+="\`${s}\`" | |
| done | |
| printf '%s' "$out" | |
| } | |
| body_file="${RUNNER_TEMP:-/tmp}/go-module-regen-pr.md" | |
| { | |
| cat <<'EOF' | |
| ## Summary | |
| - Regenerated `go/generated` + identity indexes from current `guides/` / `schema/` | |
| - Opened by `go-module-regen` after a guide or schema change landed on `main` | |
| - Branch is machine-owned — don't push fixes here; they'll be overwritten | |
| ## Changes | |
| EOF | |
| if [ "${#added_guides[@]}" -gt 0 ]; then | |
| echo "- **Added guides:** $(fmt_backticks "${added_guides[@]}")" | |
| fi | |
| if [ "${#updated_guides[@]}" -gt 0 ]; then | |
| echo "- **Updated guides:** $(fmt_backticks "${updated_guides[@]}")" | |
| fi | |
| if [ "${#removed_guides[@]}" -gt 0 ]; then | |
| echo "- **Removed guides:** $(fmt_backticks "${removed_guides[@]}")" | |
| fi | |
| if [ "${#other_files[@]}" -gt 0 ]; then | |
| echo "- **Other:** $(fmt_backticks "${other_files[@]}")" | |
| fi | |
| if [ "${#added_guides[@]}" -eq 0 ] \ | |
| && [ "${#updated_guides[@]}" -eq 0 ] \ | |
| && [ "${#removed_guides[@]}" -eq 0 ] \ | |
| && [ "${#other_files[@]}" -eq 0 ]; then | |
| echo "- _(diff vs \`main\` had no classifiable paths)_" | |
| fi | |
| cat <<'EOF' | |
| ## Release | |
| Merging this PR triggers `go-module-release` (patch bump of `go/vX.Y.Z` + GitHub Release), once `go/v0.1.0` exists. | |
| ## Test plan | |
| - [ ] `Go module CI` is green on this PR | |
| - [ ] Spot-check `go/generated` / `index_gen.go` for the guides that changed | |
| EOF | |
| } > "$body_file" | |
| existing="$(gh pr list --head "$BRANCH" --base main --state open --json number --jq '.[0].number // empty')" | |
| if [ -n "$existing" ]; then | |
| echo "Updated existing open PR #$existing for $BRANCH" | |
| gh pr edit "$existing" --title "Sync Go module embed with guides" --body-file "$body_file" | |
| else | |
| gh pr create --base main --head "$BRANCH" \ | |
| --title "Sync Go module embed with guides" \ | |
| --body-file "$body_file" | |
| fi | |
| - name: Report failure | |
| if: failure() | |
| env: | |
| GH_TOKEN: ${{ secrets.AGENT_PAT || secrets.GITHUB_TOKEN }} | |
| RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| run: | | |
| set -euo pipefail | |
| gh label create "go-module:regen-failed" --color "D73A4A" \ | |
| --description "Go module regen workflow failed" 2>/dev/null || true | |
| body_file="${RUNNER_TEMP:-/tmp}/go-module-regen-fail.md" | |
| printf '%s\n' \ | |
| 'Go module regen failed on `main`.' \ | |
| '' \ | |
| "**Workflow run:** ${RUN_URL}" \ | |
| '' \ | |
| 'Fix the guide/schema or generator issue, then re-run **Go module regen** (workflow_dispatch) or merge another guides change.' \ | |
| > "$body_file" | |
| existing="$(gh issue list --label "go-module:regen-failed" --state open --json number --jq '.[0].number // empty')" | |
| if [ -n "$existing" ]; then | |
| gh issue comment "$existing" --body-file "$body_file" | |
| else | |
| gh issue create --title "Go module regen failed" \ | |
| --label "go-module:regen-failed" \ | |
| --body-file "$body_file" | |
| fi |