Skip to content

Commit 92e958e

Browse files
authored
Deploy preview workflow run (#124)
* ci: convert PR preview to two-stage workflow_run pipeline Refactor PR preview deployment into a two-stage pipeline to fix GitHub Actions permission failures on cross-repository fork PRs: - Add Stage 1 unprivileged build workflow (pull_request event) - Add Stage 2 privileged deploy workflow (workflow_run event) - Remove monolithic single-stage deploy_pr_preview.yml - Add top-level security and stage relationship comments * ci: convert PR preview to two-stage workflow with separate jobs Refactor PR preview deployment into a two-stage pipeline to fix GitHub Actions permission failures on cross-repository fork PRs: - Add Stage 1 build workflow with distinct build & cleanup jobs - Add Stage 2 deploy workflow with parse, deploy, & cleanup jobs - Remove monolithic single-stage deploy_pr_preview.yml - Add top-level security and stage relationship comments * Setup corepack *first*
1 parent 66b8778 commit 92e958e

3 files changed

Lines changed: 376 additions & 195 deletions

File tree

.github/workflows/deploy_pr_preview.yml

Lines changed: 0 additions & 195 deletions
This file was deleted.
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# ==============================================================================
16+
# PR Preview Build (Stage 1)
17+
#
18+
# Purpose:
19+
# Stage 1 of the two-stage PR preview workflow.
20+
#
21+
# Architecture & Security:
22+
# Runs under the `pull_request` event with unprivileged `contents: read`
23+
# permissions. This allows safe execution of untrusted build scripts (e.g.,
24+
# from cross-repository forks) without exposing repository write credentials
25+
# or secrets.
26+
#
27+
# Relationship to Stage 2:
28+
# Packages built static distribution assets (`deploy_dist/`) and metadata
29+
# (`pr_meta/metadata.json`) into the `pr-preview-payload` artifact. When
30+
# completed, GitHub Actions automatically triggers Stage 2
31+
# (`pr_preview_deploy.yml`).
32+
# ==============================================================================
33+
34+
name: PR Preview Build
35+
36+
on:
37+
pull_request:
38+
types: [opened, synchronize, reopened, closed]
39+
40+
permissions:
41+
contents: read
42+
43+
concurrency:
44+
group: pages-pr-build-${{ github.event.pull_request.number }}
45+
cancel-in-progress: true
46+
47+
jobs:
48+
build-preview:
49+
if: github.event.action != 'closed'
50+
runs-on: ubuntu-latest
51+
steps:
52+
- name: Checkout Repository
53+
uses: actions/checkout@v4
54+
55+
- name: Enable Corepack
56+
run: corepack enable
57+
58+
- name: Setup Node.js
59+
uses: actions/setup-node@v4
60+
with:
61+
node-version: "24"
62+
cache: "yarn"
63+
cache-dependency-path: "yarn.lock"
64+
65+
- name: Install Dependencies
66+
run: yarn install --immutable
67+
68+
- name: Build Core Bridge Dependency
69+
run: yarn workspace a2ui-bridge build
70+
71+
- name: Build Shell & Catalogs with PR-Specific Base URLs
72+
env:
73+
PR_NUM: ${{ github.event.pull_request.number }}
74+
run: |
75+
yarn workspace ng-basic-catalog run build --base-href=/composer/pr/${PR_NUM}/samples/ng-basic-catalog/
76+
yarn workspace a2ui-composer-shell run build --base-href=/composer/pr/${PR_NUM}/
77+
yarn workspace lit-basic-catalog run build --base=/composer/pr/${PR_NUM}/samples/lit-basic-catalog/
78+
yarn workspace react-basic-catalog run build --base=/composer/pr/${PR_NUM}/samples/react-basic-catalog/
79+
80+
- name: Assemble Staging Directory (deploy_dist)
81+
run: |
82+
mkdir -p deploy_dist/samples/ng-basic-catalog
83+
mkdir -p deploy_dist/samples/lit-basic-catalog
84+
mkdir -p deploy_dist/samples/react-basic-catalog
85+
86+
if [ -d "shell/dist/a2ui-composer/browser" ]; then
87+
cp -r shell/dist/a2ui-composer/browser/. deploy_dist/
88+
else
89+
cp -r shell/dist/a2ui-composer/. deploy_dist/
90+
fi
91+
92+
if [ -d "samples/ng-basic-catalog/dist/ng-basic-catalog/browser" ]; then
93+
cp -r samples/ng-basic-catalog/dist/ng-basic-catalog/browser/. deploy_dist/samples/ng-basic-catalog/
94+
else
95+
cp -r samples/ng-basic-catalog/dist/ng-basic-catalog/. deploy_dist/samples/ng-basic-catalog/
96+
fi
97+
98+
cp -r samples/lit-basic-catalog/dist/. deploy_dist/samples/lit-basic-catalog/
99+
cp -r samples/react-basic-catalog/dist/. deploy_dist/samples/react-basic-catalog/
100+
101+
touch deploy_dist/.nojekyll
102+
103+
- name: Generate PR Metadata
104+
env:
105+
PR_NUM: ${{ github.event.pull_request.number }}
106+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
107+
run: |
108+
mkdir -p pr_meta
109+
jq -n \
110+
--arg pr_number "$PR_NUM" \
111+
--arg action "deploy" \
112+
--arg head_sha "$HEAD_SHA" \
113+
'{pr_number: ($pr_number | tonumber), action: $action, head_sha: $head_sha}' > pr_meta/metadata.json
114+
115+
- name: Upload PR Preview Artifact
116+
uses: actions/upload-artifact@v4
117+
with:
118+
name: pr-preview-payload
119+
path: |
120+
pr_meta/metadata.json
121+
deploy_dist/
122+
retention-days: 1
123+
124+
prepare-cleanup:
125+
if: github.event.action == 'closed'
126+
runs-on: ubuntu-latest
127+
steps:
128+
- name: Generate PR Metadata
129+
env:
130+
PR_NUM: ${{ github.event.pull_request.number }}
131+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
132+
run: |
133+
mkdir -p pr_meta
134+
jq -n \
135+
--arg pr_number "$PR_NUM" \
136+
--arg action "cleanup" \
137+
--arg head_sha "$HEAD_SHA" \
138+
'{pr_number: ($pr_number | tonumber), action: $action, head_sha: $head_sha}' > pr_meta/metadata.json
139+
140+
- name: Upload PR Preview Artifact
141+
uses: actions/upload-artifact@v4
142+
with:
143+
name: pr-preview-payload
144+
path: pr_meta/metadata.json
145+
retention-days: 1

0 commit comments

Comments
 (0)