climaybe 1.5.1 → 1.5.2
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 +3 -3
- package/bin/version.txt +1 -1
- package/package.json +1 -1
- package/src/workflows/preview/pr-close.yml +41 -35
- package/src/workflows/preview/pr-update.yml +47 -42
- package/src/workflows/preview/reusable-cleanup-themes.yml +6 -2
- package/src/workflows/preview/reusable-comment-on-pr.yml +2 -4
- package/src/workflows/preview/reusable-rename-theme.yml +3 -8
- package/src/workflows/preview/reusable-share-theme.yml +3 -8
package/README.md
CHANGED
|
@@ -169,8 +169,8 @@ Enabled via `climaybe init` prompt (`Enable preview + cleanup workflows?`).
|
|
|
169
169
|
|
|
170
170
|
| Workflow | Trigger | What it does |
|
|
171
171
|
|----------|---------|-------------|
|
|
172
|
-
| `pr-update.yml` | PR opened/synchronize/reopened | Shares draft theme, renames with `-PR<number>`, comments preview + customize URLs |
|
|
173
|
-
| `pr-close.yml` | PR closed | Deletes matching preview themes and comments deleted count + names |
|
|
172
|
+
| `pr-update.yml` | PR opened/synchronize/reopened (base: main, staging, develop, staging-*, live-*) | Shares draft theme, renames with `-PR<number>`, comments preview + customize URLs; uses default store for main/staging/develop, or the store for staging-<alias>/live-<alias> |
|
|
173
|
+
| `pr-close.yml` | PR closed (same branch set) | Deletes matching preview themes and comments deleted count + names |
|
|
174
174
|
| `reusable-share-theme.yml` | workflow_call | Shares Shopify draft theme and returns `theme_id` |
|
|
175
175
|
| `reusable-rename-theme.yml` | workflow_call | Renames shared theme to include `PR<number>` (fails job on rename failure) |
|
|
176
176
|
| `reusable-comment-on-pr.yml` | workflow_call | Posts preview comment including Customize URL |
|
|
@@ -232,7 +232,7 @@ Add the following secrets to your GitHub repository (or use **GitLab CI/CD varia
|
|
|
232
232
|
|
|
233
233
|
**Store URL:** During `climaybe init` (or `add-store`), store URL secret(s) are set from your configured store domain(s); you are only prompted for the theme token.
|
|
234
234
|
|
|
235
|
-
**Multi-store:** Per-store secrets `SHOPIFY_STORE_URL_<ALIAS>` and `SHOPIFY_THEME_ACCESS_TOKEN_<ALIAS>` — the URL is set from config; you must provide the theme token per store. `<ALIAS>` is uppercase with hyphens as underscores (e.g. `voldt-norway` → `SHOPIFY_STORE_URL_VOLDT_NORWAY`). Preview and cleanup workflows use the **default store** (from `config.default_store` or first
|
|
235
|
+
**Multi-store:** Per-store secrets `SHOPIFY_STORE_URL_<ALIAS>` and `SHOPIFY_THEME_ACCESS_TOKEN_<ALIAS>` — the URL is set from config; you must provide the theme token per store. `<ALIAS>` is uppercase with hyphens as underscores (e.g. `voldt-norway` → `SHOPIFY_STORE_URL_VOLDT_NORWAY`). Preview and cleanup: for PRs targeting **main**, **staging**, or **develop** the workflows use the **default store** (from `config.default_store` or first in `config.stores`); for PRs targeting **staging-<alias>** or **live-<alias>** they use that store’s credentials. Set either the plain `SHOPIFY_*` secrets or the `_<ALIAS>` pair for each store you use in preview.
|
|
236
236
|
|
|
237
237
|
## Directory Structure (Multi-store)
|
|
238
238
|
|
package/bin/version.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.5.
|
|
1
|
+
1.5.2
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@ name: PR Close
|
|
|
6
6
|
on:
|
|
7
7
|
pull_request:
|
|
8
8
|
types: [closed]
|
|
9
|
-
branches: [main, staging, develop]
|
|
9
|
+
branches: [main, staging, develop, 'staging-*', 'live-*']
|
|
10
10
|
|
|
11
11
|
jobs:
|
|
12
12
|
extract-pr-number:
|
|
@@ -20,43 +20,50 @@ jobs:
|
|
|
20
20
|
- name: Checkout code
|
|
21
21
|
uses: actions/checkout@v4
|
|
22
22
|
|
|
23
|
-
- name: Resolve
|
|
23
|
+
- name: Resolve store alias from base branch
|
|
24
24
|
id: resolve
|
|
25
|
+
env:
|
|
26
|
+
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
25
27
|
run: |
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
28
|
+
if [[ -n "$BASE_REF" && ("$BASE_REF" == staging-* || "$BASE_REF" == live-*) ]]; then
|
|
29
|
+
ALIAS="${BASE_REF#staging-}"
|
|
30
|
+
ALIAS="${ALIAS#live-}"
|
|
31
|
+
else
|
|
32
|
+
ALIAS=$(node -e "
|
|
33
|
+
const fs = require('fs');
|
|
34
|
+
const pkg = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
|
35
|
+
const stores = pkg?.config?.stores || {};
|
|
36
|
+
const defaultStoreRaw = pkg?.config?.default_store;
|
|
37
|
+
const normalize = (v) => String(v || '')
|
|
38
|
+
.toLowerCase()
|
|
39
|
+
.replace(/^https?:\\/\\//, '')
|
|
40
|
+
.replace(/\\/.*$/, '');
|
|
41
|
+
const defaultStore = normalize(defaultStoreRaw);
|
|
42
|
+
let alias = '';
|
|
43
|
+
if (defaultStore) {
|
|
44
|
+
for (const [k, d] of Object.entries(stores)) {
|
|
45
|
+
if (normalize(d) === defaultStore) {
|
|
46
|
+
alias = k;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
42
49
|
}
|
|
43
50
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
if (!alias) {
|
|
52
|
+
alias = Object.keys(stores)[0] || '';
|
|
53
|
+
}
|
|
54
|
+
if (!alias && defaultStore) {
|
|
55
|
+
const subdomain = defaultStore.split('.')[0] || 'default';
|
|
56
|
+
alias = subdomain.replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-') || 'default';
|
|
57
|
+
}
|
|
58
|
+
if (!alias) {
|
|
59
|
+
alias = 'default';
|
|
60
|
+
}
|
|
61
|
+
process.stdout.write(alias);
|
|
62
|
+
")
|
|
63
|
+
fi
|
|
57
64
|
|
|
58
65
|
if [ -z "$ALIAS" ]; then
|
|
59
|
-
echo "Could not resolve
|
|
66
|
+
echo "Could not resolve store alias from package.json config or base branch."
|
|
60
67
|
exit 1
|
|
61
68
|
fi
|
|
62
69
|
|
|
@@ -69,9 +76,8 @@ jobs:
|
|
|
69
76
|
uses: ./.github/workflows/reusable-cleanup-themes.yml
|
|
70
77
|
with:
|
|
71
78
|
pr_number: ${{ needs.extract-pr-number.outputs.pr_number }}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
SHOPIFY_THEME_ACCESS_TOKEN: ${{ secrets[format('SHOPIFY_THEME_ACCESS_TOKEN_{0}', needs.resolve-store.outputs.store_alias_secret)] || secrets.SHOPIFY_THEME_ACCESS_TOKEN }}
|
|
79
|
+
store_alias_secret: ${{ needs.resolve-store.outputs.store_alias_secret }}
|
|
80
|
+
secrets: inherit
|
|
75
81
|
|
|
76
82
|
comment-on-pr:
|
|
77
83
|
needs: cleanup-theme
|
|
@@ -7,7 +7,7 @@ name: PR Update
|
|
|
7
7
|
on:
|
|
8
8
|
pull_request:
|
|
9
9
|
types: [opened, synchronize, reopened]
|
|
10
|
-
branches: [main, staging, develop]
|
|
10
|
+
branches: [main, staging, develop, 'staging-*', 'live-*']
|
|
11
11
|
|
|
12
12
|
jobs:
|
|
13
13
|
extract-pr-number:
|
|
@@ -22,40 +22,48 @@ jobs:
|
|
|
22
22
|
- name: Checkout code
|
|
23
23
|
uses: actions/checkout@v4
|
|
24
24
|
|
|
25
|
-
- name: Resolve
|
|
25
|
+
- name: Resolve store alias from base branch
|
|
26
26
|
id: resolve
|
|
27
|
+
env:
|
|
28
|
+
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
27
29
|
run: |
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
30
|
+
# On staging-<alias> or live-<alias> PRs, use that store; otherwise default store
|
|
31
|
+
if [[ -n "$BASE_REF" && ("$BASE_REF" == staging-* || "$BASE_REF" == live-*) ]]; then
|
|
32
|
+
ALIAS="${BASE_REF#staging-}"
|
|
33
|
+
ALIAS="${ALIAS#live-}"
|
|
34
|
+
else
|
|
35
|
+
ALIAS=$(node -e "
|
|
36
|
+
const fs = require('fs');
|
|
37
|
+
const pkg = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
|
38
|
+
const stores = pkg?.config?.stores || {};
|
|
39
|
+
const defaultStoreRaw = pkg?.config?.default_store;
|
|
40
|
+
const normalize = (v) => String(v || '')
|
|
41
|
+
.toLowerCase()
|
|
42
|
+
.replace(/^https?:\\/\\//, '')
|
|
43
|
+
.replace(/\\/.*$/, '');
|
|
44
|
+
const defaultStore = normalize(defaultStoreRaw);
|
|
45
|
+
let alias = '';
|
|
46
|
+
if (defaultStore) {
|
|
47
|
+
for (const [k, d] of Object.entries(stores)) {
|
|
48
|
+
if (normalize(d) === defaultStore) {
|
|
49
|
+
alias = k;
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
44
52
|
}
|
|
45
53
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
if (!alias) {
|
|
55
|
+
alias = Object.keys(stores)[0] || '';
|
|
56
|
+
}
|
|
57
|
+
if (!alias && defaultStore) {
|
|
58
|
+
const subdomain = defaultStore.split('.')[0] || 'default';
|
|
59
|
+
alias = subdomain.replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-') || 'default';
|
|
60
|
+
}
|
|
61
|
+
if (!alias) {
|
|
62
|
+
alias = 'default';
|
|
63
|
+
}
|
|
64
|
+
process.stdout.write(alias);
|
|
65
|
+
")
|
|
66
|
+
fi
|
|
59
67
|
|
|
60
68
|
if [ -z "$ALIAS" ]; then
|
|
61
69
|
echo "Could not resolve default store alias from package.json config."
|
|
@@ -91,9 +99,8 @@ jobs:
|
|
|
91
99
|
uses: ./.github/workflows/reusable-cleanup-themes.yml
|
|
92
100
|
with:
|
|
93
101
|
pr_number: ${{ needs.extract-pr-number.outputs.pr_number }}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
SHOPIFY_THEME_ACCESS_TOKEN: ${{ secrets[format('SHOPIFY_THEME_ACCESS_TOKEN_{0}', needs.validate-environment.outputs.store_alias_secret)] || secrets.SHOPIFY_THEME_ACCESS_TOKEN }}
|
|
102
|
+
store_alias_secret: ${{ needs.validate-environment.outputs.store_alias_secret }}
|
|
103
|
+
secrets: inherit
|
|
97
104
|
|
|
98
105
|
share-theme:
|
|
99
106
|
needs: [validate-environment, extract-pr-number, cleanup-themes]
|
|
@@ -101,9 +108,8 @@ jobs:
|
|
|
101
108
|
with:
|
|
102
109
|
pr_number: ${{ needs.extract-pr-number.outputs.pr_number }}
|
|
103
110
|
store_alias: ${{ needs.validate-environment.outputs.store_alias }}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
SHOPIFY_THEME_ACCESS_TOKEN: ${{ secrets[format('SHOPIFY_THEME_ACCESS_TOKEN_{0}', needs.validate-environment.outputs.store_alias_secret)] || secrets.SHOPIFY_THEME_ACCESS_TOKEN }}
|
|
111
|
+
store_alias_secret: ${{ needs.validate-environment.outputs.store_alias_secret }}
|
|
112
|
+
secrets: inherit
|
|
107
113
|
|
|
108
114
|
rename-theme:
|
|
109
115
|
needs: [share-theme, extract-pr-number, validate-environment]
|
|
@@ -113,9 +119,8 @@ jobs:
|
|
|
113
119
|
theme_name: ${{ needs.share-theme.outputs.theme_name }}
|
|
114
120
|
pr_number: ${{ needs.extract-pr-number.outputs.pr_number }}
|
|
115
121
|
store_alias: ${{ needs.validate-environment.outputs.store_alias }}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
SHOPIFY_THEME_ACCESS_TOKEN: ${{ secrets[format('SHOPIFY_THEME_ACCESS_TOKEN_{0}', needs.validate-environment.outputs.store_alias_secret)] || secrets.SHOPIFY_THEME_ACCESS_TOKEN }}
|
|
122
|
+
store_alias_secret: ${{ needs.validate-environment.outputs.store_alias_secret }}
|
|
123
|
+
secrets: inherit
|
|
119
124
|
|
|
120
125
|
comment-on-pr:
|
|
121
126
|
needs: [share-theme, rename-theme, extract-pr-number, validate-environment]
|
|
@@ -125,5 +130,5 @@ jobs:
|
|
|
125
130
|
share_output: ${{ needs.share-theme.outputs.share_output }}
|
|
126
131
|
pr_number: ${{ needs.extract-pr-number.outputs.pr_number_unpadded }}
|
|
127
132
|
store_alias: ${{ needs.validate-environment.outputs.store_alias }}
|
|
128
|
-
|
|
129
|
-
|
|
133
|
+
store_alias_secret: ${{ needs.validate-environment.outputs.store_alias_secret }}
|
|
134
|
+
secrets: inherit
|
|
@@ -7,6 +7,10 @@ on:
|
|
|
7
7
|
required: true
|
|
8
8
|
type: string
|
|
9
9
|
description: "PR number to clean up themes for"
|
|
10
|
+
store_alias_secret:
|
|
11
|
+
required: false
|
|
12
|
+
type: string
|
|
13
|
+
description: "Upper snake-case alias for scoped secret (e.g. VOLDT_STAGING). If set, uses SHOPIFY_*_<this>; else uses SHOPIFY_STORE_URL / SHOPIFY_THEME_ACCESS_TOKEN."
|
|
10
14
|
outputs:
|
|
11
15
|
deleted_count:
|
|
12
16
|
description: "Number of deleted themes"
|
|
@@ -28,8 +32,8 @@ jobs:
|
|
|
28
32
|
- name: Cleanup PR preview themes
|
|
29
33
|
id: cleanup
|
|
30
34
|
env:
|
|
31
|
-
SHOPIFY_STORE_URL: ${{ secrets.SHOPIFY_STORE_URL }}
|
|
32
|
-
SHOPIFY_THEME_ACCESS_TOKEN: ${{ secrets.SHOPIFY_THEME_ACCESS_TOKEN }}
|
|
35
|
+
SHOPIFY_STORE_URL: ${{ inputs.store_alias_secret && secrets[format('SHOPIFY_STORE_URL_{0}', inputs.store_alias_secret)] || secrets.SHOPIFY_STORE_URL }}
|
|
36
|
+
SHOPIFY_THEME_ACCESS_TOKEN: ${{ inputs.store_alias_secret && secrets[format('SHOPIFY_THEME_ACCESS_TOKEN_{0}', inputs.store_alias_secret)] || secrets.SHOPIFY_THEME_ACCESS_TOKEN }}
|
|
33
37
|
PR_NUMBER: ${{ inputs.pr_number }}
|
|
34
38
|
run: |
|
|
35
39
|
if [ -z "$SHOPIFY_STORE_URL" ] || [ -z "$SHOPIFY_THEME_ACCESS_TOKEN" ]; then
|
|
@@ -18,9 +18,7 @@ on:
|
|
|
18
18
|
store_alias_secret:
|
|
19
19
|
required: false
|
|
20
20
|
type: string
|
|
21
|
-
|
|
22
|
-
SHOPIFY_STORE_URL:
|
|
23
|
-
required: false
|
|
21
|
+
description: "Upper snake-case alias for scoped secret (e.g. VOLDT_STAGING). If set, uses SHOPIFY_STORE_URL_<this>; else uses SHOPIFY_STORE_URL."
|
|
24
22
|
|
|
25
23
|
jobs:
|
|
26
24
|
comment:
|
|
@@ -29,7 +27,7 @@ jobs:
|
|
|
29
27
|
- name: Post preview comment
|
|
30
28
|
uses: actions/github-script@v7
|
|
31
29
|
env:
|
|
32
|
-
SHOPIFY_STORE_URL: ${{ secrets.SHOPIFY_STORE_URL }}
|
|
30
|
+
SHOPIFY_STORE_URL: ${{ inputs.store_alias_secret && secrets[format('SHOPIFY_STORE_URL_{0}', inputs.store_alias_secret)] || secrets.SHOPIFY_STORE_URL }}
|
|
33
31
|
THEME_ID: ${{ inputs.theme_id }}
|
|
34
32
|
SHARE_OUTPUT: ${{ inputs.share_output }}
|
|
35
33
|
PR_NUMBER: ${{ inputs.pr_number }}
|
|
@@ -22,12 +22,7 @@ on:
|
|
|
22
22
|
store_alias_secret:
|
|
23
23
|
required: false
|
|
24
24
|
type: string
|
|
25
|
-
description: "Upper snake-case alias for scoped secret
|
|
26
|
-
secrets:
|
|
27
|
-
SHOPIFY_STORE_URL:
|
|
28
|
-
required: false
|
|
29
|
-
SHOPIFY_THEME_ACCESS_TOKEN:
|
|
30
|
-
required: false
|
|
25
|
+
description: "Upper snake-case alias for scoped secret (e.g. VOLDT_STAGING). If set, uses SHOPIFY_*_<this>; else uses SHOPIFY_STORE_URL / SHOPIFY_THEME_ACCESS_TOKEN."
|
|
31
26
|
|
|
32
27
|
jobs:
|
|
33
28
|
rename:
|
|
@@ -38,8 +33,8 @@ jobs:
|
|
|
38
33
|
|
|
39
34
|
- name: Rename theme
|
|
40
35
|
env:
|
|
41
|
-
SHOPIFY_STORE_URL: ${{ secrets.SHOPIFY_STORE_URL }}
|
|
42
|
-
SHOPIFY_THEME_ACCESS_TOKEN: ${{ secrets.SHOPIFY_THEME_ACCESS_TOKEN }}
|
|
36
|
+
SHOPIFY_STORE_URL: ${{ inputs.store_alias_secret && secrets[format('SHOPIFY_STORE_URL_{0}', inputs.store_alias_secret)] || secrets.SHOPIFY_STORE_URL }}
|
|
37
|
+
SHOPIFY_THEME_ACCESS_TOKEN: ${{ inputs.store_alias_secret && secrets[format('SHOPIFY_THEME_ACCESS_TOKEN_{0}', inputs.store_alias_secret)] || secrets.SHOPIFY_THEME_ACCESS_TOKEN }}
|
|
43
38
|
THEME_ID: ${{ inputs.theme_id }}
|
|
44
39
|
THEME_NAME: ${{ inputs.theme_name }}
|
|
45
40
|
PR_NUMBER: ${{ inputs.pr_number }}
|
|
@@ -14,7 +14,7 @@ on:
|
|
|
14
14
|
store_alias_secret:
|
|
15
15
|
required: false
|
|
16
16
|
type: string
|
|
17
|
-
description: "Upper snake-case alias for scoped secret
|
|
17
|
+
description: "Upper snake-case alias for scoped secret (e.g. VOLDT_STAGING). If set, uses SHOPIFY_*_<this>; else uses SHOPIFY_STORE_URL / SHOPIFY_THEME_ACCESS_TOKEN."
|
|
18
18
|
outputs:
|
|
19
19
|
theme_id:
|
|
20
20
|
description: "Shared theme ID"
|
|
@@ -25,11 +25,6 @@ on:
|
|
|
25
25
|
share_output:
|
|
26
26
|
description: "Raw share command output"
|
|
27
27
|
value: ${{ jobs.share.outputs.share_output }}
|
|
28
|
-
secrets:
|
|
29
|
-
SHOPIFY_STORE_URL:
|
|
30
|
-
required: false
|
|
31
|
-
SHOPIFY_THEME_ACCESS_TOKEN:
|
|
32
|
-
required: false
|
|
33
28
|
|
|
34
29
|
jobs:
|
|
35
30
|
share:
|
|
@@ -55,8 +50,8 @@ jobs:
|
|
|
55
50
|
- name: Share theme
|
|
56
51
|
id: share
|
|
57
52
|
env:
|
|
58
|
-
SHOPIFY_STORE_URL: ${{ secrets.SHOPIFY_STORE_URL }}
|
|
59
|
-
SHOPIFY_THEME_ACCESS_TOKEN: ${{ secrets.SHOPIFY_THEME_ACCESS_TOKEN }}
|
|
53
|
+
SHOPIFY_STORE_URL: ${{ inputs.store_alias_secret && secrets[format('SHOPIFY_STORE_URL_{0}', inputs.store_alias_secret)] || secrets.SHOPIFY_STORE_URL }}
|
|
54
|
+
SHOPIFY_THEME_ACCESS_TOKEN: ${{ inputs.store_alias_secret && secrets[format('SHOPIFY_THEME_ACCESS_TOKEN_{0}', inputs.store_alias_secret)] || secrets.SHOPIFY_THEME_ACCESS_TOKEN }}
|
|
60
55
|
run: |
|
|
61
56
|
if [ -z "$SHOPIFY_STORE_URL" ] || [ -z "$SHOPIFY_THEME_ACCESS_TOKEN" ]; then
|
|
62
57
|
echo "Missing Shopify secrets."
|