forked from langchain-ai/docs
-
Notifications
You must be signed in to change notification settings - Fork 0
179 lines (150 loc) Β· 6.65 KB
/
create-preview-branch.yml
File metadata and controls
179 lines (150 loc) Β· 6.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
---
name: Create Preview Branch
run-name: Preview by @${{ github.actor }}
on:
pull_request:
types: [opened, synchronize, reopened]
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: read
actions: read
jobs:
create-preview:
# This job needs to push a branch, so contents: write here only.
permissions:
contents: write
runs-on: ubuntu-latest
# Skip for PRs from forks - they don't have write access
if: github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'workflow_dispatch'
# 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] Branch name contains invalid characters. Only alphanumeric, slash, underscore, and hyphen are allowed."
exit 1
fi
if [[ ${#SOURCE_BRANCH} -gt 100 ]]; then
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"
- name: Checkout current branch
uses: actions/checkout@v5
with:
ref: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }}
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.12'
- name: Install uv
uses: astral-sh/setup-uv@v6
- name: Install dependencies
run: make install
- name: Build documentation
run: make build
- name: Generate secure preview branch name
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}"
PREVIEW_BRANCH="preview-${safe_prefix}-${timestamp}-${short_sha}"
echo "branch_name=$PREVIEW_BRANCH" >> $GITHUB_OUTPUT
echo "[INFO] Preview branch will be: $PREVIEW_BRANCH"
- name: Configure Git
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
- 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."
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 (log)
run: |
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:
# 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
uses: actions/github-script@v8
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: ${preview}`
});