climaybe 3.4.4 → 3.4.5
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
CHANGED
|
@@ -233,11 +233,11 @@ Enabled via `climaybe init` prompt (`Enable preview + cleanup workflows?`; defau
|
|
|
233
233
|
|----------|---------|-------------|
|
|
234
234
|
| `pr-update.yml` | PR opened/synchronize/reopened (base: main, staging, develop, staging-*, live-*) | Shares draft theme, renames with `-PR<number>`, comments preview + customize URLs. **Multi-store + source branch (`pull_request.head.ref`) not** `staging-<alias>` **or** `live-<alias>`**:** publishes to **every** configured store (matrix) and posts **all** links in one PR comment. For `staging-<alias>` / `live-<alias>` source branches, only that store is used. **Path filter:** theme paths only (`assets/`, `blocks/`, `config/`, `layout/`, `locales/`, `sections/`, `snippets/`, `templates/`, `_scripts/`, `_styles/`, `shopify.theme.toml`, `stores/**`). |
|
|
235
235
|
| `pr-close.yml` | PR closed (same branch set) | Deletes this PR’s preview themes using the **same store matrix rule** as `pr-update`; PR comment shows **total** deleted count across stores. |
|
|
236
|
-
| `cleanup-orphan-preview-themes.yml` |
|
|
236
|
+
| `cleanup-orphan-preview-themes.yml` | PR closed (same branch set) + weekly (Mon 06:00 UTC) + `workflow_dispatch` | Per store: deletes themes ending with `-PR<n>` when PR `#n` is **not** open (merged/closed without cleanup). Uses `gh pr list` (limit 1000 open PRs). |
|
|
237
237
|
| `reusable-publish-pr-preview-store.yml` | workflow_call | Share + rename + upload comment fragment for **one** store (matrix leg in `pr-update`). |
|
|
238
238
|
| `reusable-share-theme.yml` | workflow_call | Shares Shopify draft theme and returns `theme_id` (still available if you call it elsewhere) |
|
|
239
239
|
| `reusable-rename-theme.yml` | workflow_call | Renames shared theme to include `PR<number>` (still available for custom flows) |
|
|
240
|
-
| `reusable-comment-on-pr.yml` | workflow_call |
|
|
240
|
+
| `reusable-comment-on-pr.yml` | workflow_call | Upserts one bot preview comment; aggregates `preview-fragment-*` artifacts when `use_preview_fragments` is true and removes older bot preview comments |
|
|
241
241
|
| `reusable-cleanup-themes.yml` | workflow_call | `cleanup_mode: by_pr` deletes names ending with `-PR{padded}`; `orphan_pr` deletes `-PR<n>` when PR `n` is not open. Optional `result_artifact_prefix` for matrix fan-in on `pr-close` |
|
|
242
242
|
| `reusable-extract-pr-number.yml` | workflow_call | Extracts padded/unpadded PR number outputs for naming and API-safe usage |
|
|
243
243
|
|
package/bin/version.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.4.
|
|
1
|
+
3.4.5
|
package/package.json
CHANGED
|
@@ -56,6 +56,7 @@ jobs:
|
|
|
56
56
|
const path = require('path');
|
|
57
57
|
const issueNumber = parseInt(process.env.PR_NUMBER);
|
|
58
58
|
const useFragments = process.env.USE_PREVIEW_FRAGMENTS === 'true';
|
|
59
|
+
const marker = '<!-- climaybe-preview-comment -->';
|
|
59
60
|
|
|
60
61
|
const walkJsonFiles = (dir) => {
|
|
61
62
|
const out = [];
|
|
@@ -84,6 +85,7 @@ jobs:
|
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
const parts = [
|
|
88
|
+
marker,
|
|
87
89
|
'## 🎨 Theme Preview Generated',
|
|
88
90
|
'',
|
|
89
91
|
`**Branch:** ${context.payload.pull_request?.head?.ref || context.ref.replace('refs/heads/', '')}`,
|
|
@@ -92,7 +94,12 @@ jobs:
|
|
|
92
94
|
|
|
93
95
|
if (fragments.length > 0) {
|
|
94
96
|
parts.push('', '### Preview links (per store)');
|
|
95
|
-
const
|
|
97
|
+
const uniqueByAlias = new Map();
|
|
98
|
+
for (const f of fragments) {
|
|
99
|
+
const alias = String(f.alias || '').trim() || 'store';
|
|
100
|
+
uniqueByAlias.set(alias, f);
|
|
101
|
+
}
|
|
102
|
+
const byAlias = [...uniqueByAlias.values()].sort((a, b) => String(a.alias).localeCompare(String(b.alias)));
|
|
96
103
|
for (const f of byAlias) {
|
|
97
104
|
const host = (f.store_host || '').replace(/\/$/, '');
|
|
98
105
|
const tid = f.theme_id || '';
|
|
@@ -129,10 +136,43 @@ jobs:
|
|
|
129
136
|
}
|
|
130
137
|
|
|
131
138
|
parts.push('', '---', '*This preview will be available for 7 days.*');
|
|
139
|
+
const body = parts.join('\n');
|
|
132
140
|
|
|
133
|
-
await github.rest.issues.
|
|
134
|
-
issue_number: issueNumber,
|
|
141
|
+
const comments = await github.paginate(github.rest.issues.listComments, {
|
|
135
142
|
owner: context.repo.owner,
|
|
136
143
|
repo: context.repo.repo,
|
|
137
|
-
|
|
144
|
+
issue_number: issueNumber,
|
|
145
|
+
per_page: 100
|
|
138
146
|
});
|
|
147
|
+
const managed = comments
|
|
148
|
+
.filter((c) => {
|
|
149
|
+
const text = String(c.body || '');
|
|
150
|
+
const botLike = c.user?.type === 'Bot' || String(c.user?.login || '').endsWith('[bot]');
|
|
151
|
+
const previewLike = text.includes(marker) || text.includes('## 🎨 Theme Preview Generated');
|
|
152
|
+
return botLike && previewLike;
|
|
153
|
+
})
|
|
154
|
+
.sort((a, b) => a.id - b.id);
|
|
155
|
+
|
|
156
|
+
if (managed.length > 0) {
|
|
157
|
+
const keep = managed[managed.length - 1];
|
|
158
|
+
await github.rest.issues.updateComment({
|
|
159
|
+
owner: context.repo.owner,
|
|
160
|
+
repo: context.repo.repo,
|
|
161
|
+
comment_id: keep.id,
|
|
162
|
+
body
|
|
163
|
+
});
|
|
164
|
+
for (const c of managed.slice(0, -1)) {
|
|
165
|
+
await github.rest.issues.deleteComment({
|
|
166
|
+
owner: context.repo.owner,
|
|
167
|
+
repo: context.repo.repo,
|
|
168
|
+
comment_id: c.id
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
} else {
|
|
172
|
+
await github.rest.issues.createComment({
|
|
173
|
+
issue_number: issueNumber,
|
|
174
|
+
owner: context.repo.owner,
|
|
175
|
+
repo: context.repo.repo,
|
|
176
|
+
body
|
|
177
|
+
});
|
|
178
|
+
}
|
|
@@ -143,20 +143,23 @@ jobs:
|
|
|
143
143
|
run: |
|
|
144
144
|
node <<'NODE'
|
|
145
145
|
const fs = require('fs');
|
|
146
|
+
const alias = process.env.STORE_ALIAS || 'store';
|
|
147
|
+
const safeAlias = alias.toLowerCase().replace(/[^a-z0-9_-]/g, '-');
|
|
148
|
+
const fileName = `fragment-${safeAlias || 'store'}.json`;
|
|
146
149
|
const url = (process.env.SHOPIFY_STORE_URL || '')
|
|
147
150
|
.replace(/^https?:\/\//, '')
|
|
148
151
|
.replace(/\/.*$/, '');
|
|
149
152
|
const payload = {
|
|
150
|
-
alias
|
|
153
|
+
alias,
|
|
151
154
|
theme_id: process.env.THEME_ID || '',
|
|
152
155
|
store_host: url,
|
|
153
156
|
};
|
|
154
|
-
fs.writeFileSync(
|
|
157
|
+
fs.writeFileSync(fileName, JSON.stringify(payload, null, 0));
|
|
155
158
|
NODE
|
|
156
159
|
|
|
157
160
|
- name: Upload preview fragment
|
|
158
161
|
uses: actions/upload-artifact@v4
|
|
159
162
|
with:
|
|
160
163
|
name: preview-fragment-${{ inputs.store_alias }}
|
|
161
|
-
path: fragment
|
|
164
|
+
path: fragment-*.json
|
|
162
165
|
retention-days: 2
|