Skip to content

homeMaker Vision Alignment: strip dev UI, home AI agent, product identity #3

homeMaker Vision Alignment: strip dev UI, home AI agent, product identity

homeMaker Vision Alignment: strip dev UI, home AI agent, product identity #3

Workflow file for this run

# SECURITY: This workflow is hardened against fork PR attacks. See docs/security/ci-hardening.md
name: Auto Release
# Fires when a staging→main PR is merged. Creates a git tag and GitHub Release
# from the version already bumped on staging by prepare-release.yml.
#
# Flow: prepare-release.yml bumps version on staging → staging→main PR merges
# → this workflow tags main and creates the GitHub Release.
#
# NOTE: To allow the v* tag push to trigger build-electron.yml, this workflow
# must use a PAT (stored as GH_PAT secret) rather than the default GITHUB_TOKEN.
# GitHub blocks cross-workflow event chains when using GITHUB_TOKEN to prevent
# infinite loops. If GH_PAT is not set, the tag push will succeed but
# build-electron.yml will not fire automatically.
on:
pull_request:
types: [closed]
branches:
- main
workflow_dispatch:
permissions: read-all
jobs:
release:
runs-on: self-hosted
if: >-
(github.event_name == 'workflow_dispatch') ||
(github.event.pull_request.merged == true &&
github.event.pull_request.head.ref == 'staging' &&
github.repository == 'protoLabsAI/protoMaker')
timeout-minutes: 10
permissions:
contents: write
pull-requests: write
env:
DISCORD_DEV_WEBHOOK: ${{ secrets.DISCORD_DEV_WEBHOOK }}
DISCORD_ALERTS_WEBHOOK: ${{ secrets.DISCORD_ALERTS_WEBHOOK }}
steps:
- name: Verify GH_PAT is set
run: |
if [ -z "${{ secrets.GH_PAT }}" ]; then
echo "WARNING: GH_PAT secret is not set."
echo "The v* tag push will fall back to GITHUB_TOKEN."
echo "build-electron.yml will NOT fire automatically."
echo "Set GH_PAT in repository secrets to enable the release → Electron build chain."
else
echo "GH_PAT is configured — release → Electron build chain is active."
fi
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0
token: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
- name: Setup project
uses: ./.github/actions/setup-project
with:
skip-native-rebuild: 'true'
- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
- name: Get version
id: version
# Version was already bumped on staging by prepare-release.yml.
# Read it from the merged content on main.
run: |
VERSION=$(node -p "require('./libs/types/package.json').version")
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Detected version: v${VERSION}"
# Verify this version isn't already tagged
if git tag -l "v${VERSION}" | grep -q "v${VERSION}"; then
echo "already_tagged=true" >> $GITHUB_OUTPUT
echo "WARNING: v${VERSION} is already tagged. Skipping."
else
echo "already_tagged=false" >> $GITHUB_OUTPUT
fi
- name: Create tag
if: steps.version.outputs.already_tagged != 'true'
run: |
VERSION="v${{ steps.version.outputs.version }}"
git tag -a "$VERSION" -m "$VERSION"
git push origin "$VERSION"
- name: Create GitHub Release
if: steps.version.outputs.already_tagged != 'true'
run: |
VERSION="v${{ steps.version.outputs.version }}"
# Generate notes, then filter out chore PRs (unless they're the only entries)
RAW_NOTES=$(gh api "repos/${{ github.repository }}/releases/generate-notes" \
-f tag_name="$VERSION" --jq '.body')
# Extract "What's Changed" lines (PR entries start with "* ")
ALL_LINES=$(echo "$RAW_NOTES" | grep '^\* ' || true)
NON_CHORE=$(echo "$ALL_LINES" | grep -vi '^\* chore' || true)
if [ -n "$NON_CHORE" ]; then
# Has real changes — filter out chores
FILTERED_NOTES=$(echo "$RAW_NOTES" | grep -vi '^\* chore')
else
# Only chores — keep them so the release isn't empty
FILTERED_NOTES="$RAW_NOTES"
fi
gh release create "$VERSION" \
--title "$VERSION Alpha" \
--notes "$FILTERED_NOTES"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Rewrite and post release notes to Discord
if: steps.version.outputs.already_tagged != 'true' && env.DISCORD_DEV_WEBHOOK != ''
continue-on-error: true
run: |
VERSION="v${{ steps.version.outputs.version }}"
PREV_TAG=$(git tag --sort=-v:refname | grep -v "^${VERSION}$" | head -1)
node scripts/rewrite-release-notes.mjs "$VERSION" "$PREV_TAG" --post-discord
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
- name: Sync main back to staging
if: steps.version.outputs.already_tagged != 'true'
run: |
# After tagging, merge main back into staging so staging has
# the merge commit. Without this, the next staging→main promotion
# diverges on package.json versions and creates merge conflicts.
echo "Syncing main back to staging..."
git fetch origin staging
git checkout staging
git merge origin/main --no-edit -m "chore: sync main merge commit back to staging"
git push origin staging
echo "Staging synced with main"
- name: Sync main back to dev
if: steps.version.outputs.already_tagged != 'true'
continue-on-error: true
run: |
# Also sync to dev to keep all three branches aligned
echo "Syncing main back to dev..."
git fetch origin dev
git checkout dev
git merge origin/main --no-edit -m "chore: sync main merge commit back to dev"
git push origin dev
echo "Dev synced with main"
- name: Alert on skipped release
if: steps.version.outputs.already_tagged == 'true'
run: |
VERSION="v${{ steps.version.outputs.version }}"
RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
MSG="Release SKIPPED: ${VERSION} is already tagged. Was prepare-release.yml run before promotion? ${RUN_URL}"
echo "::error::${MSG}"
if [ -n "${DISCORD_ALERTS_WEBHOOK:-}" ]; then
curl -sf -H "Content-Type: application/json" \
-d "{\"content\": \"${MSG}\"}" \
"$DISCORD_ALERTS_WEBHOOK" || true
fi
exit 1
- name: Alert on release failure
if: failure() && steps.version.outputs.already_tagged != 'true'
run: |
RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
MSG="ALERT: Auto-release FAILED. Tag or GitHub Release may be incomplete. ${RUN_URL}"
if [ -n "${DISCORD_ALERTS_WEBHOOK:-}" ]; then
curl -sf -H "Content-Type: application/json" \
-d "{\"content\": \"${MSG}\"}" \
"$DISCORD_ALERTS_WEBHOOK" || true
fi