2026-04-22-whats-new-sync

Whats-New Sync Workflow Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Add a GitHub Actions workflow to cloudzero-documentation that opens a PR in feature-web-apps whenever docs/Introduction/whats-new.md changes on v1.0.

Architecture: A single workflow file triggers on push to v1.0 (path-filtered) and workflow_dispatch. It strips YAML frontmatter with awk, generates a cross-repo GitHub App token, clones feature-web-apps, writes the file, and opens a PR via gh CLI if the content differs.

Tech Stack: GitHub Actions, actions/checkout@v4, actions/create-github-app-token@v1, gh CLI (pre-installed on ubuntu-latest), awk, git


Task 1: Verify frontmatter stripping locally

Files:

  • Read: docs/Introduction/whats-new.md

  • Step 1: Run the awk strip command against the real file

awk 'BEGIN{f=0} /^---/{f++; next} f>=2{print}' \
  docs/Introduction/whats-new.md | head -15

Expected output: the first lines of rendered markdown content (starting with the banner image line), with NO --- lines and NO YAML keys like title:, slug:, etc.

  • Step 2: Confirm the result looks clean

If the output starts with ![What's New At CloudZero] and contains no YAML, the strip logic is correct. If not, the frontmatter delimiter in the file may differ — inspect with head -10 docs/Introduction/whats-new.md and adjust the awk pattern before continuing.


Task 2: Create the workflow file

Files:

  • Create: .github/workflows/sync-whats-new.yml

  • Step 1: Create the workflow file with the following content

name: Sync What's New to feature-web-apps

on:
  push:
    branches:
      - v1.0
    paths:
      - 'docs/Introduction/whats-new.md'
  workflow_dispatch:
    inputs:
      reason:
        description: 'Reason for manual trigger'
        required: false
        default: 'Manual sync'

concurrency:
  group: sync-whats-new
  cancel-in-progress: true

permissions:
  contents: read

jobs:
  sync:
    name: Sync What's New
    runs-on: ubuntu-latest
    timeout-minutes: 10

    steps:
      - name: Checkout cloudzero-documentation
        uses: actions/checkout@v4

      - name: Strip frontmatter
        run: |
          awk 'BEGIN{f=0} /^---/{f++; next} f>=2{print}' \
            docs/Introduction/whats-new.md > /tmp/whats-new-stripped.md
          echo "=== Stripped preview ==="
          head -10 /tmp/whats-new-stripped.md

      - name: Generate GitHub App token
        id: app-token
        uses: actions/create-github-app-token@v1
        with:
          app-id: ${{ secrets.CLOUDZERO_GITHUB_ACTIONS_APP_ID }}
          private-key: ${{ secrets.CLOUDZERO_GITHUB_ACTIONS_APP_PRIVATE_KEY }}
          owner: Cloudzero
          repositories: feature-web-apps

      - name: Clone feature-web-apps
        run: |
          git clone \
            https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/Cloudzero/feature-web-apps.git \
            /tmp/feature-web-apps

      - name: Write stripped content
        run: |
          mkdir -p /tmp/feature-web-apps/libs/ui/help-guidance/src/data
          cp /tmp/whats-new-stripped.md \
            /tmp/feature-web-apps/libs/ui/help-guidance/src/data/whats-new.md

      - name: Check for changes
        id: changes
        run: |
          cd /tmp/feature-web-apps
          if [ -z "$(git status --porcelain libs/ui/help-guidance/src/data/whats-new.md)" ]; then
            echo "has_changes=false" >> "$GITHUB_OUTPUT"
            echo "No changes detected — skipping PR"
          else
            echo "has_changes=true" >> "$GITHUB_OUTPUT"
            echo "Changes detected:"
            git diff libs/ui/help-guidance/src/data/whats-new.md
          fi

      - name: Create branch and push
        id: commit
        if: steps.changes.outputs.has_changes == 'true'
        env:
          COMMIT_SHA: ${{ github.sha }}
        run: |
          cd /tmp/feature-web-apps
          SHORT_SHA="${COMMIT_SHA:0:7}"
          BRANCH="sync/whats-new-${SHORT_SHA}"

          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"

          git checkout -b "$BRANCH"
          git add libs/ui/help-guidance/src/data/whats-new.md
          git commit -m "chore: sync whats-new from cloudzero-documentation (${SHORT_SHA})"
          git push origin "$BRANCH"

          echo "branch=${BRANCH}" >> "$GITHUB_OUTPUT"

      - name: Open pull request
        if: steps.changes.outputs.has_changes == 'true'
        env:
          GH_TOKEN: ${{ steps.app-token.outputs.token }}
          BRANCH: ${{ steps.commit.outputs.branch }}
          COMMIT_SHA: ${{ github.sha }}
        run: |
          SHORT_SHA="${COMMIT_SHA:0:7}"
          gh pr create \
            --repo Cloudzero/feature-web-apps \
            --base main \
            --head "$BRANCH" \
            --title "chore: sync whats-new from cloudzero-documentation (${SHORT_SHA})" \
            --body "Automated sync of What's New content from cloudzero-documentation.

          Source commit: https://github.com/Cloudzero/cloudzero-documentation/commit/${COMMIT_SHA}

          This PR was opened automatically by the sync-whats-new workflow."
  • Step 2: Validate the YAML syntax
python3 -c "import yaml; yaml.safe_load(open('.github/workflows/sync-whats-new.yml'))" && echo "YAML valid"

Expected: YAML valid

If you get a parse error, check indentation — YAML is sensitive to mixed tabs/spaces.


Task 3: Commit and push

Files:

  • Modify: .github/workflows/sync-whats-new.yml (committed)

  • Step 1: Stage and commit the workflow

git add .github/workflows/sync-whats-new.yml
git commit -m "feat: add sync-whats-new workflow to open PR in feature-web-apps on change"

Expected: commit succeeds on branch v1.0 (or your working branch).

  • Step 2: Push to remote
git push

Task 4: Verify the GitHub App has access (prerequisite check)

Before triggering the workflow, confirm the GitHub App can write to feature-web-apps. This is a one-time setup check, not a code step.

  • Step 1: Check GitHub App repository access

In GitHub: go to your organization's GitHub Apps settings → find the app identified by CLOUDZERO_GITHUB_ACTIONS_APP_ID → confirm feature-web-apps is listed under repository access.

If it is not listed, add it. The app needs Contents: Read & write and Pull requests: Read & write on feature-web-apps.

  • Step 2: Confirm secrets exist in cloudzero-documentation

In GitHub: cloudzero-documentation repo → Settings → Secrets and variables → Actions. Confirm both CLOUDZERO_GITHUB_ACTIONS_APP_ID and CLOUDZERO_GITHUB_ACTIONS_APP_PRIVATE_KEY are present.

If they are missing, they must be added before the workflow can run.


Task 5: Trigger via workflow_dispatch and verify

  • Step 1: Trigger the workflow manually

In GitHub: cloudzero-documentation → Actions → "Sync What's New to feature-web-apps" → Run workflow → select branch v1.0 → Run.

  • Step 2: Watch the run complete

Click into the run. Each step should show green. Specifically verify:

  • "Strip frontmatter" step logs show the stripped preview starting with the banner image line (no YAML keys)

  • "Check for changes" step logs either say "No changes detected" (if feature-web-apps already has the file) or "Changes detected" with a diff

  • If changes were detected: "Create branch and push" and "Open pull request" steps both succeed

  • Step 3: Confirm the PR in feature-web-apps

Go to Cloudzero/feature-web-apps → Pull Requests. A PR titled chore: sync whats-new from cloudzero-documentation (<sha>) should appear targeting main, with libs/ui/help-guidance/src/data/whats-new.md as the only changed file.

Open the PR and verify the file content: it should be the full What's New markdown with no YAML frontmatter at the top.


Setup Notes (not implementation steps)

These must be true before the workflow will succeed:

  1. GitHub App repository access: The app must have Contents: write and Pull requests: write on feature-web-apps (see Task 4).
  2. Secrets in cloudzero-documentation: CLOUDZERO_GITHUB_ACTIONS_APP_ID and CLOUDZERO_GITHUB_ACTIONS_APP_PRIVATE_KEY must exist as Actions secrets in this repo.
  3. Target directory: The workflow creates libs/ui/help-guidance/src/data/ with mkdir -p if it does not exist, so no manual setup is needed here.