@design-parity/action 0.1.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.
Files changed (66) hide show
  1. package/README.md +109 -0
  2. package/dist/baseline.d.ts +48 -0
  3. package/dist/baseline.d.ts.map +1 -0
  4. package/dist/baseline.js +126 -0
  5. package/dist/baseline.js.map +1 -0
  6. package/dist/candidate.d.ts +48 -0
  7. package/dist/candidate.d.ts.map +1 -0
  8. package/dist/candidate.js +109 -0
  9. package/dist/candidate.js.map +1 -0
  10. package/dist/cli/action.d.ts +3 -0
  11. package/dist/cli/action.d.ts.map +1 -0
  12. package/dist/cli/action.js +222 -0
  13. package/dist/cli/action.js.map +1 -0
  14. package/dist/cli/run.d.ts +3 -0
  15. package/dist/cli/run.d.ts.map +1 -0
  16. package/dist/cli/run.js +123 -0
  17. package/dist/cli/run.js.map +1 -0
  18. package/dist/config.d.ts +23 -0
  19. package/dist/config.d.ts.map +1 -0
  20. package/dist/config.js +46 -0
  21. package/dist/config.js.map +1 -0
  22. package/dist/github/changed-components.d.ts +15 -0
  23. package/dist/github/changed-components.d.ts.map +1 -0
  24. package/dist/github/changed-components.js +18 -0
  25. package/dist/github/changed-components.js.map +1 -0
  26. package/dist/github/conclusion.d.ts +16 -0
  27. package/dist/github/conclusion.d.ts.map +1 -0
  28. package/dist/github/conclusion.js +17 -0
  29. package/dist/github/conclusion.js.map +1 -0
  30. package/dist/github/publish.d.ts +50 -0
  31. package/dist/github/publish.d.ts.map +1 -0
  32. package/dist/github/publish.js +91 -0
  33. package/dist/github/publish.js.map +1 -0
  34. package/dist/github/rest.d.ts +29 -0
  35. package/dist/github/rest.d.ts.map +1 -0
  36. package/dist/github/rest.js +64 -0
  37. package/dist/github/rest.js.map +1 -0
  38. package/dist/github/surface.d.ts +17 -0
  39. package/dist/github/surface.d.ts.map +1 -0
  40. package/dist/github/surface.js +21 -0
  41. package/dist/github/surface.js.map +1 -0
  42. package/dist/index.d.ts +33 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +23 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/mode.d.ts +35 -0
  47. package/dist/mode.d.ts.map +1 -0
  48. package/dist/mode.js +25 -0
  49. package/dist/mode.js.map +1 -0
  50. package/dist/orchestrate.d.ts +80 -0
  51. package/dist/orchestrate.d.ts.map +1 -0
  52. package/dist/orchestrate.js +100 -0
  53. package/dist/orchestrate.js.map +1 -0
  54. package/dist/pushback.d.ts +81 -0
  55. package/dist/pushback.d.ts.map +1 -0
  56. package/dist/pushback.js +106 -0
  57. package/dist/pushback.js.map +1 -0
  58. package/dist/registry.d.ts +24 -0
  59. package/dist/registry.d.ts.map +1 -0
  60. package/dist/registry.js +14 -0
  61. package/dist/registry.js.map +1 -0
  62. package/dist/report.d.ts +29 -0
  63. package/dist/report.d.ts.map +1 -0
  64. package/dist/report.js +72 -0
  65. package/dist/report.js.map +1 -0
  66. package/package.json +40 -0
@@ -0,0 +1,222 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * GitHub Action entrypoint. Auto-selects its mode from the triggering event
4
+ * (issue #56), staying unattended throughout: zero human input, only committed
5
+ * deterministic artifacts, no model call (docs/PRINCIPLES.md).
6
+ *
7
+ * - **comment** (a `pull_request`): keep the changed-component components, run
8
+ * the pipeline, and post/update the single verdict comment. Exits non-zero
9
+ * only when the parity direction blocks (`design-led` + a failure).
10
+ * - **baseline** (a `push` to the `development-branch`): render the full mapped
11
+ * surface and publish the browsable artifacts (`index.html` + per-component
12
+ * `report.html` triptychs + `verdict.json`) to a permanent artifact branch,
13
+ * force-updated each run. Requires a token with `contents: write`.
14
+ * - **skip**: nothing applies (e.g. a push to a non-dev branch).
15
+ *
16
+ * Reads the standard Action environment (`GITHUB_TOKEN`, `GITHUB_REPOSITORY`,
17
+ * `GITHUB_EVENT_PATH`, `GITHUB_WORKSPACE`, `GITHUB_EVENT_NAME`, `GITHUB_REF_NAME`,
18
+ * `GITHUB_SHA`). Candidate renders come from a committed/produced
19
+ * `CandidateRender[]` JSON (`INPUT_CANDIDATES`) and/or compose-preview bundles
20
+ * (`INPUT_CANDIDATE_BUNDLES`) — live rendering is the consumer's prior step.
21
+ */
22
+ import { env, cwd, exit, stdout, stderr } from "node:process";
23
+ import { readFile, mkdtemp } from "node:fs/promises";
24
+ import { tmpdir } from "node:os";
25
+ import { join } from "node:path";
26
+ import { resolve as resolveCorrespondences } from "@design-parity/resolver";
27
+ import { FigmaCanvasWriter } from "@design-parity/adapter-figma";
28
+ import { buildCandidateProvider } from "../candidate.js";
29
+ import { pushBack } from "../pushback.js";
30
+ import { resolveRunConfig } from "../config.js";
31
+ import { createAdapterRegistry } from "../registry.js";
32
+ import { orchestrate } from "../orchestrate.js";
33
+ import { renderReport, renderBootstrapNotice } from "../report.js";
34
+ import { GitHubRest } from "../github/rest.js";
35
+ import { postReport } from "../github/surface.js";
36
+ import { componentsForChangedFiles } from "../github/changed-components.js";
37
+ import { exitCode } from "../github/conclusion.js";
38
+ import { publishBaseline } from "../github/publish.js";
39
+ import { writeBaselineArtifacts } from "../baseline.js";
40
+ import { selectMode } from "../mode.js";
41
+ /** Whether an Action input string is set to a truthy opt-in value. */
42
+ function isOptedIn(value) {
43
+ if (!value)
44
+ return false;
45
+ return ["1", "true", "yes", "on"].includes(value.trim().toLowerCase());
46
+ }
47
+ /**
48
+ * Build the Code-to-Canvas writer (issue #9) from the configured bridge
49
+ * endpoint. Returns `undefined` when no endpoint is set, so push-back no-ops
50
+ * with a clear log even when opted in — the Figma REST API can't write, so a
51
+ * bridge must be configured for the candidate to reach the canvas.
52
+ */
53
+ function canvasWriter() {
54
+ const endpoint = env.INPUT_CANVAS_ENDPOINT ?? env.FIGMA_CANVAS_ENDPOINT;
55
+ if (!endpoint?.trim())
56
+ return undefined;
57
+ const token = env.INPUT_CANVAS_TOKEN ?? env.FIGMA_CANVAS_TOKEN ?? env.FIGMA_OAUTH_TOKEN;
58
+ return new FigmaCanvasWriter({ endpoint, ...(token ? { token } : {}) });
59
+ }
60
+ async function readPrNumber() {
61
+ const path = env.GITHUB_EVENT_PATH;
62
+ if (!path)
63
+ return undefined;
64
+ try {
65
+ const event = JSON.parse(await readFile(path, "utf8"));
66
+ return event.pull_request?.number ?? event.number;
67
+ }
68
+ catch {
69
+ return undefined;
70
+ }
71
+ }
72
+ /** Build the candidate provider from the committed JSON / bundle inputs. */
73
+ async function candidateProvider(repoRoot, designMap) {
74
+ const candidatesPath = env.INPUT_CANDIDATES ?? env.DESIGN_PARITY_CANDIDATES;
75
+ const bundles = (env.INPUT_CANDIDATE_BUNDLES ?? "")
76
+ .split(",")
77
+ .map((s) => s.trim())
78
+ .filter(Boolean);
79
+ const opts = {
80
+ repoRoot,
81
+ bundlePaths: bundles,
82
+ };
83
+ if (designMap)
84
+ opts.designMap = designMap;
85
+ if (candidatesPath)
86
+ opts.candidatesPath = candidatesPath;
87
+ const { provider, warnings } = await buildCandidateProvider(opts);
88
+ return { provider: provider ?? (() => undefined), warnings };
89
+ }
90
+ /** comment mode: changed-component parity run + the single verdict comment. */
91
+ async function runComment(ref, repoRoot, rest, prNumber) {
92
+ const { designMap, direction, cmpCapable, warnings } = await resolveRunConfig(repoRoot);
93
+ // No committed setup at all: don't guess the design ↔ code mapping at run time
94
+ // (Principle 1). Post a comment pointing at the interactive bootstrap (#11)
95
+ // instead of silently skipping, so the repo owner knows parity isn't wired up.
96
+ if (!designMap || designMap.components.length === 0) {
97
+ const outcome = await postReport(rest.commentClient(ref, prNumber), renderBootstrapNotice());
98
+ stdout.write(`design-parity: ${outcome} bootstrap notice — no committed design-map.json (run design-parity-bootstrap)\n`);
99
+ return 0;
100
+ }
101
+ const changedFiles = await rest.listPullRequestFiles(ref, prNumber);
102
+ const components = componentsForChangedFiles(designMap, changedFiles);
103
+ if (components.length === 0) {
104
+ stdout.write("design-parity: no design-mapped components changed — skipping (non-UI PR)\n");
105
+ return 0;
106
+ }
107
+ const resolved = resolveCorrespondences(components, designMap ? { designMap } : {});
108
+ const { provider, warnings: candidateWarnings } = await candidateProvider(repoRoot, designMap);
109
+ const report = await orchestrate({
110
+ repoRoot,
111
+ env,
112
+ registry: createAdapterRegistry(),
113
+ correspondences: resolved.correspondences,
114
+ candidate: provider,
115
+ direction,
116
+ ...(env.DESIGN_PARITY_OUT ? { outDir: env.DESIGN_PARITY_OUT } : {}),
117
+ });
118
+ report.warnings.unshift(...warnings, ...resolved.warnings, ...candidateWarnings, ...resolved.unresolved.map((u) => `unresolved (no source matched): ${u}`));
119
+ // Promote CMP to Android-only repos in the comment (Principle 6); advisory.
120
+ if (typeof cmpCapable === "boolean")
121
+ report.cmpCapable = cmpCapable;
122
+ const outcome = await postReport(rest.commentClient(ref, prNumber), renderReport(report));
123
+ stdout.write(`design-parity: ${outcome} report — status=${report.status} blocked=${report.blocked}\n`);
124
+ // Optional Code-to-Canvas push-back (#9): gated on the opt-in flag + a
125
+ // `code-led` direction + a `figma` source, and a no-op (with a log) otherwise.
126
+ // A side effect only — it never changes the PR verdict / exit code.
127
+ const writer = canvasWriter();
128
+ await pushBack({
129
+ report,
130
+ enabled: isOptedIn(env.INPUT_PUSH_BACK ?? env.DESIGN_PARITY_PUSH_BACK),
131
+ ...(writer ? { writer } : {}),
132
+ ctx: { repoRoot, env },
133
+ log: (m) => stdout.write(m + "\n"),
134
+ });
135
+ return exitCode(report);
136
+ }
137
+ /** baseline mode: full-surface parity run published to the artifact branch. */
138
+ async function runBaseline(ref, repoRoot, token, artifactBranch) {
139
+ const { designMap, direction, warnings } = await resolveRunConfig(repoRoot);
140
+ const components = designMap?.components.map((c) => c.code) ?? [];
141
+ if (components.length === 0) {
142
+ stdout.write("design-parity: no components in design-map.json — nothing to baseline\n");
143
+ return 0;
144
+ }
145
+ const resolved = resolveCorrespondences(components, designMap ? { designMap } : {});
146
+ const { provider, warnings: candidateWarnings } = await candidateProvider(repoRoot, designMap);
147
+ const outDir = await mkdtemp(join(tmpdir(), "design-parity-baseline-"));
148
+ const report = await orchestrate({
149
+ repoRoot,
150
+ env,
151
+ registry: createAdapterRegistry(),
152
+ correspondences: resolved.correspondences,
153
+ candidate: provider,
154
+ direction,
155
+ outDir,
156
+ });
157
+ report.warnings.unshift(...warnings, ...resolved.warnings, ...candidateWarnings, ...resolved.unresolved.map((u) => `unresolved (no source matched): ${u}`));
158
+ const commit = env.GITHUB_SHA;
159
+ const { summary } = await writeBaselineArtifacts(outDir, report, {
160
+ ...(commit ? { commit } : {}),
161
+ });
162
+ const result = await publishBaseline({
163
+ sourceDir: outDir,
164
+ branch: artifactBranch,
165
+ repo: `${ref.owner}/${ref.repo}`,
166
+ token,
167
+ message: `design-parity: baseline ${summary.status}${commit ? ` @ ${commit.slice(0, 12)}` : ""}`,
168
+ skipIfUnchanged: true,
169
+ ...(env.GITHUB_SERVER_URL ? { serverUrl: env.GITHUB_SERVER_URL } : {}),
170
+ });
171
+ stdout.write(result.pushed
172
+ ? `design-parity: published baseline to ${result.branch} (${result.sha?.slice(0, 12)}) — status=${summary.status}\n`
173
+ : `design-parity: baseline unchanged vs ${result.branch} — nothing to publish\n`);
174
+ // Baseline mode never blocks the dev-branch push; it only publishes.
175
+ return 0;
176
+ }
177
+ async function main() {
178
+ const token = env.GITHUB_TOKEN ?? env.INPUT_GITHUB_TOKEN;
179
+ const repository = env.GITHUB_REPOSITORY;
180
+ if (!token || !repository) {
181
+ stderr.write("design-parity: GITHUB_TOKEN and GITHUB_REPOSITORY are required\n");
182
+ return 2;
183
+ }
184
+ const [owner, repo] = repository.split("/");
185
+ if (!owner || !repo) {
186
+ stderr.write(`design-parity: bad GITHUB_REPOSITORY '${repository}'\n`);
187
+ return 2;
188
+ }
189
+ const ref = { owner, repo };
190
+ const repoRoot = env.GITHUB_WORKSPACE ?? cwd();
191
+ const developmentBranch = env.INPUT_DEVELOPMENT_BRANCH?.trim() || "main";
192
+ const artifactBranch = env.INPUT_ARTIFACT_BRANCH?.trim() || `design-parity/${developmentBranch}`;
193
+ const prNumber = await readPrNumber();
194
+ const mode = selectMode({
195
+ eventName: env.GITHUB_EVENT_NAME,
196
+ refName: env.GITHUB_REF_NAME,
197
+ developmentBranch,
198
+ ...(env.INPUT_MODE ? { override: env.INPUT_MODE } : {}),
199
+ ...(prNumber ? { prNumber } : {}),
200
+ });
201
+ switch (mode) {
202
+ case "baseline":
203
+ stdout.write(`design-parity: baseline mode → ${artifactBranch}\n`);
204
+ return runBaseline(ref, repoRoot, token, artifactBranch);
205
+ case "comment": {
206
+ if (!prNumber) {
207
+ stdout.write("design-parity: comment mode but no pull_request in context — nothing to do\n");
208
+ return 0;
209
+ }
210
+ const rest = new GitHubRest({
211
+ token,
212
+ ...(env.GITHUB_API_URL ? { baseUrl: env.GITHUB_API_URL } : {}),
213
+ });
214
+ return runComment(ref, repoRoot, rest, prNumber);
215
+ }
216
+ default:
217
+ stdout.write(`design-parity: nothing to do for event='${env.GITHUB_EVENT_NAME}' ref='${env.GITHUB_REF_NAME}' (not the development branch '${developmentBranch}')\n`);
218
+ return 0;
219
+ }
220
+ }
221
+ exit(await main());
222
+ //# sourceMappingURL=action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action.js","sourceRoot":"","sources":["../../src/cli/action.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":""}
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * `design-parity run` — a local parity run.
4
+ *
5
+ * design-parity run --repo . --components ui/Button.kt#PrimaryButton \
6
+ * --candidates candidates.json --out .design-parity/out
7
+ *
8
+ * Reads the committed `design-map.json` + `.design-parity.json`, resolves each
9
+ * changed component to a design reference, diffs it against the candidate
10
+ * render, and prints the markdown report. Exits non-zero only when the parity
11
+ * direction blocks (`design-led` + a failure).
12
+ *
13
+ * Candidate renders come from committed, offline inputs (reproducible — no live
14
+ * render at run time): `--candidates <file>` (a precomputed `CandidateRender[]`)
15
+ * and/or `--candidate-bundles <png|dir,...>` (compose-ai-tools preview-bundle
16
+ * polyglots, read statically by `@design-parity/candidate`; issue #38 Phase 1).
17
+ * When both are given, bundles win and the JSON is the fallback.
18
+ */
19
+ import { argv, cwd, env, exit, stdout } from "node:process";
20
+ import { resolve as resolvePath } from "node:path";
21
+ import { resolve as resolveCorrespondences } from "@design-parity/resolver";
22
+ import { FigmaCanvasWriter } from "@design-parity/adapter-figma";
23
+ import { buildCandidateProvider } from "../candidate.js";
24
+ import { resolveRunConfig } from "../config.js";
25
+ import { createAdapterRegistry } from "../registry.js";
26
+ import { orchestrate } from "../orchestrate.js";
27
+ import { pushBack } from "../pushback.js";
28
+ import { renderReport } from "../report.js";
29
+ function parseArgs(args) {
30
+ const out = { repoRoot: cwd(), components: [], bundlePaths: [], pushBack: false };
31
+ for (let i = 0; i < args.length; i++) {
32
+ const a = args[i];
33
+ const next = () => args[(i += 1)];
34
+ switch (a) {
35
+ case "run":
36
+ break;
37
+ case "--repo":
38
+ out.repoRoot = resolvePath(next() ?? ".");
39
+ break;
40
+ case "--components":
41
+ out.components.push(...(next() ?? "").split(",").filter(Boolean));
42
+ break;
43
+ case "--candidates":
44
+ out.candidatesPath = next();
45
+ break;
46
+ case "--candidate-bundles":
47
+ out.bundlePaths.push(...(next() ?? "").split(",").filter(Boolean));
48
+ break;
49
+ case "--out":
50
+ out.outDir = next();
51
+ break;
52
+ case "--push-back":
53
+ out.pushBack = true;
54
+ break;
55
+ case "--canvas-endpoint":
56
+ out.canvasEndpoint = next();
57
+ break;
58
+ default:
59
+ if (a && !a.startsWith("--"))
60
+ out.components.push(a);
61
+ }
62
+ }
63
+ return out;
64
+ }
65
+ async function main() {
66
+ const args = parseArgs(argv.slice(2));
67
+ if (args.components.length === 0) {
68
+ stdout.write("design-parity run --components <code#Member,...> [--repo .] " +
69
+ "[--candidates file.json] [--candidate-bundles <png|dir,...>] [--out dir] " +
70
+ "[--push-back [--canvas-endpoint <url>]]\n");
71
+ return 2;
72
+ }
73
+ const { designMap, direction, cmpCapable, warnings } = await resolveRunConfig(args.repoRoot);
74
+ const resolved = resolveCorrespondences(args.components, { designMap });
75
+ const candidateOpts = {
76
+ repoRoot: args.repoRoot,
77
+ bundlePaths: args.bundlePaths,
78
+ };
79
+ if (designMap)
80
+ candidateOpts.designMap = designMap;
81
+ if (args.candidatesPath)
82
+ candidateOpts.candidatesPath = args.candidatesPath;
83
+ const { provider, warnings: candidateWarnings } = await buildCandidateProvider(candidateOpts);
84
+ const report = await orchestrate({
85
+ repoRoot: args.repoRoot,
86
+ env,
87
+ registry: createAdapterRegistry(),
88
+ correspondences: resolved.correspondences,
89
+ candidate: provider ?? (() => undefined),
90
+ direction,
91
+ ...(args.outDir ? { outDir: args.outDir } : {}),
92
+ });
93
+ report.warnings.unshift(...warnings, ...resolved.warnings, ...candidateWarnings, ...resolved.unresolved.map((u) => `unresolved (no source matched): ${u}`));
94
+ // Promote CMP in the comment for Android-only repos (Principle 6). Read from
95
+ // the committed config (set false by bootstrap on a non-CMP repo); advisory
96
+ // only, so it never touches the verdict or exit code.
97
+ if (typeof cmpCapable === "boolean")
98
+ report.cmpCapable = cmpCapable;
99
+ stdout.write(renderReport(report) + "\n");
100
+ // Optional Code-to-Canvas push-back (#9): no-op (with a log) unless the
101
+ // `--push-back` flag is set, the direction is `code-led`, and a figma bridge
102
+ // endpoint is configured. A side effect only — it never affects the exit code.
103
+ const endpoint = args.canvasEndpoint ?? env.FIGMA_CANVAS_ENDPOINT;
104
+ await pushBack({
105
+ report,
106
+ enabled: args.pushBack,
107
+ ...(endpoint ? { writer: new FigmaCanvasWriter({ endpoint }) } : {}),
108
+ ctx: { repoRoot: args.repoRoot, env },
109
+ log: (m) => stdout.write(m + "\n"),
110
+ });
111
+ // Point at the self-contained HTML comparison pages, when written (#50).
112
+ const pages = report.results
113
+ .map((r) => r.reportPath)
114
+ .filter((p) => p !== undefined);
115
+ if (pages.length > 0) {
116
+ stdout.write(`\nWrote ${pages.length} comparison page(s):\n` +
117
+ pages.map((p) => ` ${p}`).join("\n") +
118
+ "\n");
119
+ }
120
+ return report.blocked ? 1 : 0;
121
+ }
122
+ exit(await main());
123
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,WAAW,CAAC;AAEnD,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAY5C,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,GAAG,GAAS,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACxF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClC,QAAQ,CAAC,EAAE,CAAC;YACV,KAAK,KAAK;gBACR,MAAM;YACR,KAAK,QAAQ;gBACX,GAAG,CAAC,QAAQ,GAAG,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,CAAC;gBAC1C,MAAM;YACR,KAAK,cAAc;gBACjB,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;gBAClE,MAAM;YACR,KAAK,cAAc;gBACjB,GAAG,CAAC,cAAc,GAAG,IAAI,EAAE,CAAC;gBAC5B,MAAM;YACR,KAAK,qBAAqB;gBACxB,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;gBACnE,MAAM;YACR,KAAK,OAAO;gBACV,GAAG,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;gBACpB,MAAM;YACR,KAAK,aAAa;gBAChB,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACpB,MAAM;YACR,KAAK,mBAAmB;gBACtB,GAAG,CAAC,cAAc,GAAG,IAAI,EAAE,CAAC;gBAC5B,MAAM;YACR;gBACE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC;oBAAE,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,MAAM,CAAC,KAAK,CACV,8DAA8D;YAC5D,2EAA2E;YAC3E,2CAA2C,CAC9C,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,MAAM,gBAAgB,CAC3E,IAAI,CAAC,QAAQ,CACd,CAAC;IACF,MAAM,QAAQ,GAAG,sBAAsB,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IAExE,MAAM,aAAa,GAAiD;QAClE,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,WAAW,EAAE,IAAI,CAAC,WAAW;KAC9B,CAAC;IACF,IAAI,SAAS;QAAE,aAAa,CAAC,SAAS,GAAG,SAAS,CAAC;IACnD,IAAI,IAAI,CAAC,cAAc;QAAE,aAAa,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC;IAC5E,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,EAAE,GAC7C,MAAM,sBAAsB,CAAC,aAAa,CAAC,CAAC;IAE9C,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC;QAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,GAAG;QACH,QAAQ,EAAE,qBAAqB,EAAE;QACjC,eAAe,EAAE,QAAQ,CAAC,eAAe;QACzC,SAAS,EAAE,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC;QACxC,SAAS;QACT,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChD,CAAC,CAAC;IAEH,MAAM,CAAC,QAAQ,CAAC,OAAO,CACrB,GAAG,QAAQ,EACX,GAAG,QAAQ,CAAC,QAAQ,EACpB,GAAG,iBAAiB,EACpB,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,mCAAmC,CAAC,EAAE,CAAC,CAC1E,CAAC;IAEF,6EAA6E;IAC7E,4EAA4E;IAC5E,sDAAsD;IACtD,IAAI,OAAO,UAAU,KAAK,SAAS;QAAE,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;IAEpE,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;IAE1C,wEAAwE;IACxE,6EAA6E;IAC7E,+EAA+E;IAC/E,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,IAAI,GAAG,CAAC,qBAAqB,CAAC;IAClE,MAAM,QAAQ,CAAC;QACb,MAAM;QACN,OAAO,EAAE,IAAI,CAAC,QAAQ;QACtB,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,GAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE;QACrC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC;KACnC,CAAC,CAAC;IAEH,yEAAyE;IACzE,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO;SACzB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC;SACxB,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;IAC/C,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,CAAC,KAAK,CACV,WAAW,KAAK,CAAC,MAAM,wBAAwB;YAC7C,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YACrC,IAAI,CACP,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC;AAED,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { type DesignMap, type ResolvedDirection } from "@design-parity/core";
2
+ export interface RunConfig {
3
+ designMap?: DesignMap;
4
+ direction: ResolvedDirection;
5
+ /**
6
+ * The committed CMP capability flag (Principle 6), read verbatim from
7
+ * `.design-parity.json` — *not* re-derived here (Principle 1). `false` lets
8
+ * the run promote CMP in the PR comment; `true`/omitted stays silent. See
9
+ * {@link ParityConfig.cmpCapable}.
10
+ */
11
+ cmpCapable?: boolean;
12
+ warnings: string[];
13
+ }
14
+ /**
15
+ * Read `design-map.json` and `.design-parity.json` from `repoRoot`.
16
+ *
17
+ * A concrete `direction` is used verbatim. `auto` means setup never ran to
18
+ * materialize it (Principle 5), so we fall back to `code-led` (advisory) and
19
+ * warn — the steady-state Action never re-derives direction from a maturity
20
+ * scan; that's setup's job.
21
+ */
22
+ export declare function resolveRunConfig(repoRoot: string): Promise<RunConfig>;
23
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAQA,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,iBAAiB,EACvB,MAAM,qBAAqB,CAAC;AAM7B,MAAM,WAAW,SAAS;IACxB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,SAAS,EAAE,iBAAiB,CAAC;IAC7B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CA+B3E"}
package/dist/config.js ADDED
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Resolve the committed configuration a parity run reads from a repo: the
3
+ * `design-map.json` correspondence manifest and the `.design-parity.json` parity
4
+ * direction. Everything here is committed and read deterministically — no model,
5
+ * no network (Principle 1).
6
+ */
7
+ import { join } from "node:path";
8
+ import { loadDesignMap, } from "@design-parity/core";
9
+ import { loadParityConfigOrDefault, PARITY_CONFIG_FILENAME, } from "@design-parity/policy";
10
+ /**
11
+ * Read `design-map.json` and `.design-parity.json` from `repoRoot`.
12
+ *
13
+ * A concrete `direction` is used verbatim. `auto` means setup never ran to
14
+ * materialize it (Principle 5), so we fall back to `code-led` (advisory) and
15
+ * warn — the steady-state Action never re-derives direction from a maturity
16
+ * scan; that's setup's job.
17
+ */
18
+ export async function resolveRunConfig(repoRoot) {
19
+ const warnings = [];
20
+ let designMap;
21
+ try {
22
+ designMap = await loadDesignMap(join(repoRoot, "design-map.json"));
23
+ }
24
+ catch (err) {
25
+ // A missing design-map is fine (Code Connect / convention may still resolve);
26
+ // an invalid one is worth surfacing.
27
+ const message = err.message;
28
+ if (!/cannot read/.test(message))
29
+ warnings.push(message);
30
+ }
31
+ const config = await loadParityConfigOrDefault(join(repoRoot, PARITY_CONFIG_FILENAME));
32
+ let direction;
33
+ if (config.direction === "auto") {
34
+ direction = "code-led";
35
+ warnings.push(`parity direction is 'auto' (no ${PARITY_CONFIG_FILENAME} from setup); defaulting to code-led (advisory). Run the bootstrap to materialize a concrete direction.`);
36
+ }
37
+ else {
38
+ direction = config.direction;
39
+ }
40
+ const runConfig = { designMap, direction, warnings };
41
+ // Carry the committed CMP flag through verbatim (only when setup recorded it).
42
+ if (typeof config.cmpCapable === "boolean")
43
+ runConfig.cmpCapable = config.cmpCapable;
44
+ return runConfig;
45
+ }
46
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EACL,aAAa,GAGd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,yBAAyB,EACzB,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAe/B;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgB;IACrD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,IAAI,SAAgC,CAAC;IACrC,IAAI,CAAC;QACH,SAAS,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC;IACrE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,8EAA8E;QAC9E,qCAAqC;QACrC,MAAM,OAAO,GAAI,GAAa,CAAC,OAAO,CAAC;QACvC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,yBAAyB,CAC5C,IAAI,CAAC,QAAQ,EAAE,sBAAsB,CAAC,CACvC,CAAC;IACF,IAAI,SAA4B,CAAC;IACjC,IAAI,MAAM,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;QAChC,SAAS,GAAG,UAAU,CAAC;QACvB,QAAQ,CAAC,IAAI,CACX,kCAAkC,sBAAsB,yGAAyG,CAClK,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IAC/B,CAAC;IAED,MAAM,SAAS,GAAc,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;IAChE,+EAA+E;IAC/E,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,SAAS;QACxC,SAAS,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IAC3C,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Decide which components a PR touched: the `design-map.json` entries whose code
3
+ * file is among the PR's changed files. Deterministic — the Action never guesses
4
+ * components from a model (Principle 1). A PR that changes no mapped component is
5
+ * "non-UI" and gets skipped.
6
+ */
7
+ import type { DesignMap } from "@design-parity/core";
8
+ /** The file part of a code handle: `"ui/Button.kt#PrimaryButton"` → `"ui/Button.kt"`. */
9
+ export declare function filePathOf(code: string): string;
10
+ /**
11
+ * Code handles from `design-map.json` whose file was changed in this PR. Paths
12
+ * are compared after stripping a leading `./`, so either form matches.
13
+ */
14
+ export declare function componentsForChangedFiles(designMap: DesignMap | undefined, changedFiles: string[]): string[];
15
+ //# sourceMappingURL=changed-components.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changed-components.d.ts","sourceRoot":"","sources":["../../src/github/changed-components.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,yFAAyF;AACzF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG/C;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,SAAS,GAAG,SAAS,EAChC,YAAY,EAAE,MAAM,EAAE,GACrB,MAAM,EAAE,CAMV"}
@@ -0,0 +1,18 @@
1
+ /** The file part of a code handle: `"ui/Button.kt#PrimaryButton"` → `"ui/Button.kt"`. */
2
+ export function filePathOf(code) {
3
+ const hash = code.indexOf("#");
4
+ return hash === -1 ? code : code.slice(0, hash);
5
+ }
6
+ /**
7
+ * Code handles from `design-map.json` whose file was changed in this PR. Paths
8
+ * are compared after stripping a leading `./`, so either form matches.
9
+ */
10
+ export function componentsForChangedFiles(designMap, changedFiles) {
11
+ if (!designMap)
12
+ return [];
13
+ const changed = new Set(changedFiles.map((f) => f.replace(/^\.\//, "")));
14
+ return designMap.components
15
+ .filter((c) => changed.has(filePathOf(c.code).replace(/^\.\//, "")))
16
+ .map((c) => c.code);
17
+ }
18
+ //# sourceMappingURL=changed-components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changed-components.js","sourceRoot":"","sources":["../../src/github/changed-components.ts"],"names":[],"mappings":"AAQA,yFAAyF;AACzF,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/B,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AAClD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CACvC,SAAgC,EAChC,YAAsB;IAEtB,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,CAAC;IAC1B,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IACzE,OAAO,SAAS,CAAC,UAAU;SACxB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;SACnE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Map a {@link ParityReport} to a GitHub check conclusion and a process exit
3
+ * code. Blocking is owned by the parity direction (`design-led` blocks; `code-led`
4
+ * is advisory) — the surface only translates it.
5
+ */
6
+ import type { ParityReport } from "../orchestrate.js";
7
+ export type CheckConclusion = "success" | "failure" | "neutral";
8
+ /**
9
+ * - `blocked` (design-led + a failure) → `failure` (red check, exit 1).
10
+ * - any other failure/warn (advisory) → `neutral` (visible, non-blocking).
11
+ * - clean pass → `success`.
12
+ */
13
+ export declare function checkConclusion(report: ParityReport): CheckConclusion;
14
+ /** Exit code for the Action step: non-zero only when blocking. */
15
+ export declare function exitCode(report: ParityReport): number;
16
+ //# sourceMappingURL=conclusion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conclusion.d.ts","sourceRoot":"","sources":["../../src/github/conclusion.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAEhE;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,eAAe,CAIrE;AAED,kEAAkE;AAClE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAErD"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * - `blocked` (design-led + a failure) → `failure` (red check, exit 1).
3
+ * - any other failure/warn (advisory) → `neutral` (visible, non-blocking).
4
+ * - clean pass → `success`.
5
+ */
6
+ export function checkConclusion(report) {
7
+ if (report.blocked)
8
+ return "failure";
9
+ if (report.status === "pass")
10
+ return "success";
11
+ return "neutral";
12
+ }
13
+ /** Exit code for the Action step: non-zero only when blocking. */
14
+ export function exitCode(report) {
15
+ return report.blocked ? 1 : 0;
16
+ }
17
+ //# sourceMappingURL=conclusion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conclusion.js","sourceRoot":"","sources":["../../src/github/conclusion.ts"],"names":[],"mappings":"AASA;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,MAAoB;IAClD,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IACrC,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM;QAAE,OAAO,SAAS,CAAC;IAC/C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,QAAQ,CAAC,MAAoB;IAC3C,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,50 @@
1
+ export interface GitResult {
2
+ stdout: string;
3
+ stderr: string;
4
+ /** Process exit code; non-zero is expected (and handled) for some commands. */
5
+ code: number;
6
+ }
7
+ /** Runs one `git` invocation. Injectable so tests can script the sequence. */
8
+ export type GitRunner = (args: string[], opts: {
9
+ cwd: string;
10
+ }) => Promise<GitResult>;
11
+ /** Default runner: shells out to the system `git` in `cwd`. */
12
+ export declare const execGit: GitRunner;
13
+ export interface PublishOptions {
14
+ /** Directory whose current contents become the published tree. */
15
+ sourceDir: string;
16
+ /** Destination branch on the remote (force-updated / re-parented each run). */
17
+ branch: string;
18
+ /** `owner/repo`. */
19
+ repo: string;
20
+ /** Token with `contents: write`. */
21
+ token: string;
22
+ /** Commit message. */
23
+ message: string;
24
+ /** When the tree matches the branch tip, skip the push (no empty commits). */
25
+ skipIfUnchanged?: boolean;
26
+ /** Commit identity (defaults to the GitHub Actions bot). */
27
+ authorName?: string;
28
+ authorEmail?: string;
29
+ /** Remote host, e.g. `https://github.com` or a GHES server URL. */
30
+ serverUrl?: string;
31
+ /** Push-race retry budget. Default 5. */
32
+ maxAttempts?: number;
33
+ /** Injected git runner (tests); defaults to {@link execGit}. */
34
+ git?: GitRunner;
35
+ /** Backoff sleeper (tests); defaults to a real `setTimeout`. */
36
+ sleep?: (ms: number) => Promise<void>;
37
+ }
38
+ export interface PublishResult {
39
+ branch: string;
40
+ /** False when `skipIfUnchanged` short-circuited an unchanged tree. */
41
+ pushed: boolean;
42
+ /** The pushed commit SHA (absent when nothing was pushed). */
43
+ sha?: string;
44
+ }
45
+ /**
46
+ * Stage `sourceDir`'s contents and push them as a single commit on `branch`,
47
+ * re-parented on the existing tip. Retries the push on a non-fast-forward race.
48
+ */
49
+ export declare function publishBaseline(options: PublishOptions): Promise<PublishResult>;
50
+ //# sourceMappingURL=publish.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../src/github/publish.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;CACd;AAED,8EAA8E;AAC9E,MAAM,MAAM,SAAS,GAAG,CACtB,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,KAClB,OAAO,CAAC,SAAS,CAAC,CAAC;AAExB,+DAA+D;AAC/D,eAAO,MAAM,OAAO,EAAE,SAWrB,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,gEAAgE;IAChE,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,MAAM,EAAE,OAAO,CAAC;IAChB,8DAA8D;IAC9D,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAaD;;;GAGG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CA+DxB"}