pandorga 1.4.4 → 1.4.6
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -3
- data/functions/api/studio/_lib/github.js +138 -21
- data/lib/pandorga/version.rb +1 -1
- data/scripts/test/test-studio-api-contract.rb +8 -2
- data/scripts/test/test-studio-pipeline-config.mjs +35 -0
- data/scripts/validate.sh +5 -0
- data/studio/assets/{index-Cf9OPjQU.js → index-CMVzh8F1.js} +60 -60
- data/studio/index.html +1 -1
- data/studio-app/src/api/client.js +6 -4
- data/studio-app/src/main.js +71 -61
- metadata +3 -2
data/studio/index.html
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
rel="stylesheet"
|
|
19
19
|
href="https://cdn.jsdelivr.net/gh/lipis/flag-icons@7.2.3/css/flag-icons.min.css"
|
|
20
20
|
/>
|
|
21
|
-
<script type="module" crossorigin src="/studio/assets/index-
|
|
21
|
+
<script type="module" crossorigin src="/studio/assets/index-CMVzh8F1.js"></script>
|
|
22
22
|
<link rel="stylesheet" crossorigin href="/studio/assets/index-Cd1mlY_H.css">
|
|
23
23
|
</head>
|
|
24
24
|
<body>
|
|
@@ -73,10 +73,12 @@ export const studioApi = {
|
|
|
73
73
|
method: "POST",
|
|
74
74
|
body: JSON.stringify(payload),
|
|
75
75
|
}),
|
|
76
|
-
/** Content-pipeline run for a commit SHA
|
|
77
|
-
pipelineStatus: (sha, workflow = null) => {
|
|
78
|
-
const params = new URLSearchParams(
|
|
76
|
+
/** Content-pipeline run for a commit SHA, or latest on the branch when omitted. */
|
|
77
|
+
pipelineStatus: (sha = null, workflow = null) => {
|
|
78
|
+
const params = new URLSearchParams();
|
|
79
|
+
if (sha) params.set("sha", String(sha));
|
|
79
80
|
if (workflow) params.set("workflow", String(workflow));
|
|
80
|
-
|
|
81
|
+
const q = params.toString();
|
|
82
|
+
return api(q ? `pipeline-status?${q}` : "pipeline-status");
|
|
81
83
|
},
|
|
82
84
|
};
|
data/studio-app/src/main.js
CHANGED
|
@@ -892,7 +892,9 @@ function pipelineChipMeta(pipelineState) {
|
|
|
892
892
|
icon: "cloud_off",
|
|
893
893
|
className: "pipeline-chip pipeline-idle",
|
|
894
894
|
spinning: false,
|
|
895
|
-
title:
|
|
895
|
+
title:
|
|
896
|
+
state.pipeline.message ||
|
|
897
|
+
"Set pandorga.content.workflow in _config.yml (e.g. content-pipeline.yml)",
|
|
896
898
|
};
|
|
897
899
|
default:
|
|
898
900
|
return {
|
|
@@ -940,6 +942,38 @@ function renderPipelineChip() {
|
|
|
940
942
|
);
|
|
941
943
|
}
|
|
942
944
|
|
|
945
|
+
function applyPipelinePayload(data) {
|
|
946
|
+
state.pipeline.runUrl = data.run?.html_url || state.pipeline.runUrl || "";
|
|
947
|
+
if (data.sha) state.pipeline.sha = String(data.sha).toLowerCase();
|
|
948
|
+
state.pipeline.message = "";
|
|
949
|
+
if (data.state === "unconfigured") {
|
|
950
|
+
state.pipeline.state = "unconfigured";
|
|
951
|
+
state.pipeline.message =
|
|
952
|
+
data.message ||
|
|
953
|
+
"Set pandorga.content.workflow in _config.yml (e.g. content-pipeline.yml)";
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
state.pipeline.state = data.state || "idle";
|
|
957
|
+
if (data.state === "error") {
|
|
958
|
+
state.pipeline.message =
|
|
959
|
+
data.message || "Content pipeline failed for this commit.";
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
/** Hydrate the always-visible chip from the latest workflow run (or a SHA). */
|
|
964
|
+
async function refreshPipelineStatus(sha = null) {
|
|
965
|
+
if (isLocalDevHost()) return;
|
|
966
|
+
try {
|
|
967
|
+
const data = await studioApi.pipelineStatus(sha || null);
|
|
968
|
+
applyPipelinePayload(data);
|
|
969
|
+
renderShell();
|
|
970
|
+
} catch (err) {
|
|
971
|
+
state.pipeline.state = "error";
|
|
972
|
+
state.pipeline.message = String(err.message || err);
|
|
973
|
+
renderShell();
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
|
|
943
977
|
/**
|
|
944
978
|
* After a production Save, poll Actions for the content-pipeline run on this SHA.
|
|
945
979
|
*/
|
|
@@ -976,32 +1010,17 @@ async function pollPipelineStatus(gen, sha) {
|
|
|
976
1010
|
const data = await studioApi.pipelineStatus(sha);
|
|
977
1011
|
if (gen !== state.pipeline.pollGen) return;
|
|
978
1012
|
softFails = 0;
|
|
979
|
-
|
|
980
|
-
state.pipeline.message = "";
|
|
1013
|
+
applyPipelinePayload(data);
|
|
981
1014
|
|
|
982
|
-
if (data.state === "unconfigured") {
|
|
983
|
-
state.pipeline.state = "unconfigured";
|
|
1015
|
+
if (data.state === "unconfigured" || data.state === "ok" || data.state === "error") {
|
|
984
1016
|
renderShell();
|
|
985
1017
|
return;
|
|
986
1018
|
}
|
|
987
|
-
if (data.state === "
|
|
988
|
-
state.pipeline.state =
|
|
989
|
-
if (data.state === "error") {
|
|
990
|
-
state.pipeline.message = "Content pipeline failed for this commit.";
|
|
991
|
-
}
|
|
1019
|
+
if (data.state === "awaiting_run" && elapsed > STALL_MS) {
|
|
1020
|
+
state.pipeline.state = "stalled";
|
|
992
1021
|
renderShell();
|
|
993
1022
|
return;
|
|
994
1023
|
}
|
|
995
|
-
if (data.state === "running") {
|
|
996
|
-
state.pipeline.state = "running";
|
|
997
|
-
} else if (data.state === "awaiting_run") {
|
|
998
|
-
if (elapsed > STALL_MS) {
|
|
999
|
-
state.pipeline.state = "stalled";
|
|
1000
|
-
renderShell();
|
|
1001
|
-
return;
|
|
1002
|
-
}
|
|
1003
|
-
state.pipeline.state = "awaiting_run";
|
|
1004
|
-
}
|
|
1005
1024
|
renderShell();
|
|
1006
1025
|
} catch (err) {
|
|
1007
1026
|
if (gen !== state.pipeline.pollGen) return;
|
|
@@ -1114,8 +1133,35 @@ function renderStudioToolbar({ brand = null, menuToggle = null } = {}) {
|
|
|
1114
1133
|
: null,
|
|
1115
1134
|
]);
|
|
1116
1135
|
|
|
1117
|
-
const actions = [
|
|
1118
|
-
|
|
1136
|
+
const actions = [renderThemeMenu()];
|
|
1137
|
+
|
|
1138
|
+
// Theme → pipeline/Export → Revert → Save. Pipeline chip is always present.
|
|
1139
|
+
if (isLocalDevHost()) {
|
|
1140
|
+
const exportBusy = state.reexporting || state.pipeline.state === "syncing";
|
|
1141
|
+
actions.push(
|
|
1142
|
+
toolbarActionButton({
|
|
1143
|
+
className:
|
|
1144
|
+
"btn btn-tool btn-reexport" +
|
|
1145
|
+
(exportBusy ? " pipeline-running" : "") +
|
|
1146
|
+
(state.pipeline.state === "ok" && !exportBusy ? " pipeline-ok" : "") +
|
|
1147
|
+
(state.pipeline.state === "error" && !exportBusy ? " pipeline-error" : ""),
|
|
1148
|
+
title: exportBusy
|
|
1149
|
+
? "Exporting content JSON locally"
|
|
1150
|
+
: "Export content JSON locally and reload",
|
|
1151
|
+
ariaLabel: exportBusy ? "Exporting locally" : "Export locally",
|
|
1152
|
+
action: "reexport",
|
|
1153
|
+
disabled: exportBusy,
|
|
1154
|
+
onClick: () => reexportLocalContent(),
|
|
1155
|
+
icon: exportBusy ? "progress_activity" : "sync",
|
|
1156
|
+
label: exportBusy ? "Exporting…" : "Export",
|
|
1157
|
+
spinning: exportBusy,
|
|
1158
|
+
})
|
|
1159
|
+
);
|
|
1160
|
+
} else {
|
|
1161
|
+
actions.push(renderPipelineChip());
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
actions.push(
|
|
1119
1165
|
toolbarActionButton({
|
|
1120
1166
|
className: "btn btn-tool",
|
|
1121
1167
|
title: "Revert all edits to the last loaded or saved version",
|
|
@@ -1140,45 +1186,8 @@ function renderStudioToolbar({ brand = null, menuToggle = null } = {}) {
|
|
|
1140
1186
|
icon: saveIcon,
|
|
1141
1187
|
label: saveLabel,
|
|
1142
1188
|
spinning: state.saving,
|
|
1143
|
-
})
|
|
1144
|
-
|
|
1145
|
-
if (state.file && collectionAllowsDelete()) {
|
|
1146
|
-
actions.push(
|
|
1147
|
-
toolbarActionButton({
|
|
1148
|
-
className: "btn btn-tool btn-danger",
|
|
1149
|
-
title: "Delete this entry from the repository",
|
|
1150
|
-
ariaLabel: "Delete entry",
|
|
1151
|
-
action: "delete",
|
|
1152
|
-
onClick: () => deleteCurrentEntry(),
|
|
1153
|
-
icon: "delete",
|
|
1154
|
-
label: "Delete",
|
|
1155
|
-
})
|
|
1156
|
-
);
|
|
1157
|
-
}
|
|
1158
|
-
if (isLocalDevHost()) {
|
|
1159
|
-
const exportBusy = state.reexporting || state.pipeline.state === "syncing";
|
|
1160
|
-
actions.push(
|
|
1161
|
-
toolbarActionButton({
|
|
1162
|
-
className:
|
|
1163
|
-
"btn btn-tool btn-reexport" +
|
|
1164
|
-
(exportBusy ? " pipeline-running" : "") +
|
|
1165
|
-
(state.pipeline.state === "ok" && !exportBusy ? " pipeline-ok" : "") +
|
|
1166
|
-
(state.pipeline.state === "error" && !exportBusy ? " pipeline-error" : ""),
|
|
1167
|
-
title: exportBusy
|
|
1168
|
-
? "Exporting content JSON locally"
|
|
1169
|
-
: "Export content JSON locally and reload",
|
|
1170
|
-
ariaLabel: exportBusy ? "Exporting locally" : "Export locally",
|
|
1171
|
-
action: "reexport",
|
|
1172
|
-
disabled: exportBusy,
|
|
1173
|
-
onClick: () => reexportLocalContent(),
|
|
1174
|
-
icon: exportBusy ? "progress_activity" : "sync",
|
|
1175
|
-
label: exportBusy ? "Exporting…" : "Export",
|
|
1176
|
-
spinning: exportBusy,
|
|
1177
|
-
})
|
|
1178
|
-
);
|
|
1179
|
-
} else if (state.pipeline.state !== "idle") {
|
|
1180
|
-
actions.push(renderPipelineChip());
|
|
1181
|
-
}
|
|
1189
|
+
})
|
|
1190
|
+
);
|
|
1182
1191
|
|
|
1183
1192
|
const kids = [
|
|
1184
1193
|
brandCluster,
|
|
@@ -4257,6 +4266,7 @@ async function bootApp(clerk) {
|
|
|
4257
4266
|
}
|
|
4258
4267
|
|
|
4259
4268
|
renderShell();
|
|
4269
|
+
void refreshPipelineStatus();
|
|
4260
4270
|
|
|
4261
4271
|
scheduleTreePrefetch();
|
|
4262
4272
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pandorga
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.4.
|
|
4
|
+
version: 1.4.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- The Pandorga contributors
|
|
@@ -412,6 +412,7 @@ files:
|
|
|
412
412
|
- scripts/test/test-studio-api-contract.rb
|
|
413
413
|
- scripts/test/test-studio-content-files.rb
|
|
414
414
|
- scripts/test/test-studio-liquid-roundtrip.mjs
|
|
415
|
+
- scripts/test/test-studio-pipeline-config.mjs
|
|
415
416
|
- scripts/test/test-studio-rate-limit.mjs
|
|
416
417
|
- scripts/test/test-studio-rewrite-api-contract.rb
|
|
417
418
|
- scripts/test/test-studio-rewrite-sanitize.mjs
|
|
@@ -449,8 +450,8 @@ files:
|
|
|
449
450
|
- studio-app/src/preview/render.js
|
|
450
451
|
- studio-app/src/styles/studio.css
|
|
451
452
|
- studio-app/vite.config.js
|
|
453
|
+
- studio/assets/index-CMVzh8F1.js
|
|
452
454
|
- studio/assets/index-Cd1mlY_H.css
|
|
453
|
-
- studio/assets/index-Cf9OPjQU.js
|
|
454
455
|
- studio/index.html
|
|
455
456
|
- studio/schema.yml
|
|
456
457
|
- templates/articles/README.md
|