@anselmdk/feature-spec-md 0.3.1 → 0.5.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 CHANGED
@@ -1,8 +1,8 @@
1
1
  # feature-spec-md
2
2
 
3
- Markdown specs for AI-assisted, testable spec driven development.
3
+ Markdown specs for AI-assisted, testable spec-driven development.
4
4
 
5
- The concept is deliberately small:
5
+ `feature-spec-md` helps you describe a product in Markdown, ask an AI to turn those specs into executable tests, and then prove which parts of the specification are covered by those tests. It is intentionally small: your specs stay as plain Markdown, your tests stay in your normal test runner, and the tool connects the two through stable spec IDs.
6
6
 
7
7
  ```txt
8
8
  model + features + stack + design
@@ -10,9 +10,44 @@ model + features + stack + design
10
10
  -> validation, coverage, screenshots, and reports
11
11
  ```
12
12
 
13
- The specs are meant to be written with an AI before implementation. The tests are meant to be written with an AI from those specs. `feature-spec-md` checks that the Markdown stays structured and that executable tests still cover the model items, rules, and scenarios the specs define.
13
+ ## What the tool does
14
14
 
15
- ## What You Write
15
+ The shortest version is: `feature-spec-md` turns Markdown specifications into a testable contract.
16
+
17
+ It gives you:
18
+
19
+ - **Spec document formats** for domain models, product features, technical stack notes, and UI/design direction.
20
+ - **Stable IDs** for model items, rules, and scenarios, so tests can reference exactly what they implement.
21
+ - **Validation** that checks frontmatter, headings, IDs, cross-document references, and test coverage expectations.
22
+ - **Coverage reporting** that shows which model items, rules, and scenarios are implemented by tests.
23
+ - **HTML reports** that are useful for reviews, CI artifacts, or published build reports.
24
+ - **Screenshot evidence** for scenarios when using the Playwright helper.
25
+ - **A library API** for projects that want to parse specs, check coverage, collect screenshots, or render reports from their own tooling.
26
+
27
+ The specs are meant to be written with an AI before implementation. The tests are meant to be written with an AI from those specs. `feature-spec-md` then checks that the Markdown stays structured and that executable tests still cover the model items, rules, and scenarios the specs define.
28
+
29
+ ## Why this exists
30
+
31
+ AI can write tests quickly, but it needs a stable source of truth. Free-form product notes are often too ambiguous, and generated tests are hard to audit later. `feature-spec-md` keeps the source of truth in readable Markdown and makes the AI preserve IDs such as `ACCOUNT-M001`, `TICKET-R001`, or `TICKET-S001` in the generated tests.
32
+
33
+ That gives humans a simple review loop:
34
+
35
+ 1. Read the Markdown spec.
36
+ 2. Read or run the generated tests.
37
+ 3. Run `feature-spec-md check` or `coverage` to see what is missing.
38
+ 4. Open the HTML report to review the implemented scenarios, rules, model items, and screenshots.
39
+
40
+ ## Demo project
41
+
42
+ A complete demo app is available in [`anselmdk/feature-spec-md-demo`](https://github.com/anselmdk/feature-spec-md-demo). It shows a small support-ticket desk built from model, feature, stack, and design specs, with unit tests, Playwright tests, generated coverage, and a published report.
43
+
44
+ Demo reports, including scenario screenshots, are available here:
45
+
46
+ <https://feature-spec-md.anselm.dk/demo/>
47
+
48
+ Use the demo repository when you want to see the expected project shape, script names, screenshot manifest flow, and report output in a real app.
49
+
50
+ ## What you write
16
51
 
17
52
  Use four ordinary Markdown document types:
18
53
 
@@ -23,9 +58,27 @@ Use four ordinary Markdown document types:
23
58
  *.design.md product, UI, and interaction direction
24
59
  ```
25
60
 
26
- Each document has frontmatter, a short `## Purpose`, and stable IDs. Tests reference those IDs in titles, tags, annotations, comments, or metadata.
61
+ Each document has frontmatter, a short `## Purpose`, and stable IDs.
62
+
63
+ ### Model specs
64
+
65
+ Model specs define the shared vocabulary that features can refer to. Use them for domain concepts, states, entities, and important business terms.
66
+
67
+ ```md
68
+ ### ACCOUNT-M001: Registered person
69
+
70
+ A person who has completed registration and can request sign-in links.
71
+ ```
72
+
73
+ ### Feature specs
74
+
75
+ Feature specs describe user-facing behavior with rules and scenarios. Rules and scenarios get stable IDs that tests can reference.
27
76
 
28
77
  ```md
78
+ ### ACCOUNT-ACCESS-R001: Sign-in links expire
79
+
80
+ Sign-in links can only be used within the configured expiry window.
81
+
29
82
  ### ACCOUNT-ACCESS-S001: Registered person signs in
30
83
 
31
84
  Given a registered person is on the sign-in page
@@ -33,13 +86,27 @@ When they request and open a valid sign-in link
33
86
  Then they are signed in
34
87
  ```
35
88
 
89
+ ### Stack specs
90
+
91
+ Stack specs document technical decisions that shape the implementation: framework, storage, test runner, deployment constraints, external services, or architecture decisions.
92
+
93
+ ### Design specs
94
+
95
+ Design specs capture product, UI, and interaction direction: layout priorities, states, accessibility expectations, empty states, or copy tone.
96
+
97
+ See [SPEC_FORMAT.md](SPEC_FORMAT.md) for the exact document format.
98
+
99
+ ## How tests connect to specs
100
+
101
+ Tests reference spec IDs in titles, tags, annotations, comments, or metadata. The tool scans test files and matches those references back to the Markdown documents.
102
+
36
103
  ```ts
37
104
  test("ACCOUNT-ACCESS-S001 registered person signs in", async ({ page }) => {
38
105
  // Covers ACCOUNT-ACCESS-R001 and ACCOUNT-M001.
39
106
  });
40
107
  ```
41
108
 
42
- See [SPEC_FORMAT.md](SPEC_FORMAT.md) for the exact document format.
109
+ This keeps the test runner independent from `feature-spec-md`. You can use Playwright, Vitest, Node test, or another runner as long as the source files contain the relevant IDs.
43
110
 
44
111
  ## Install
45
112
 
@@ -63,15 +130,17 @@ npx feature-spec-md init --kind design --dir specs
63
130
  3. Ask an AI to write executable tests from the specs, preserving the relevant `-M001`, `-R001`, and `-S001` IDs in the test source.
64
131
  4. Run `npx feature-spec-md coverage` to see which scenarios, rules, and model items have tests.
65
132
  5. Run `npx feature-spec-md report` to generate an HTML implementation report for review or CI artifacts.
133
+ 6. Use `npx feature-spec-md github-report` in GitHub Actions when the report should be linked from the job summary or published.
66
134
 
67
- The longer flow, including AI prompts and CI setup, is in [docs/spec-driven-flow.md](docs/spec-driven-flow.md).
135
+ The longer flow, including AI prompts and CI setup, is in [docs/spec-driven-flow.md](docs/spec-driven-flow.md). The demo repository also shows the flow in practice: <https://github.com/anselmdk/feature-spec-md-demo>.
68
136
 
69
- ## CLI
137
+ ## CLI tools
70
138
 
71
139
  ```bash
72
140
  npx feature-spec-md check
73
141
  npx feature-spec-md coverage --fail-on-missing
74
142
  npx feature-spec-md report --out test-results/feature-spec-report/index.html
143
+ npx feature-spec-md github-report --report-dir test-results/spec-report
75
144
  ```
76
145
 
77
146
  By default the CLI scans:
@@ -92,17 +161,85 @@ npx feature-spec-md check \
92
161
  --tests "e2e/**/*.spec.ts"
93
162
  ```
94
163
 
95
- The `check` command validates spec structure, references between documents, and test coverage. Scenario coverage is required by default when tests are scanned. Use `--require-scenario-coverage=false` while drafting. Use `--require-rule-coverage` and `--require-model-coverage` when rules and model items must also fail validation if they have no test references.
164
+ ### `init`
165
+
166
+ Creates starter Markdown files for one spec kind.
167
+
168
+ ```bash
169
+ npx feature-spec-md init --kind feature --dir specs
170
+ ```
171
+
172
+ Supported kinds are `model`, `feature`, `stack`, and `design`.
173
+
174
+ ### `check`
175
+
176
+ Validates the spec set and, by default, requires scenario coverage when tests are scanned.
177
+
178
+ ```bash
179
+ npx feature-spec-md check
180
+ ```
181
+
182
+ `check` validates spec structure, references between documents, and test coverage. Use `--require-scenario-coverage=false` while drafting. Use `--require-rule-coverage` and `--require-model-coverage` when rules and model items must also fail validation if they have no test references.
96
183
 
97
- The `coverage` command prints a terminal implementation report. Use `--fail-on-missing` when missing model item, rule, or scenario coverage should fail CI.
184
+ The demo uses stricter coverage gates for all tests:
98
185
 
99
- The `report` command writes an HTML report. It can include screenshot evidence from Playwright or another test runner by passing one or more screenshot manifest files:
186
+ ```bash
187
+ feature-spec-md check --tests "tests/**/*.ts" --require-rule-coverage --require-model-coverage
188
+ ```
189
+
190
+ ### `coverage`
191
+
192
+ Prints a terminal implementation report showing covered and missing model items, rules, and scenarios.
193
+
194
+ ```bash
195
+ npx feature-spec-md coverage --fail-on-missing
196
+ ```
197
+
198
+ Use `--fail-on-missing` when missing model item, rule, or scenario coverage should fail CI.
199
+
200
+ ### `report`
201
+
202
+ Writes an HTML report for local review, CI artifacts, or publishing.
203
+
204
+ ```bash
205
+ npx feature-spec-md report \
206
+ --tests "tests/**/*.ts" \
207
+ --out test-results/spec-report/index.html
208
+ ```
209
+
210
+ The report can include screenshot evidence from Playwright or another test runner by passing one or more screenshot manifest files:
100
211
 
101
212
  ```bash
102
213
  npx feature-spec-md report \
103
214
  --screenshots "test-results/spec-report/screenshots-*.json"
104
215
  ```
105
216
 
217
+ The demo report is published at <https://feature-spec-md.anselm.dk/demo/> and includes scenario screenshots, so it is the best place to see what the report output looks like.
218
+
219
+ ### `github-report`
220
+
221
+ Writes a GitHub Actions job summary and prepares the generated report for either artifact upload or FTP publishing.
222
+
223
+ ```bash
224
+ npx feature-spec-md github-report \
225
+ --report-dir test-results/spec-report \
226
+ --publish artifact
227
+ ```
228
+
229
+ Use `--publish ftp` when the report should be uploaded to a public report site from CI.
230
+
231
+ ```bash
232
+ npx feature-spec-md github-report \
233
+ --report-dir test-results/spec-report \
234
+ --publish ftp
235
+ ```
236
+
237
+ ## Playwright screenshot evidence
238
+
239
+ The package exports a Playwright helper from `@anselmdk/feature-spec-md/playwright`. It maps scenario step text back to the spec line, wraps the implementation in a Playwright `test.step`, captures a screenshot after the step, attaches it to the test, and writes a screenshot manifest such as `test-results/spec-report/screenshots-0.json`.
240
+
241
+ That manifest can then be passed to `feature-spec-md report` with `--screenshots "test-results/spec-report/screenshots-*.json"` so the HTML report can show scenario evidence next to the relevant spec step.
242
+
106
243
  ## GitHub Actions report publishing
107
244
 
108
245
  `feature-spec-md github-report` writes the GitHub Actions job summary and can either prepare outputs for a GitHub artifact upload or publish the generated report to FTP.
@@ -176,14 +313,27 @@ Most integrations can use the top-level document API:
176
313
  ```ts
177
314
  import {
178
315
  checkSpecDocuments,
316
+ collectSpecScreenshots,
179
317
  parseSpecDocument,
180
318
  renderHtmlReport,
181
319
  validateSpecDocument,
182
320
  } from "@anselmdk/feature-spec-md";
183
321
  ```
184
322
 
323
+ Useful exports include:
324
+
325
+ - `parseSpecDocument` and kind-specific parsers for reading Markdown specs.
326
+ - `validateSpecDocument` and `validateSpecGraph` for checking one document or a connected spec set.
327
+ - `checkSpecDocuments` for loading specs and tests, validating documents, and computing coverage in one call.
328
+ - `buildSpecCoverageSummary` and `collectSpecTestReferences` for custom coverage workflows.
329
+ - `renderHtmlReport` for generating the same report UI from your own integration.
330
+ - `collectSpecScreenshots` for loading screenshot manifest files before rendering a report.
331
+ - `writeTextFile` for small report-writing integrations.
332
+
185
333
  Feature-only helpers such as `parseFeatureSpec` and `checkFeatureSpecs` remain available for compatibility.
186
334
 
335
+ The package also exports `@anselmdk/feature-spec-md/specDocuments` and `@anselmdk/feature-spec-md/playwright` for more focused imports.
336
+
187
337
  ## Development
188
338
 
189
339
  ```bash
package/dist/cli.js CHANGED
@@ -6,6 +6,7 @@
6
6
  import { mkdir, readFile, writeFile } from "node:fs/promises";
7
7
  import path from "node:path";
8
8
  import { collectSpecScreenshots, renderHtmlReport, writeTextFile, } from "./index.js";
9
+ import { publishGithubActionDiffReport } from "./githubActionDiffReport.js";
9
10
  import { publishGithubActionReport } from "./githubActionReport.js";
10
11
  import { checkSpecDocuments } from "./specDocuments.js";
11
12
  import { buildSpecImplementationReport, formatSpecImplementationReport, } from "./testImplementationReport.js";
@@ -26,6 +27,8 @@ async function main() {
26
27
  return runCoverage(options);
27
28
  if (command === "github-report")
28
29
  return publishGithubActionReport(options);
30
+ if (command === "github-diff-report")
31
+ return publishGithubActionDiffReport(options);
29
32
  if (command === "init")
30
33
  return runInit(options);
31
34
  printHelp();
@@ -87,6 +90,7 @@ async function runReport(options) {
87
90
  coverage: result.coverage,
88
91
  screenshots,
89
92
  validationIssues: [...result.validationIssues, ...result.coverageIssues],
93
+ ...githubSourceLinkOptions(),
90
94
  }));
91
95
  console.log(`Feature spec report written to ${out}`);
92
96
  }
@@ -156,6 +160,28 @@ async function readPackageName() {
156
160
  return undefined;
157
161
  }
158
162
  }
163
+ function githubSourceLinkOptions() {
164
+ const repository = process.env.GITHUB_REPOSITORY;
165
+ const githubRef = githubRefFromEnv();
166
+ if (!repository || !githubRef)
167
+ return {};
168
+ const githubBaseUrl = `${process.env.GITHUB_SERVER_URL ?? "https://github.com"}/${repository}`;
169
+ return {
170
+ githubBaseUrl,
171
+ githubRef,
172
+ repositoryUrl: githubBaseUrl,
173
+ };
174
+ }
175
+ function githubRefFromEnv() {
176
+ if (process.env.GITHUB_SHA)
177
+ return process.env.GITHUB_SHA;
178
+ if (process.env.GITHUB_HEAD_REF)
179
+ return process.env.GITHUB_HEAD_REF;
180
+ if (process.env.GITHUB_REF_NAME)
181
+ return process.env.GITHUB_REF_NAME;
182
+ const ref = process.env.GITHUB_REF;
183
+ return ref?.replace(/^refs\/(heads|tags)\//, "");
184
+ }
159
185
  function printHelp() {
160
186
  console.log(`feature-spec-md
161
187
 
@@ -165,6 +191,7 @@ Usage:
165
191
  feature-spec-md coverage [--specs "specs/**/*.model.md,specs/**/*.feature.md,specs/**/*.stack.md,specs/**/*.design.md"] [--tests "tests/**/*.spec.ts"] [--fail-on-missing]
166
192
  feature-spec-md report [--specs "specs/**/*.model.md,specs/**/*.feature.md,specs/**/*.stack.md,specs/**/*.design.md"] [--tests "tests/**/*.spec.ts"] [--screenshots "test-results/spec-report/screenshots.json"] [--out test-results/feature-spec-report/index.html]
167
193
  feature-spec-md github-report [--report-dir test-results/spec-report] [--publish artifact|ftp]
194
+ feature-spec-md github-diff-report --publish ftp --pr-number 123
168
195
 
169
196
  Options:
170
197
  --require-model-coverage Fail when model items have no matching test references.
@@ -182,6 +209,8 @@ GitHub report publishing:
182
209
  --ftp-password FTP password, or FEATURE_SPEC_FTP_PASSWORD.
183
210
  --ftp-remote-dir FTP root directory for reports, or FEATURE_SPEC_FTP_REMOTE_DIR.
184
211
  --base-url Public base URL, or FEATURE_SPEC_REPORT_BASE_URL.
212
+ --build-number Numeric build number, or FEATURE_SPEC_BUILD_NUMBER / GITHUB_RUN_NUMBER.
213
+ --pr-number Numeric PR number, or FEATURE_SPEC_PR_NUMBER. Required for github-diff-report.
185
214
  `);
186
215
  }
187
216
  function fileNameForKind(kind) {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { type GithubActionOptions } from "./githubActionFtp.js";
2
+ export type GithubActionDiffReportOptions = GithubActionOptions;
3
+ export declare function publishGithubActionDiffReport(options: GithubActionDiffReportOptions): Promise<void>;
4
+ //# sourceMappingURL=githubActionDiffReport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"githubActionDiffReport.d.ts","sourceRoot":"","sources":["../src/githubActionDiffReport.ts"],"names":[],"mappings":"AAKA,OAAO,EAQL,KAAK,mBAAmB,EACzB,MAAM,sBAAsB,CAAC;AAG9B,MAAM,MAAM,6BAA6B,GAAG,mBAAmB,CAAC;AAqBhE,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,6BAA6B,iBA4DvC"}
@@ -0,0 +1,209 @@
1
+ import { createHash } from "node:crypto";
2
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
3
+ import { basename, join, relative } from "node:path";
4
+ import { tmpdir } from "node:os";
5
+ import { html } from "./html.js";
6
+ import { downloadRemoteFile, ftpConfig, listBuildNumbers, listRemoteFilesRecursive, pathJoin, publicUrl, uploadDirectory, } from "./githubActionFtp.js";
7
+ import { writeGithubOutput, writeGithubSummary } from "./githubActionOutput.js";
8
+ export async function publishGithubActionDiffReport(options) {
9
+ const config = ftpConfig(options);
10
+ const prNumber = config.prNumber;
11
+ if (!prNumber) {
12
+ throw new Error("Missing required option --pr-number or FEATURE_SPEC_PR_NUMBER.");
13
+ }
14
+ const buildsRoot = pathJoin(config.remoteDir, "build");
15
+ const builds = await listBuildNumbers(buildsRoot, config);
16
+ const currentBuild = config.buildNumber;
17
+ const previousBuild = previousBuildNumber(builds, currentBuild);
18
+ const currentBuildUrl = publicUrl(config.baseUrl, "build", currentBuild, "");
19
+ const previousBuildUrl = previousBuild
20
+ ? publicUrl(config.baseUrl, "build", previousBuild, "")
21
+ : undefined;
22
+ const report = previousBuild
23
+ ? await compareBuilds(config, previousBuild, currentBuild, prNumber)
24
+ : {
25
+ prNumber,
26
+ currentBuild,
27
+ currentBuildUrl,
28
+ files: [],
29
+ };
30
+ if (previousBuild) {
31
+ report.previousBuild = previousBuild;
32
+ report.previousBuildUrl = previousBuildUrl;
33
+ }
34
+ const localReportDir = join(tmpdir(), `feature-spec-md-pr-diff-${process.pid}-${prNumber}-${currentBuild}`);
35
+ await mkdir(localReportDir, { recursive: true });
36
+ await writeFile(join(localReportDir, "index.html"), renderDiffReport(report), "utf8");
37
+ const remoteReportDir = pathJoin(config.remoteDir, "pr", prNumber, currentBuild);
38
+ await uploadDirectory(localReportDir, remoteReportDir, config);
39
+ const reportUrl = publicUrl(config.baseUrl, "pr", prNumber, currentBuild, "");
40
+ await writeGithubSummary([
41
+ "## Feature Spec PR Diff",
42
+ "",
43
+ `<p><strong>Diff report:</strong> <a href=\"${html(reportUrl)}\">PR #${html(prNumber)} build ${html(currentBuild)}</a></p>`,
44
+ report.previousBuild
45
+ ? `<p>Compared build <strong>${html(report.previousBuild)}</strong> with build <strong>${html(currentBuild)}</strong>.</p>`
46
+ : `<p>No earlier build was found, so this report establishes the first comparison baseline.</p>`,
47
+ "",
48
+ ].join("\n"));
49
+ await writeGithubOutput({
50
+ "diff-report-url": reportUrl,
51
+ "diff-comment-body": commentBody(report, reportUrl),
52
+ "previous-build": report.previousBuild ?? "",
53
+ "current-build": currentBuild,
54
+ });
55
+ console.log(`Feature spec PR diff report uploaded to ${reportUrl}`);
56
+ }
57
+ async function compareBuilds(config, previousBuild, currentBuild, prNumber) {
58
+ const previousRoot = pathJoin(config.remoteDir, "build", previousBuild);
59
+ const currentRoot = pathJoin(config.remoteDir, "build", currentBuild);
60
+ const previousFiles = await listRemoteFilesRecursive(previousRoot, config);
61
+ const currentFiles = await listRemoteFilesRecursive(currentRoot, config);
62
+ const previousRelative = new Set(previousFiles.map((file) => relativeRemotePath(previousRoot, file)));
63
+ const currentRelative = new Set(currentFiles.map((file) => relativeRemotePath(currentRoot, file)));
64
+ const allPaths = Array.from(new Set([...previousRelative, ...currentRelative])).sort();
65
+ const localRoot = join(tmpdir(), `feature-spec-md-build-compare-${process.pid}-${previousBuild}-${currentBuild}`);
66
+ const files = [];
67
+ for (const filePath of allPaths) {
68
+ const previousRemote = previousRelative.has(filePath)
69
+ ? pathJoin(previousRoot, filePath)
70
+ : undefined;
71
+ const currentRemote = currentRelative.has(filePath)
72
+ ? pathJoin(currentRoot, filePath)
73
+ : undefined;
74
+ const previousLocal = previousRemote
75
+ ? join(localRoot, "previous", filePath)
76
+ : undefined;
77
+ const currentLocal = currentRemote ? join(localRoot, "current", filePath) : undefined;
78
+ if (previousRemote && previousLocal) {
79
+ await downloadRemoteFile(previousRemote, previousLocal, config);
80
+ }
81
+ if (currentRemote && currentLocal) {
82
+ await downloadRemoteFile(currentRemote, currentLocal, config);
83
+ }
84
+ const previousInfo = previousLocal ? await fileInfo(previousLocal) : undefined;
85
+ const currentInfo = currentLocal ? await fileInfo(currentLocal) : undefined;
86
+ const status = !previousInfo
87
+ ? "added"
88
+ : !currentInfo
89
+ ? "removed"
90
+ : previousInfo.hash === currentInfo.hash
91
+ ? "unchanged"
92
+ : "changed";
93
+ files.push({
94
+ path: filePath,
95
+ kind: fileKind(filePath),
96
+ status,
97
+ previousHash: previousInfo?.hash,
98
+ currentHash: currentInfo?.hash,
99
+ previousSize: previousInfo?.size,
100
+ currentSize: currentInfo?.size,
101
+ });
102
+ }
103
+ return {
104
+ prNumber,
105
+ previousBuild,
106
+ currentBuild,
107
+ previousBuildUrl: publicUrl(config.baseUrl, "build", previousBuild, ""),
108
+ currentBuildUrl: publicUrl(config.baseUrl, "build", currentBuild, ""),
109
+ files,
110
+ };
111
+ }
112
+ function previousBuildNumber(builds, currentBuild) {
113
+ const current = Number(currentBuild);
114
+ return builds
115
+ .map(Number)
116
+ .filter((build) => Number.isFinite(build) && build < current)
117
+ .sort((a, b) => b - a)
118
+ .at(0)
119
+ ?.toString();
120
+ }
121
+ async function fileInfo(filePath) {
122
+ const buffer = await readFile(filePath);
123
+ return {
124
+ hash: createHash("sha256").update(buffer).digest("hex"),
125
+ size: buffer.byteLength,
126
+ };
127
+ }
128
+ function relativeRemotePath(root, filePath) {
129
+ return relative(root, filePath).split("\\").join("/");
130
+ }
131
+ function fileKind(filePath) {
132
+ const name = basename(filePath).toLowerCase();
133
+ if (name === "index.html" || name.endsWith(".html") || name.endsWith(".json")) {
134
+ return "report";
135
+ }
136
+ if (/\.(png|jpe?g|webp|gif)$/i.test(name))
137
+ return "screenshot";
138
+ return "asset";
139
+ }
140
+ function renderDiffReport(report) {
141
+ const changed = report.files.filter((file) => file.status !== "unchanged");
142
+ const byKind = (kind) => changed.filter((file) => file.kind === kind);
143
+ const sections = [
144
+ renderFileSection("Report output", byKind("report")),
145
+ renderFileSection("Screenshots", byKind("screenshot")),
146
+ renderFileSection("Other assets", byKind("asset")),
147
+ ].join("\n");
148
+ return `<!doctype html>
149
+ <html lang="en">
150
+ <head>
151
+ <meta charset="utf-8">
152
+ <meta name="viewport" content="width=device-width,initial-scale=1">
153
+ <title>Feature spec PR diff</title>
154
+ <style>
155
+ body{font-family:system-ui,sans-serif;max-width:1180px;margin:0 auto;padding:40px 24px;color:#1f2328}
156
+ .panel{border:1px solid #d0d7de;border-radius:8px;padding:20px;margin:18px 0}
157
+ .badge{border:1px solid #d0d7de;border-radius:999px;padding:2px 8px;font-size:12px;white-space:nowrap}
158
+ .added{color:#1a7f37}.removed{color:#cf222e}.changed{color:#9a6700}.muted{color:#57606a}
159
+ table{border-collapse:collapse;width:100%;font-size:14px} th,td{border:1px solid #d0d7de;padding:6px 8px;text-align:left;vertical-align:top} th{background:#f6f8fa}
160
+ a{color:#0969da}
161
+ </style>
162
+ </head>
163
+ <body>
164
+ <h1>Feature spec PR diff for PR #${html(report.prNumber)}</h1>
165
+ <p>Generated ${html(new Date().toISOString())}.</p>
166
+ <section class="panel">
167
+ <h2>Compared builds</h2>
168
+ <p>${report.previousBuild ? `Previous: <a href="${html(report.previousBuildUrl ?? "")}">build ${html(report.previousBuild)}</a>` : "No previous build found."}</p>
169
+ <p>Current: <a href="${html(report.currentBuildUrl)}">build ${html(report.currentBuild)}</a></p>
170
+ <p><span class="badge">${changed.length} changed file${changed.length === 1 ? "" : "s"}</span> <span class="muted">${report.files.length} file${report.files.length === 1 ? "" : "s"} checked</span></p>
171
+ </section>
172
+ ${sections}
173
+ </body>
174
+ </html>`;
175
+ }
176
+ function renderFileSection(title, files) {
177
+ if (!files.length) {
178
+ return `<section class="panel"><h2>${html(title)}</h2><p class="muted">No changes.</p></section>`;
179
+ }
180
+ return `<section class="panel"><h2>${html(title)}</h2><table><thead><tr><th>Status</th><th>File</th><th>Size change</th></tr></thead><tbody>${files
181
+ .map((file) => `<tr><td class="${file.status}">${html(file.status)}</td><td><code>${html(file.path)}</code></td><td>${html(sizeChange(file))}</td></tr>`)
182
+ .join("")}</tbody></table></section>`;
183
+ }
184
+ function sizeChange(file) {
185
+ if (file.previousSize === undefined)
186
+ return `+${file.currentSize ?? 0} bytes`;
187
+ if (file.currentSize === undefined)
188
+ return `-${file.previousSize} bytes`;
189
+ const diff = file.currentSize - file.previousSize;
190
+ if (diff === 0)
191
+ return "same size";
192
+ return `${diff > 0 ? "+" : ""}${diff} bytes`;
193
+ }
194
+ function commentBody(report, reportUrl) {
195
+ const changed = report.files.filter((file) => file.status !== "unchanged");
196
+ const reportChanges = changed.filter((file) => file.kind === "report").length;
197
+ const screenshotChanges = changed.filter((file) => file.kind === "screenshot").length;
198
+ const previous = report.previousBuild
199
+ ? `build ${report.previousBuild} → build ${report.currentBuild}`
200
+ : `build ${report.currentBuild}`;
201
+ return [
202
+ "## Feature spec PR diff",
203
+ "",
204
+ `[Open the diff report](${reportUrl}) for ${previous}.`,
205
+ "",
206
+ `Changed files: **${changed.length}** total, **${reportChanges}** report output, **${screenshotChanges}** screenshots.`,
207
+ ].join("\n");
208
+ }
209
+ //# sourceMappingURL=githubActionDiffReport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"githubActionDiffReport.js","sourceRoot":"","sources":["../src/githubActionDiffReport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,kBAAkB,EAClB,SAAS,EACT,gBAAgB,EAChB,wBAAwB,EACxB,QAAQ,EACR,SAAS,EACT,eAAe,GAEhB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAuBhF,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,OAAsC;IAEtC,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IACjC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;IACpF,CAAC;IAED,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC1D,MAAM,YAAY,GAAG,MAAM,CAAC,WAAW,CAAC;IACxC,MAAM,aAAa,GAAG,mBAAmB,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAChE,MAAM,eAAe,GAAG,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,CAAC,CAAC;IAC7E,MAAM,gBAAgB,GAAG,aAAa;QACpC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,CAAC;QACvD,CAAC,CAAC,SAAS,CAAC;IAEd,MAAM,MAAM,GAAe,aAAa;QACtC,CAAC,CAAC,MAAM,aAAa,CAAC,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,QAAQ,CAAC;QACpE,CAAC,CAAC;YACE,QAAQ;YACR,YAAY;YACZ,eAAe;YACf,KAAK,EAAE,EAAE;SACV,CAAC;IAEN,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,CAAC,aAAa,GAAG,aAAa,CAAC;QACrC,MAAM,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;IAC7C,CAAC;IAED,MAAM,cAAc,GAAG,IAAI,CACzB,MAAM,EAAE,EACR,2BAA2B,OAAO,CAAC,GAAG,IAAI,QAAQ,IAAI,YAAY,EAAE,CACrE,CAAC;IACF,MAAM,KAAK,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,MAAM,SAAS,CAAC,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;IAEtF,MAAM,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;IACjF,MAAM,eAAe,CAAC,cAAc,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC;IAE/D,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,CAAC,CAAC;IAC9E,MAAM,kBAAkB,CACtB;QACE,yBAAyB;QACzB,EAAE;QACF,8CAA8C,IAAI,CAAC,SAAS,CAAC,UAAU,IAAI,CAAC,QAAQ,CAAC,UAAU,IAAI,CAAC,YAAY,CAAC,UAAU;QAC3H,MAAM,CAAC,aAAa;YAClB,CAAC,CAAC,6BAA6B,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,gCAAgC,IAAI,CAAC,YAAY,CAAC,gBAAgB;YAC3H,CAAC,CAAC,8FAA8F;QAClG,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IACF,MAAM,iBAAiB,CAAC;QACtB,iBAAiB,EAAE,SAAS;QAC5B,mBAAmB,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC;QACnD,gBAAgB,EAAE,MAAM,CAAC,aAAa,IAAI,EAAE;QAC5C,eAAe,EAAE,YAAY;KAC9B,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,2CAA2C,SAAS,EAAE,CAAC,CAAC;AACtE,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,MAAoC,EACpC,aAAqB,EACrB,YAAoB,EACpB,QAAgB;IAEhB,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;IACxE,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;IACtE,MAAM,aAAa,GAAG,MAAM,wBAAwB,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC3E,MAAM,YAAY,GAAG,MAAM,wBAAwB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACzE,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAC9B,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,kBAAkB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CACpE,CAAC;IACF,MAAM,eAAe,GAAG,IAAI,GAAG,CAC7B,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,kBAAkB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAClE,CAAC;IACF,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,gBAAgB,EAAE,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAEvF,MAAM,SAAS,GAAG,IAAI,CACpB,MAAM,EAAE,EACR,iCAAiC,OAAO,CAAC,GAAG,IAAI,aAAa,IAAI,YAAY,EAAE,CAChF,CAAC;IACF,MAAM,KAAK,GAAmB,EAAE,CAAC;IAEjC,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;QAChC,MAAM,cAAc,GAAG,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC;YACnD,CAAC,CAAC,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC;YAClC,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,aAAa,GAAG,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC;YACjD,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC;YACjC,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,aAAa,GAAG,cAAc;YAClC,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,QAAQ,CAAC;YACvC,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,YAAY,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAEtF,IAAI,cAAc,IAAI,aAAa,EAAE,CAAC;YACpC,MAAM,kBAAkB,CAAC,cAAc,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;QAClE,CAAC;QACD,IAAI,aAAa,IAAI,YAAY,EAAE,CAAC;YAClC,MAAM,kBAAkB,CAAC,aAAa,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,YAAY,GAAG,aAAa,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC/E,MAAM,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC5E,MAAM,MAAM,GAAG,CAAC,YAAY;YAC1B,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,CAAC,WAAW;gBACZ,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,YAAY,CAAC,IAAI,KAAK,WAAW,CAAC,IAAI;oBACtC,CAAC,CAAC,WAAW;oBACb,CAAC,CAAC,SAAS,CAAC;QAElB,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC;YACxB,MAAM;YACN,YAAY,EAAE,YAAY,EAAE,IAAI;YAChC,WAAW,EAAE,WAAW,EAAE,IAAI;YAC9B,YAAY,EAAE,YAAY,EAAE,IAAI;YAChC,WAAW,EAAE,WAAW,EAAE,IAAI;SAC/B,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,QAAQ;QACR,aAAa;QACb,YAAY;QACZ,gBAAgB,EAAE,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,CAAC;QACvE,eAAe,EAAE,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,CAAC;QACrE,KAAK;KACN,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,MAAgB,EAAE,YAAoB;IACjE,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;IACrC,OAAO,MAAM;SACV,GAAG,CAAC,MAAM,CAAC;SACX,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,OAAO,CAAC;SAC5D,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;SACrB,EAAE,CAAC,CAAC,CAAC;QACN,EAAE,QAAQ,EAAE,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,QAAgB;IACtC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACxC,OAAO;QACL,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QACvD,IAAI,EAAE,MAAM,CAAC,UAAU;KACxB,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAY,EAAE,QAAgB;IACxD,OAAO,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,QAAQ,CAAC,QAAgB;IAChC,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IAC9C,IAAI,IAAI,KAAK,YAAY,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9E,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,IAAI,0BAA0B,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,YAAY,CAAC;IAC/D,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAkB;IAC1C,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC;IAC3E,MAAM,MAAM,GAAG,CAAC,IAA0B,EAAE,EAAE,CAC5C,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG;QACf,iBAAiB,CAAC,eAAe,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACpD,iBAAiB,CAAC,aAAa,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;QACtD,iBAAiB,CAAC,cAAc,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;KACnD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,OAAO;;;;;;;;;;;;;;;;uCAgB8B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;mBACzC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;;;WAGtC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,sBAAsB,IAAI,CAAC,MAAM,CAAC,gBAAgB,IAAI,EAAE,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,0BAA0B;6BACtI,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;+BAC9D,OAAO,CAAC,MAAM,gBAAgB,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,+BAA+B,MAAM,CAAC,KAAK,CAAC,MAAM,QAAQ,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG;;MAEpL,QAAQ;;QAEN,CAAC;AACT,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAa,EAAE,KAAqB;IAC7D,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,8BAA8B,IAAI,CAAC,KAAK,CAAC,iDAAiD,CAAC;IACpG,CAAC;IAED,OAAO,8BAA8B,IAAI,CAAC,KAAK,CAAC,8FAA8F,KAAK;SAChJ,GAAG,CACF,CAAC,IAAI,EAAE,EAAE,CACP,kBAAkB,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,kBAAkB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,YAAY,CAC5I;SACA,IAAI,CAAC,EAAE,CAAC,4BAA4B,CAAC;AAC1C,CAAC;AAED,SAAS,UAAU,CAAC,IAAkB;IACpC,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS;QAAE,OAAO,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC,QAAQ,CAAC;IAC9E,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS;QAAE,OAAO,IAAI,IAAI,CAAC,YAAY,QAAQ,CAAC;IACzE,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC;IAClD,IAAI,IAAI,KAAK,CAAC;QAAE,OAAO,WAAW,CAAC;IACnC,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,QAAQ,CAAC;AAC/C,CAAC;AAED,SAAS,WAAW,CAAC,MAAkB,EAAE,SAAiB;IACxD,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC;IAC3E,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;IAC9E,MAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,MAAM,CAAC;IACtF,MAAM,QAAQ,GAAG,MAAM,CAAC,aAAa;QACnC,CAAC,CAAC,SAAS,MAAM,CAAC,aAAa,YAAY,MAAM,CAAC,YAAY,EAAE;QAChE,CAAC,CAAC,SAAS,MAAM,CAAC,YAAY,EAAE,CAAC;IAEnC,OAAO;QACL,yBAAyB;QACzB,EAAE;QACF,0BAA0B,SAAS,SAAS,QAAQ,GAAG;QACvD,EAAE;QACF,oBAAoB,OAAO,CAAC,MAAM,eAAe,aAAa,uBAAuB,iBAAiB,iBAAiB;KACxH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,25 @@
1
+ export type GithubActionOptions = Record<string, string | undefined>;
2
+ export type FtpConfig = {
3
+ host: string;
4
+ user: string;
5
+ password: string;
6
+ port?: string;
7
+ secure: boolean;
8
+ remoteDir: string;
9
+ baseUrl: string;
10
+ buildNumber: string;
11
+ prNumber?: string;
12
+ };
13
+ export declare function ftpConfig(options: GithubActionOptions): FtpConfig;
14
+ export declare function uploadDirectory(localDir: string, remoteDir: string, config: FtpConfig): Promise<void>;
15
+ export declare function uploadFile(localFile: string, remotePath: string, config: FtpConfig): Promise<void>;
16
+ export declare function downloadRemoteFile(remotePath: string, localFile: string, config: FtpConfig): Promise<void>;
17
+ export declare function listRemoteDirectory(remoteDir: string, config: FtpConfig): Promise<string>;
18
+ export declare function listRemoteFilesRecursive(remoteDir: string, config: FtpConfig): Promise<string[]>;
19
+ export declare function parseBuildNumbersFromDirectoryListing(listing: string): string[];
20
+ export declare function listBuildNumbers(remoteDir: string, config: FtpConfig): Promise<string[]>;
21
+ export declare function pathJoin(...parts: string[]): string;
22
+ export declare function publicUrl(baseUrl: string, ...parts: string[]): string;
23
+ export declare function trimTrailingSlash(value: string): string;
24
+ export declare function runCurl(args: string[]): Promise<string>;
25
+ //# sourceMappingURL=githubActionFtp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"githubActionFtp.d.ts","sourceRoot":"","sources":["../src/githubActionFtp.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAErE,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAgB,SAAS,CAAC,OAAO,EAAE,mBAAmB,GAAG,SAAS,CA0BjE;AAED,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,SAAS,iBAclB;AAED,wBAAsB,UAAU,CAC9B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,SAAS,iBAalB;AAED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,SAAS,iBAalB;AAED,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,mBAe7E;AAED,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,SAAS,qBAuBlB;AAED,wBAAgB,qCAAqC,CAAC,OAAO,EAAE,MAAM,YAapE;AAED,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,qBAO1E;AAED,wBAAgB,QAAQ,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,UAO1C;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,UAO5D;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,UAE9C;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,mBAoB3C"}