climaybe 3.1.4 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -8
- package/bin/version.txt +1 -1
- package/package.json +1 -1
- package/src/index.js +6 -2
- package/src/lib/config.js +17 -0
- package/src/lib/dev-runtime.js +35 -8
- package/src/lib/prompts.js +22 -0
- package/src/lib/serve-multi-store.js +81 -0
- package/src/workflows/preview/cleanup-orphan-preview-themes.yml +59 -0
- package/src/workflows/preview/pr-close.yml +105 -61
- package/src/workflows/preview/pr-update.yml +87 -76
- package/src/workflows/preview/reusable-cleanup-themes.yml +220 -14
- package/src/workflows/preview/reusable-comment-on-pr.yml +83 -19
- package/src/workflows/preview/reusable-publish-pr-preview-store.yml +162 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Share theme to one Shopify store, rename with -PR{padded}, upload JSON fragment for PR comment fan-in.
|
|
2
|
+
# Intended to be called from a matrix job (one invocation per store).
|
|
3
|
+
|
|
4
|
+
name: Publish PR preview (single store)
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
workflow_call:
|
|
8
|
+
inputs:
|
|
9
|
+
pr_number:
|
|
10
|
+
required: true
|
|
11
|
+
type: string
|
|
12
|
+
description: "Padded PR number (e.g. 09) for theme name suffix -PR09"
|
|
13
|
+
store_alias:
|
|
14
|
+
required: true
|
|
15
|
+
type: string
|
|
16
|
+
description: "Store alias (for artifact naming and comment JSON)"
|
|
17
|
+
store_alias_secret:
|
|
18
|
+
required: false
|
|
19
|
+
type: string
|
|
20
|
+
default: ''
|
|
21
|
+
description: "Upper snake-case secret suffix; empty uses SHOPIFY_STORE_URL / SHOPIFY_THEME_ACCESS_TOKEN"
|
|
22
|
+
outputs:
|
|
23
|
+
theme_id:
|
|
24
|
+
description: "Theme ID after share/rename"
|
|
25
|
+
value: ${{ jobs.publish.outputs.theme_id }}
|
|
26
|
+
theme_name:
|
|
27
|
+
description: "Final theme name after rename"
|
|
28
|
+
value: ${{ jobs.publish.outputs.theme_name }}
|
|
29
|
+
share_output:
|
|
30
|
+
description: "Raw share command output"
|
|
31
|
+
value: ${{ jobs.publish.outputs.share_output }}
|
|
32
|
+
|
|
33
|
+
jobs:
|
|
34
|
+
publish:
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
permissions:
|
|
37
|
+
contents: read
|
|
38
|
+
actions: write
|
|
39
|
+
outputs:
|
|
40
|
+
theme_id: ${{ steps.rename.outputs.theme_id }}
|
|
41
|
+
theme_name: ${{ steps.rename.outputs.theme_name }}
|
|
42
|
+
share_output: ${{ steps.share.outputs.share_output }}
|
|
43
|
+
steps:
|
|
44
|
+
- name: Checkout code
|
|
45
|
+
uses: actions/checkout@v4
|
|
46
|
+
|
|
47
|
+
- name: Validate theme root
|
|
48
|
+
run: |
|
|
49
|
+
if [ ! -f "layout/theme.liquid" ]; then
|
|
50
|
+
echo "layout/theme.liquid not found. Ensure workflow runs at theme repository root."
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
- name: Install Shopify CLI
|
|
55
|
+
run: npm install -g @shopify/cli @shopify/theme
|
|
56
|
+
|
|
57
|
+
- name: Share theme
|
|
58
|
+
id: share
|
|
59
|
+
env:
|
|
60
|
+
SHOPIFY_STORE_URL: ${{ inputs.store_alias_secret && secrets[format('SHOPIFY_STORE_URL_{0}', inputs.store_alias_secret)] || secrets.SHOPIFY_STORE_URL }}
|
|
61
|
+
SHOPIFY_THEME_ACCESS_TOKEN: ${{ inputs.store_alias_secret && secrets[format('SHOPIFY_THEME_ACCESS_TOKEN_{0}', inputs.store_alias_secret)] || secrets.SHOPIFY_THEME_ACCESS_TOKEN }}
|
|
62
|
+
run: |
|
|
63
|
+
if [ -z "$SHOPIFY_STORE_URL" ] || [ -z "$SHOPIFY_THEME_ACCESS_TOKEN" ]; then
|
|
64
|
+
echo "Missing Shopify secrets."
|
|
65
|
+
exit 1
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
OUTPUT=$(shopify theme share \
|
|
69
|
+
--store "$SHOPIFY_STORE_URL" \
|
|
70
|
+
--password "$SHOPIFY_THEME_ACCESS_TOKEN" 2>&1)
|
|
71
|
+
STATUS=$?
|
|
72
|
+
|
|
73
|
+
echo "$OUTPUT"
|
|
74
|
+
if [ $STATUS -ne 0 ]; then
|
|
75
|
+
echo "Theme share failed."
|
|
76
|
+
exit $STATUS
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
THEME_NAME=$(echo "$OUTPUT" | sed -n "s/.*The theme '\([^']*\)'.*/\1/p" | head -1)
|
|
80
|
+
THEME_ID=$(echo "$OUTPUT" | sed -n 's/.*#\([0-9]*\).*/\1/p' | head -1)
|
|
81
|
+
|
|
82
|
+
if [ -z "$THEME_ID" ]; then
|
|
83
|
+
echo "Could not parse theme id from share output."
|
|
84
|
+
exit 1
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
echo "theme_id=$THEME_ID" >> "$GITHUB_OUTPUT"
|
|
88
|
+
if [ -n "$THEME_NAME" ]; then
|
|
89
|
+
echo "theme_name=$THEME_NAME" >> "$GITHUB_OUTPUT"
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
{
|
|
93
|
+
echo "share_output<<SHARE_EOF"
|
|
94
|
+
echo "$OUTPUT"
|
|
95
|
+
echo "SHARE_EOF"
|
|
96
|
+
} >> "$GITHUB_OUTPUT"
|
|
97
|
+
|
|
98
|
+
- name: Rename theme with PR suffix
|
|
99
|
+
id: rename
|
|
100
|
+
env:
|
|
101
|
+
SHOPIFY_STORE_URL: ${{ inputs.store_alias_secret && secrets[format('SHOPIFY_STORE_URL_{0}', inputs.store_alias_secret)] || secrets.SHOPIFY_STORE_URL }}
|
|
102
|
+
SHOPIFY_THEME_ACCESS_TOKEN: ${{ inputs.store_alias_secret && secrets[format('SHOPIFY_THEME_ACCESS_TOKEN_{0}', inputs.store_alias_secret)] || secrets.SHOPIFY_THEME_ACCESS_TOKEN }}
|
|
103
|
+
THEME_ID: ${{ steps.share.outputs.theme_id }}
|
|
104
|
+
THEME_NAME: ${{ steps.share.outputs.theme_name }}
|
|
105
|
+
PR_NUMBER: ${{ inputs.pr_number }}
|
|
106
|
+
run: |
|
|
107
|
+
if [ -z "$THEME_ID" ] || [ -z "$THEME_NAME" ]; then
|
|
108
|
+
echo "Missing theme_id/theme_name from share step."
|
|
109
|
+
exit 1
|
|
110
|
+
fi
|
|
111
|
+
if [ -z "$SHOPIFY_STORE_URL" ] || [ -z "$SHOPIFY_THEME_ACCESS_TOKEN" ]; then
|
|
112
|
+
echo "Missing Shopify store URL/token for rename."
|
|
113
|
+
exit 1
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
NEW_THEME_NAME="${THEME_NAME}-PR${PR_NUMBER}"
|
|
117
|
+
echo "Renaming theme $THEME_ID to '$NEW_THEME_NAME'..."
|
|
118
|
+
|
|
119
|
+
if shopify theme rename \
|
|
120
|
+
--store "$SHOPIFY_STORE_URL" \
|
|
121
|
+
--password "$SHOPIFY_THEME_ACCESS_TOKEN" \
|
|
122
|
+
--theme "$THEME_ID" \
|
|
123
|
+
--name "$NEW_THEME_NAME" 2>&1; then
|
|
124
|
+
echo "Rename succeeded with password auth."
|
|
125
|
+
elif shopify theme rename \
|
|
126
|
+
--store "$SHOPIFY_STORE_URL" \
|
|
127
|
+
--theme "$THEME_ID" \
|
|
128
|
+
--name "$NEW_THEME_NAME" 2>&1; then
|
|
129
|
+
echo "Rename succeeded with authenticated session."
|
|
130
|
+
else
|
|
131
|
+
echo "Failed to rename theme."
|
|
132
|
+
exit 1
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
echo "theme_id=$THEME_ID" >> "$GITHUB_OUTPUT"
|
|
136
|
+
echo "theme_name=$NEW_THEME_NAME" >> "$GITHUB_OUTPUT"
|
|
137
|
+
|
|
138
|
+
- name: Write preview fragment for PR comment
|
|
139
|
+
env:
|
|
140
|
+
STORE_ALIAS: ${{ inputs.store_alias }}
|
|
141
|
+
THEME_ID: ${{ steps.rename.outputs.theme_id }}
|
|
142
|
+
SHOPIFY_STORE_URL: ${{ inputs.store_alias_secret && secrets[format('SHOPIFY_STORE_URL_{0}', inputs.store_alias_secret)] || secrets.SHOPIFY_STORE_URL }}
|
|
143
|
+
run: |
|
|
144
|
+
node <<'NODE'
|
|
145
|
+
const fs = require('fs');
|
|
146
|
+
const url = (process.env.SHOPIFY_STORE_URL || '')
|
|
147
|
+
.replace(/^https?:\/\//, '')
|
|
148
|
+
.replace(/\/.*$/, '');
|
|
149
|
+
const payload = {
|
|
150
|
+
alias: process.env.STORE_ALIAS || '',
|
|
151
|
+
theme_id: process.env.THEME_ID || '',
|
|
152
|
+
store_host: url,
|
|
153
|
+
};
|
|
154
|
+
fs.writeFileSync('fragment.json', JSON.stringify(payload, null, 0));
|
|
155
|
+
NODE
|
|
156
|
+
|
|
157
|
+
- name: Upload preview fragment
|
|
158
|
+
uses: actions/upload-artifact@v4
|
|
159
|
+
with:
|
|
160
|
+
name: preview-fragment-${{ inputs.store_alias }}
|
|
161
|
+
path: fragment.json
|
|
162
|
+
retention-days: 2
|