From fdd93bc62208a38b08745bc30983ad120dbcec0d Mon Sep 17 00:00:00 2001 From: Brody Klapko Date: Fri, 15 Aug 2025 07:59:00 -0700 Subject: [PATCH 1/3] Move PR write permissions --- .github/workflows/create-preview-branch.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/create-preview-branch.yml b/.github/workflows/create-preview-branch.yml index 473567bb..3852a0a9 100644 --- a/.github/workflows/create-preview-branch.yml +++ b/.github/workflows/create-preview-branch.yml @@ -14,10 +14,11 @@ concurrency: permissions: contents: write # Required to checkout, create branches, and push actions: read # Required to run the workflow - pull-requests: write # Required to comment on PRs jobs: create-preview: + permissions: + pull-requests: write # Required to comment on PRs runs-on: ubuntu-latest env: SOURCE_BRANCH: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }} From 847c7d28062feb4095b208ba673bdb82965bf063 Mon Sep 17 00:00:00 2001 From: Brody Klapko Date: Fri, 15 Aug 2025 09:06:43 -0700 Subject: [PATCH 2/3] Split workflow into two jobs, replace some error messaging, other minor tweaks --- .github/workflows/create-preview-branch.yml | 97 +++++++-------------- 1 file changed, 32 insertions(+), 65 deletions(-) diff --git a/.github/workflows/create-preview-branch.yml b/.github/workflows/create-preview-branch.yml index 3852a0a9..57e89394 100644 --- a/.github/workflows/create-preview-branch.yml +++ b/.github/workflows/create-preview-branch.yml @@ -5,46 +5,47 @@ run-name: Preview by @${{ github.actor }} on: pull_request: types: [opened, synchronize, reopened] - workflow_dispatch: # Keep manual trigger as fallback + workflow_dispatch: concurrency: group: create-preview-${{ github.ref_name }} cancel-in-progress: true +# Least-privileged defaults. We'll elevate at the job level only where needed. permissions: - contents: write # Required to checkout, create branches, and push - actions: read # Required to run the workflow + contents: read + actions: read jobs: create-preview: + # This job needs to push a branch, so contents: write here only. permissions: - pull-requests: write # Required to comment on PRs + contents: write runs-on: ubuntu-latest + + # Expose the generated preview branch name for the next job + outputs: + preview_branch: ${{ steps.branch-name.outputs.branch_name }} + env: SOURCE_BRANCH: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }} GITHUB_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} + steps: - name: Validate and sanitize branch context id: validate run: | set -euo pipefail - - echo "[INFO] Validating current branch context" echo "[INFO] Current ref: ${{ github.ref }}" echo "[INFO] Branch name: $SOURCE_BRANCH" - - # Validate source branch contains only safe characters and isn't too long if [[ ! "$SOURCE_BRANCH" =~ ^[a-zA-Z0-9/_-]+$ ]]; then - echo "[ERROR] Current branch name contains invalid characters. Only alphanumeric, slash, underscore, and hyphen are allowed." + echo "[ERROR] Branch name contains invalid characters. Only alphanumeric, slash, underscore, and hyphen are allowed." exit 1 fi - if [[ ${#SOURCE_BRANCH} -gt 100 ]]; then - echo "[ERROR] Current branch name is too long (max 100 characters)" + echo "[ERROR] Branch name too long (max 100)." exit 1 fi - - # Sanitize for logging (first 20 chars max) SAFE_LOG_BRANCH=$(echo "$SOURCE_BRANCH" | cut -c1-20) echo "safe_branch_log=$SAFE_LOG_BRANCH" >> $GITHUB_OUTPUT echo "[SUCCESS] Branch validation passed for: $SAFE_LOG_BRANCH" @@ -73,19 +74,10 @@ jobs: id: branch-name run: | set -euo pipefail - - echo "[INFO] Generating collision-resistant preview branch name" - - # Function to generate preview branch name - generate_preview_branch() { - local safe_prefix timestamp short_sha - safe_prefix=$(echo "$SOURCE_BRANCH" | tr -cd '[:alnum:]' | cut -c1-6) - timestamp=$(date +%s) - short_sha="${GITHUB_SHA:0:7}" - echo "preview-${safe_prefix}-${timestamp}-${short_sha}" - } - - PREVIEW_BRANCH=$(generate_preview_branch) + safe_prefix=$(echo "$SOURCE_BRANCH" | tr -cd '[:alnum:]' | cut -c1-6) + timestamp=$(date +%s) + short_sha="${GITHUB_SHA:0:7}" + PREVIEW_BRANCH="preview-${safe_prefix}-${timestamp}-${short_sha}" echo "branch_name=$PREVIEW_BRANCH" >> $GITHUB_OUTPUT echo "[INFO] Preview branch will be: $PREVIEW_BRANCH" @@ -97,82 +89,57 @@ jobs: - name: Check if preview branch already exists run: | set -euo pipefail - PREVIEW_BRANCH="${{ steps.branch-name.outputs.branch_name }}" - echo "[INFO] Checking if preview branch already exists: $PREVIEW_BRANCH" - - # Check if the branch exists remotely if git ls-remote --exit-code --heads origin "$PREVIEW_BRANCH" >/dev/null 2>&1; then - echo "[ERROR] Preview branch $PREVIEW_BRANCH already exists. This should be extremely rare." - echo "[INFO] Please retry the workflow to generate a new branch name." + echo "[ERROR] Preview branch $PREVIEW_BRANCH already exists." exit 1 fi - echo "[SUCCESS] Preview branch name is unique" - name: Create and push preview branch run: | set -euo pipefail - PREVIEW_BRANCH="${{ steps.branch-name.outputs.branch_name }}" SAFE_BRANCH_LOG="${{ steps.validate.outputs.safe_branch_log }}" - - echo "[INFO] Creating preview branch: $PREVIEW_BRANCH" - - # Create new branch from current state git checkout -b "$PREVIEW_BRANCH" - - # Add build artifacts (force add since build/ is likely in .gitignore) - echo "[INFO] Adding build artifacts to preview branch (forced)" git add -f build/ - - # Check if there are changes to commit if git diff --cached --quiet; then echo "[WARN] No build artifacts to commit" else - echo "[INFO] Committing build artifacts" git commit -m "Add build artifacts for preview deployment Source branch: $SAFE_BRANCH_LOG Generated from commit: $GITHUB_SHA Timestamp: $(date -u +"%Y-%m-%d %H:%M:%S UTC") - - This branch contains the built documentation for preview deployment. Do not merge this branch to main." fi - - # Push the preview branch - echo "[INFO] Pushing preview branch to origin" git push origin "$PREVIEW_BRANCH" echo "[SUCCESS] Successfully pushed preview branch" - - name: Save preview branch info + - name: Save preview branch info (log) run: | - set -euo pipefail - PREVIEW_BRANCH="${{ steps.branch-name.outputs.branch_name }}" SAFE_BRANCH_LOG="${{ steps.validate.outputs.safe_branch_log }}" - - echo "[SUCCESS] Preview branch created successfully!" - echo "[INFO] Branch name: $PREVIEW_BRANCH" - echo "[INFO] Source branch: $SAFE_BRANCH_LOG" - echo "[INFO] Source commit: $GITHUB_SHA" - echo "[INFO] Created at: $(date -u +"%Y-%m-%d %H:%M:%S UTC")" - echo "" - echo "[INFO] The preview branch is now ready for Mintlify deployment." - echo "" + echo "[SUCCESS] Preview branch created: $PREVIEW_BRANCH" echo "[INFO] 🔗 Branch URL: https://github.com/${{ github.repository }}/tree/$PREVIEW_BRANCH" + comment-on-pr: + # Only this job gets permission to write PR comments. + permissions: + pull-requests: write + runs-on: ubuntu-latest + needs: create-preview + if: github.event_name == 'pull_request' && needs.create-preview.result == 'success' + + steps: - name: Comment on PR - if: github.event_name == 'pull_request' # Only run on PR events uses: actions/github-script@v7 with: script: | + const preview = `${{ needs.create-preview.outputs.preview_branch }}`; await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, - body: `Preview ID generated: ${process.env.PREVIEW_BRANCH}` + body: `Preview ID generated: ${preview}` }); - env: - PREVIEW_BRANCH: ${{ steps.branch-name.outputs.branch_name }} \ No newline at end of file From c82e16ac80f5026b92e71ecf07dbd171df6414ad Mon Sep 17 00:00:00 2001 From: Brody Klapko Date: Fri, 15 Aug 2025 09:19:21 -0700 Subject: [PATCH 3/3] Add logging and comments back --- .github/workflows/create-preview-branch.yml | 33 ++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/.github/workflows/create-preview-branch.yml b/.github/workflows/create-preview-branch.yml index 57e89394..7b3d1388 100644 --- a/.github/workflows/create-preview-branch.yml +++ b/.github/workflows/create-preview-branch.yml @@ -36,8 +36,10 @@ jobs: id: validate run: | set -euo pipefail + echo "[INFO] Validating current branch context" echo "[INFO] Current ref: ${{ github.ref }}" echo "[INFO] Branch name: $SOURCE_BRANCH" + # Validate source branch contains only safe characters and isn't too long if [[ ! "$SOURCE_BRANCH" =~ ^[a-zA-Z0-9/_-]+$ ]]; then echo "[ERROR] Branch name contains invalid characters. Only alphanumeric, slash, underscore, and hyphen are allowed." exit 1 @@ -46,6 +48,7 @@ jobs: echo "[ERROR] Branch name too long (max 100)." exit 1 fi + # Sanitize for logging (first 20 chars max) SAFE_LOG_BRANCH=$(echo "$SOURCE_BRANCH" | cut -c1-20) echo "safe_branch_log=$SAFE_LOG_BRANCH" >> $GITHUB_OUTPUT echo "[SUCCESS] Branch validation passed for: $SAFE_LOG_BRANCH" @@ -74,6 +77,7 @@ jobs: id: branch-name run: | set -euo pipefail + echo "[INFO] Generating collision-resistant preview branch name" safe_prefix=$(echo "$SOURCE_BRANCH" | tr -cd '[:alnum:]' | cut -c1-6) timestamp=$(date +%s) short_sha="${GITHUB_SHA:0:7}" @@ -90,8 +94,12 @@ jobs: run: | set -euo pipefail PREVIEW_BRANCH="${{ steps.branch-name.outputs.branch_name }}" + echo "[INFO] Checking if preview branch already exists: $PREVIEW_BRANCH" + + # Check if the branch exists remotely if git ls-remote --exit-code --heads origin "$PREVIEW_BRANCH" >/dev/null 2>&1; then - echo "[ERROR] Preview branch $PREVIEW_BRANCH already exists." + echo "[ERROR] Preview branch $PREVIEW_BRANCH already exists. This should be extremely rare." + echo "[INFO] Please retry the workflow to generate a new branch name." exit 1 fi echo "[SUCCESS] Preview branch name is unique" @@ -101,18 +109,34 @@ jobs: set -euo pipefail PREVIEW_BRANCH="${{ steps.branch-name.outputs.branch_name }}" SAFE_BRANCH_LOG="${{ steps.validate.outputs.safe_branch_log }}" + + echo "[INFO] Creating preview branch: $PREVIEW_BRANCH" + + # Create new branch from current state + git checkout -b "$PREVIEW_BRANCH" + + # Add build artifacts (force add since build/ is likely in .gitignore) + echo "[INFO] Adding build artifacts to preview branch (forced)" + git add -f build/ + + # Check if there are changes to commit if git diff --cached --quiet; then echo "[WARN] No build artifacts to commit" else + echo "[INFO] Committing build artifacts" git commit -m "Add build artifacts for preview deployment Source branch: $SAFE_BRANCH_LOG Generated from commit: $GITHUB_SHA Timestamp: $(date -u +"%Y-%m-%d %H:%M:%S UTC") + This branch contains the built documentation for preview deployment. Do not merge this branch to main." fi + + # Push the preview branch + echo "[INFO] Pushing preview branch to origin" git push origin "$PREVIEW_BRANCH" echo "[SUCCESS] Successfully pushed preview branch" @@ -121,6 +145,13 @@ jobs: PREVIEW_BRANCH="${{ steps.branch-name.outputs.branch_name }}" SAFE_BRANCH_LOG="${{ steps.validate.outputs.safe_branch_log }}" echo "[SUCCESS] Preview branch created: $PREVIEW_BRANCH" + echo "[INFO] Branch name: $PREVIEW_BRANCH" + echo "[INFO] Source branch: $SAFE_BRANCH_LOG" + echo "[INFO] Source commit: $GITHUB_SHA" + echo "[INFO] Created at: $(date -u +"%Y-%m-%d %H:%M:%S UTC")" + echo "" + echo "[INFO] The preview branch is now ready for Mintlify deployment." + echo "" echo "[INFO] 🔗 Branch URL: https://github.com/${{ github.repository }}/tree/$PREVIEW_BRANCH" comment-on-pr: