figdiff 0.1.0-alpha.0 → 0.1.0-alpha.1
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 +67 -19
- package/dist/action/changed-files.d.ts +14 -0
- package/dist/action/changed-files.js +35 -0
- package/dist/action/changed-files.js.map +1 -0
- package/dist/action/comment.d.ts +28 -0
- package/dist/action/comment.js +70 -0
- package/dist/action/comment.js.map +1 -0
- package/dist/action/github.d.ts +15 -0
- package/dist/action/github.js +62 -0
- package/dist/action/github.js.map +1 -0
- package/dist/action/glob.d.ts +10 -0
- package/dist/action/glob.js +45 -0
- package/dist/action/glob.js.map +1 -0
- package/dist/action/main.d.ts +20 -0
- package/dist/action/main.js +111 -0
- package/dist/action/main.js.map +1 -0
- package/dist/action.d.ts +2 -0
- package/dist/action.js +7 -0
- package/dist/action.js.map +1 -0
- package/dist/cli.js +16 -2
- package/dist/cli.js.map +1 -1
- package/dist/git.d.ts +12 -0
- package/dist/git.js +32 -0
- package/dist/git.js.map +1 -0
- package/dist/html.d.ts +25 -0
- package/dist/html.js +205 -0
- package/dist/html.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/render/compare.d.ts +19 -0
- package/dist/render/compare.js +61 -0
- package/dist/render/compare.js.map +1 -0
- package/dist/render/figcraft-cli.d.ts +21 -0
- package/dist/render/figcraft-cli.js +63 -0
- package/dist/render/figcraft-cli.js.map +1 -0
- package/dist/render/frames.d.ts +19 -0
- package/dist/render/frames.js +53 -0
- package/dist/render/frames.js.map +1 -0
- package/dist/render/png.d.ts +14 -0
- package/dist/render/png.js +185 -0
- package/dist/render/png.js.map +1 -0
- package/dist/run.d.ts +18 -3
- package/dist/run.js +117 -17
- package/dist/run.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
`figdiff` compares two versions of a [FigCraft](https://github.com/storytold/figcraft) design file (`.figcraft`) and explains what changed, both as a readable list of changes and as before/after images.
|
|
6
6
|
|
|
7
|
-
> **Status: early development (pre-alpha).** Phase 0 is in progress. The parser and a basic text diff exist
|
|
7
|
+
> **Status: early development (pre-alpha).** Phase 0 is in progress. The parser and a basic text diff exist and are published as a pre-alpha on npm (see [Try it](#try-it)); the HTML report, visual diff and GitHub Action are still planned. Commands in the usage section below are the intended interface and may change. Feedback is very welcome: please open an issue.
|
|
8
8
|
|
|
9
9
|
> **Not affiliated.** figdiff is an independent community project. It is not made by, endorsed by, or connected to the FigCraft / ArtCraft authors. FigCraft is a trademark of its respective owners.
|
|
10
10
|
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
## Table of contents
|
|
14
14
|
|
|
15
|
+
- [Try it](#try-it)
|
|
15
16
|
- [The problem](#the-problem)
|
|
16
17
|
- [The idea](#the-idea)
|
|
17
18
|
- [Planned usage](#planned-usage)
|
|
@@ -24,6 +25,20 @@
|
|
|
24
25
|
|
|
25
26
|
---
|
|
26
27
|
|
|
28
|
+
## Try it
|
|
29
|
+
|
|
30
|
+
The first pre-alpha is on npm under the `alpha` tag. It needs Node.js 20 or newer.
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
npx figdiff@alpha before.figcraft after.figcraft
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
To install it globally instead: `npm install -g figdiff@alpha`.
|
|
37
|
+
|
|
38
|
+
Today it compares two files and prints a grouped list of changes (`--json` and `--exit-code` are available). The HTML report, visual diff and GitHub Action are on the roadmap below. Matching of nodes relies on ids staying stable between saves in FigCraft, which is not yet verified, so treat results as preliminary.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
27
42
|
## The problem
|
|
28
43
|
|
|
29
44
|
A `.figcraft` file is a zip archive. When it changes in a Git repository, GitHub and `git diff` can only say "binary file changed". A reviewer has no way to tell whether a designer moved one button or rebuilt a whole screen, short of opening the file in FigCraft and comparing by eye.
|
|
@@ -61,7 +76,7 @@ Page "App"
|
|
|
61
76
|
4 changes in 2 frames (1 removed, 3 property changes)
|
|
62
77
|
```
|
|
63
78
|
|
|
64
|
-
Useful flags: `--json` prints the summary and every change as JSON, and `--exit-code` exits with 1 when the files differ, so it can fail a CI step.
|
|
79
|
+
Useful flags: `--html report.html` also writes a self-contained HTML report (add `--images` for rendered before/after images), `--json` prints the summary and every change as JSON, and `--exit-code` exits with 1 when the files differ, so it can fail a CI step.
|
|
65
80
|
|
|
66
81
|
**Generate a shareable report**
|
|
67
82
|
|
|
@@ -69,7 +84,7 @@ Useful flags: `--json` prints the summary and every change as JSON, and `--exit-
|
|
|
69
84
|
npx figdiff before.figcraft after.figcraft --html report.html
|
|
70
85
|
```
|
|
71
86
|
|
|
72
|
-
One self-contained HTML file with
|
|
87
|
+
One self-contained HTML file with the list of changes, filters, and light and dark mode. No server needed, so it can be sent by email or chat to a developer or client. With `--images` (and FigCraft's `figcraft-cli` installed) it also embeds before/after images with a swipe slider and a difference view. This part is experimental: it has been tested with a stand-in for `figcraft-cli` but not yet with the real one.
|
|
73
88
|
|
|
74
89
|
**Compare against another Git branch**
|
|
75
90
|
|
|
@@ -77,25 +92,54 @@ One self-contained HTML file with before/after images, a slider, and the list of
|
|
|
77
92
|
npx figdiff design/app.figcraft --against main
|
|
78
93
|
```
|
|
79
94
|
|
|
95
|
+
`--against` accepts any git revision (a branch, tag, or commit such as `HEAD~1`). The file is compared with its committed version, so it also works for uncommitted edits: `--against HEAD` shows what you changed since the last commit.
|
|
96
|
+
|
|
97
|
+
**Use it as a `git difftool`**
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
git config difftool.figdiff.cmd 'figdiff "$LOCAL" "$REMOTE"'
|
|
101
|
+
git difftool -y -t figdiff main -- design/app.figcraft
|
|
102
|
+
```
|
|
103
|
+
|
|
80
104
|
**Run on every pull request**
|
|
81
105
|
|
|
106
|
+
The GitHub Action (`action.yml`, currently in alpha) posts one comment per pull request with what changed in each `.figcraft` file, and keeps that comment up to date on every push. Full HTML reports are attached to the workflow run.
|
|
107
|
+
|
|
82
108
|
```yaml
|
|
83
|
-
# .github/workflows/
|
|
84
|
-
name: Design
|
|
85
|
-
on:
|
|
109
|
+
# .github/workflows/figdiff.yml (also in examples/figdiff.yml)
|
|
110
|
+
name: Design changes
|
|
111
|
+
on:
|
|
112
|
+
pull_request:
|
|
113
|
+
paths: ["**/*.figcraft"]
|
|
114
|
+
|
|
115
|
+
permissions:
|
|
116
|
+
contents: read
|
|
117
|
+
pull-requests: write
|
|
86
118
|
|
|
87
119
|
jobs:
|
|
88
|
-
|
|
120
|
+
figdiff:
|
|
89
121
|
runs-on: ubuntu-latest
|
|
90
122
|
steps:
|
|
91
123
|
- uses: actions/checkout@v4
|
|
92
124
|
with:
|
|
93
|
-
fetch-depth: 0
|
|
94
|
-
- uses: bintangyoga/figdiff@
|
|
125
|
+
fetch-depth: 0 # needed to read the base commit
|
|
126
|
+
- uses: bintangyoga/figdiff@main
|
|
95
127
|
with:
|
|
96
128
|
files: "design/**/*.figcraft"
|
|
97
129
|
```
|
|
98
130
|
|
|
131
|
+
| Input | Default | Meaning |
|
|
132
|
+
| --- | --- | --- |
|
|
133
|
+
| `files` | `**/*.figcraft` | Glob patterns (commas or new lines) of the design files to look at |
|
|
134
|
+
| `comment` | `true` | `false` writes the reports without commenting |
|
|
135
|
+
| `max-files` | `20` | Compare at most this many files per pull request |
|
|
136
|
+
| `upload-reports` | `true` | Upload the HTML reports as the artifact `figdiff-reports` |
|
|
137
|
+
| `report-dir` | `figdiff-reports` | Where the reports are written |
|
|
138
|
+
| `version` | `latest` | Version of the `figdiff` npm package to use |
|
|
139
|
+
| `token` | `github.token` | Token used to comment |
|
|
140
|
+
|
|
141
|
+
Pull requests from forks get a read-only token, so no comment is posted; the changes are printed in the job log instead. Images in the comment are not included yet (see Phase 3).
|
|
142
|
+
|
|
99
143
|
## How it will work
|
|
100
144
|
|
|
101
145
|
```text
|
|
@@ -176,13 +220,17 @@ Deliver `figdiff a.figcraft b.figcraft` printing a correct list of changes in th
|
|
|
176
220
|
|
|
177
221
|
Deliver a self-contained HTML report that anyone can open, including designers who do not use Git.
|
|
178
222
|
|
|
179
|
-
- [
|
|
180
|
-
- [
|
|
181
|
-
- [
|
|
223
|
+
- [x] Self-contained HTML report of the semantic diff (`--html report.html`), with filters and light/dark mode
|
|
224
|
+
- [x] Before/after swipe slider and a difference view with the share of changed pixels
|
|
225
|
+
- [x] Pixel comparison with highlighted changed areas (own PNG decoder, no dependencies; checked against real FigCraft PNGs)
|
|
226
|
+
- [x] A single `report.html` with embedded images and no server
|
|
227
|
+
- [x] Graceful fallback when `figcraft-cli` is unavailable: the report is still written, with a warning
|
|
228
|
+
- [x] Frames that exist in only one version (added or removed) are shown on their own
|
|
229
|
+
- [ ] Verify rendering against a real `figcraft-cli` (implemented from its documentation and tested with a stand-in; the exact `--node` and `--page` behavior is unconfirmed)
|
|
230
|
+
- [ ] Render at 2x as well as 1x
|
|
231
|
+
- [x] Side-by-side view next to the swipe slider
|
|
182
232
|
- [ ] Semantic change list next to the images; clicking a change highlights its location
|
|
183
|
-
- [
|
|
184
|
-
- [ ] Graceful fallback when `figcraft-cli` is unavailable: semantic diff only, with a clear message
|
|
185
|
-
- [ ] `git difftool` integration and `--against <branch>` support
|
|
233
|
+
- [x] `--against <revision>` (compare a file with its version on a branch, tag or commit) and `git difftool` usage
|
|
186
234
|
|
|
187
235
|
**Release:** `v0.2.0`, with the first demo GIF in this README.
|
|
188
236
|
|
|
@@ -192,12 +240,12 @@ Deliver a self-contained HTML report that anyone can open, including designers w
|
|
|
192
240
|
|
|
193
241
|
Deliver an automatic comment on every pull request that changes a `.figcraft` file, set up with one workflow file.
|
|
194
242
|
|
|
195
|
-
- [
|
|
243
|
+
- [x] Detect changed `.figcraft` files in a pull request and compare each with its base version
|
|
196
244
|
- [ ] Install `figcraft-cli` on the runner, with caching
|
|
197
|
-
- [
|
|
245
|
+
- [x] Pull request comment with a summary and per-frame changes (before/after images still to do)
|
|
198
246
|
- [ ] Host images via workflow artifacts or a dedicated branch (GitHub comments need image URLs)
|
|
199
|
-
- [
|
|
200
|
-
- [
|
|
247
|
+
- [x] Update a single comment on each push instead of posting new ones
|
|
248
|
+
- [x] Configuration options: file patterns, file limit, report folder (render scale and comment language still to do)
|
|
201
249
|
- [ ] Public example repository that uses the Action as a live demo
|
|
202
250
|
|
|
203
251
|
**Release:** `v0.3.0` and a listing on GitHub Marketplace.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface ChangedFile {
|
|
2
|
+
status: "added" | "modified" | "deleted" | "renamed";
|
|
3
|
+
/** Path in the new version (or the old one, for a deleted file). */
|
|
4
|
+
path: string;
|
|
5
|
+
/** Path in the base version, for a renamed file. */
|
|
6
|
+
oldPath?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Parse the output of `git diff --name-status -z`. Entries are separated by NUL characters;
|
|
10
|
+
* renames and copies carry two paths.
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseNameStatus(output: string): ChangedFile[];
|
|
13
|
+
/** Keep the files that match one of the patterns (a rename matches on either of its two paths). */
|
|
14
|
+
export declare function filterByPatterns(files: ChangedFile[], patterns: string[]): ChangedFile[];
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { matchesAny } from "./glob.js";
|
|
2
|
+
/**
|
|
3
|
+
* Parse the output of `git diff --name-status -z`. Entries are separated by NUL characters;
|
|
4
|
+
* renames and copies carry two paths.
|
|
5
|
+
*/
|
|
6
|
+
export function parseNameStatus(output) {
|
|
7
|
+
const tokens = output.split("\0");
|
|
8
|
+
const files = [];
|
|
9
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
10
|
+
const code = tokens[i];
|
|
11
|
+
if (code === "")
|
|
12
|
+
continue;
|
|
13
|
+
const kind = code[0];
|
|
14
|
+
if (kind === "R") {
|
|
15
|
+
const oldPath = tokens[++i];
|
|
16
|
+
const path = tokens[++i];
|
|
17
|
+
files.push({ status: "renamed", path, oldPath });
|
|
18
|
+
}
|
|
19
|
+
else if (kind === "C") {
|
|
20
|
+
i++; // the copy source is not interesting
|
|
21
|
+
files.push({ status: "added", path: tokens[++i] });
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
const path = tokens[++i];
|
|
25
|
+
const status = kind === "A" ? "added" : kind === "D" ? "deleted" : "modified";
|
|
26
|
+
files.push({ status, path });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return files;
|
|
30
|
+
}
|
|
31
|
+
/** Keep the files that match one of the patterns (a rename matches on either of its two paths). */
|
|
32
|
+
export function filterByPatterns(files, patterns) {
|
|
33
|
+
return files.filter((f) => matchesAny(f.path, patterns) || (f.oldPath !== undefined && matchesAny(f.oldPath, patterns)));
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=changed-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changed-files.js","sourceRoot":"","sources":["../../src/action/changed-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAUvC;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAW,CAAC;QACjC,IAAI,IAAI,KAAK,EAAE;YAAE,SAAS;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACrB,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACjB,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC,CAAW,CAAC;YACtC,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,CAAW,CAAC;YACnC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QACnD,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACxB,CAAC,EAAE,CAAC,CAAC,qCAAqC;YAC1C,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC,CAAW,EAAE,CAAC,CAAC;QAC/D,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,CAAW,CAAC;YACnC,MAAM,MAAM,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC;YAC9E,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,gBAAgB,CAAC,KAAoB,EAAE,QAAkB;IACvE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,KAAK,SAAS,IAAI,UAAU,CAAC,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC3H,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Summary } from "../diff/types.js";
|
|
2
|
+
import type { ChangedFile } from "./changed-files.js";
|
|
3
|
+
/** Hidden marker used to find our own comment again on later pushes. */
|
|
4
|
+
export declare const COMMENT_MARKER = "<!-- figdiff-comment -->";
|
|
5
|
+
export interface FileResult {
|
|
6
|
+
file: ChangedFile;
|
|
7
|
+
/** Present when the two versions were compared. */
|
|
8
|
+
summary?: Summary;
|
|
9
|
+
/** The text diff, as printed by `figdiff`. */
|
|
10
|
+
text?: string;
|
|
11
|
+
/** Why the comparison could not be made. */
|
|
12
|
+
error?: string;
|
|
13
|
+
/** Name of the HTML report written for this file, if any. */
|
|
14
|
+
reportName?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface CommentContext {
|
|
17
|
+
/** Link to the workflow run, where the report artifact can be downloaded. */
|
|
18
|
+
runUrl?: string;
|
|
19
|
+
/** Whether the HTML reports were uploaded as an artifact. */
|
|
20
|
+
reportsUploaded: boolean;
|
|
21
|
+
version?: string;
|
|
22
|
+
}
|
|
23
|
+
/** A file counts as changed unless it was only re-saved without any design difference. */
|
|
24
|
+
export declare function isSubstantive(r: FileResult): boolean;
|
|
25
|
+
/** The pull request comment for a set of compared files. */
|
|
26
|
+
export declare function buildComment(results: FileResult[], ctx: CommentContext): string;
|
|
27
|
+
/** Replaces an earlier comment when a later push no longer changes any design file. */
|
|
28
|
+
export declare function buildEmptyComment(): string;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { formatSummary } from "../report.js";
|
|
2
|
+
/** Hidden marker used to find our own comment again on later pushes. */
|
|
3
|
+
export const COMMENT_MARKER = "<!-- figdiff-comment -->";
|
|
4
|
+
/** GitHub rejects comments over 65,536 characters; stay well below. */
|
|
5
|
+
const MAX_COMMENT = 60_000;
|
|
6
|
+
const MAX_FILE_TEXT = 15_000;
|
|
7
|
+
/** A file counts as changed unless it was only re-saved without any design difference. */
|
|
8
|
+
export function isSubstantive(r) {
|
|
9
|
+
if (r.error)
|
|
10
|
+
return true;
|
|
11
|
+
if (r.file.status === "added" || r.file.status === "deleted" || r.file.status === "renamed")
|
|
12
|
+
return true;
|
|
13
|
+
return (r.summary?.changes ?? 0) > 0;
|
|
14
|
+
}
|
|
15
|
+
/** Wrap text in a code span, choosing a delimiter that cannot be broken by backticks inside. */
|
|
16
|
+
function code(text) {
|
|
17
|
+
const longest = Math.max(0, ...(text.match(/`+/g) ?? []).map((m) => m.length));
|
|
18
|
+
const fence = "`".repeat(longest + 1);
|
|
19
|
+
return `${fence}${text.startsWith("`") || text.endsWith("`") ? ` ${text} ` : text}${fence}`;
|
|
20
|
+
}
|
|
21
|
+
/** A fenced code block whose fence is longer than any backtick run inside. */
|
|
22
|
+
function block(text) {
|
|
23
|
+
const longest = Math.max(2, ...(text.match(/`+/g) ?? []).map((m) => m.length));
|
|
24
|
+
const fence = "`".repeat(longest + 1);
|
|
25
|
+
return `${fence}text\n${text.replace(/\n$/, "")}\n${fence}`;
|
|
26
|
+
}
|
|
27
|
+
function truncate(text, limit) {
|
|
28
|
+
if (text.length <= limit)
|
|
29
|
+
return text;
|
|
30
|
+
const cut = text.slice(0, limit);
|
|
31
|
+
const kept = cut.slice(0, Math.max(cut.lastIndexOf("\n"), 0));
|
|
32
|
+
const hidden = text.slice(kept.length).split("\n").filter(Boolean).length;
|
|
33
|
+
return `${kept}\n… ${hidden} more lines not shown`;
|
|
34
|
+
}
|
|
35
|
+
function section(r) {
|
|
36
|
+
const { file } = r;
|
|
37
|
+
const name = code(file.path);
|
|
38
|
+
switch (file.status) {
|
|
39
|
+
case "added":
|
|
40
|
+
return `**${name}**: new design file, nothing earlier to compare with.`;
|
|
41
|
+
case "deleted":
|
|
42
|
+
return `**${name}**: design file deleted.`;
|
|
43
|
+
default:
|
|
44
|
+
}
|
|
45
|
+
const renamed = file.status === "renamed" ? ` (renamed from ${code(file.oldPath ?? "")})` : "";
|
|
46
|
+
if (r.error)
|
|
47
|
+
return `**${name}**${renamed}: could not be compared. ${r.error}`;
|
|
48
|
+
if (!r.summary || r.summary.changes === 0) {
|
|
49
|
+
return `**${name}**${renamed}: ${file.status === "renamed" ? "renamed, no design changes." : "saved again, no design changes."}`;
|
|
50
|
+
}
|
|
51
|
+
const details = r.text
|
|
52
|
+
? `\n\n<details><summary>Show changes</summary>\n\n${block(truncate(r.text, MAX_FILE_TEXT))}\n\n</details>`
|
|
53
|
+
: "";
|
|
54
|
+
return `**${name}**${renamed}: ${formatSummary(r.summary)}${details}`;
|
|
55
|
+
}
|
|
56
|
+
/** The pull request comment for a set of compared files. */
|
|
57
|
+
export function buildComment(results, ctx) {
|
|
58
|
+
const parts = [`${COMMENT_MARKER}\n## Design changes`, ...results.map(section)];
|
|
59
|
+
if (ctx.reportsUploaded && ctx.runUrl && results.some((r) => r.reportName)) {
|
|
60
|
+
parts.push(`Full HTML reports (with filters and, if enabled, images) are attached to [this workflow run](${ctx.runUrl}) as the artifact **figdiff-reports**.`);
|
|
61
|
+
}
|
|
62
|
+
parts.push(`<sub>Generated by figdiff${ctx.version ? ` ${ctx.version}` : ""}. Changes are matched by node id.</sub>`);
|
|
63
|
+
const body = parts.join("\n\n");
|
|
64
|
+
return body.length <= MAX_COMMENT ? body : `${body.slice(0, MAX_COMMENT)}\n\n… (comment shortened)`;
|
|
65
|
+
}
|
|
66
|
+
/** Replaces an earlier comment when a later push no longer changes any design file. */
|
|
67
|
+
export function buildEmptyComment() {
|
|
68
|
+
return `${COMMENT_MARKER}\n## Design changes\n\nThis pull request no longer changes any design file.`;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=comment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comment.js","sourceRoot":"","sources":["../../src/action/comment.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** An error from the GitHub API, with the HTTP status so callers can tell "no permission" apart. */
|
|
2
|
+
export declare class GitHubError extends Error {
|
|
3
|
+
readonly status: number;
|
|
4
|
+
constructor(message: string, status: number);
|
|
5
|
+
}
|
|
6
|
+
export interface GitHubApi {
|
|
7
|
+
fetch: typeof fetch;
|
|
8
|
+
/** For example https://api.github.com */
|
|
9
|
+
baseUrl: string;
|
|
10
|
+
token: string;
|
|
11
|
+
}
|
|
12
|
+
/** Find the comment figdiff wrote earlier on this pull request, if any. */
|
|
13
|
+
export declare function findComment(api: GitHubApi, repo: string, pr: number): Promise<number | undefined>;
|
|
14
|
+
/** Create the comment, or update the one found earlier so a pull request only ever has one. */
|
|
15
|
+
export declare function upsertComment(api: GitHubApi, repo: string, pr: number, body: string, existing?: number): Promise<"created" | "updated">;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { COMMENT_MARKER } from "./comment.js";
|
|
2
|
+
/** An error from the GitHub API, with the HTTP status so callers can tell "no permission" apart. */
|
|
3
|
+
export class GitHubError extends Error {
|
|
4
|
+
status;
|
|
5
|
+
constructor(message, status) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.status = status;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
async function request(api, method, path, body) {
|
|
11
|
+
const res = await api.fetch(`${api.baseUrl}${path}`, {
|
|
12
|
+
method,
|
|
13
|
+
headers: {
|
|
14
|
+
authorization: `Bearer ${api.token}`,
|
|
15
|
+
accept: "application/vnd.github+json",
|
|
16
|
+
"x-github-api-version": "2022-11-28",
|
|
17
|
+
"user-agent": "figdiff-action",
|
|
18
|
+
...(body === undefined ? {} : { "content-type": "application/json" }),
|
|
19
|
+
},
|
|
20
|
+
body: body === undefined ? undefined : JSON.stringify(body),
|
|
21
|
+
});
|
|
22
|
+
if (!res.ok) {
|
|
23
|
+
let detail = "";
|
|
24
|
+
try {
|
|
25
|
+
detail = (await res.json()).message ?? "";
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// the error body was not JSON
|
|
29
|
+
}
|
|
30
|
+
throw new GitHubError(`GitHub API ${method} ${path} failed with ${res.status}${detail ? `: ${detail}` : ""}`, res.status);
|
|
31
|
+
}
|
|
32
|
+
return (res.status === 204 ? undefined : await res.json());
|
|
33
|
+
}
|
|
34
|
+
/** Find the comment figdiff wrote earlier on this pull request, if any. */
|
|
35
|
+
export async function findComment(api, repo, pr) {
|
|
36
|
+
for (let page = 1; page <= 10; page++) {
|
|
37
|
+
const comments = await request(api, "GET", `/repos/${repo}/issues/${pr}/comments?per_page=100&page=${page}`);
|
|
38
|
+
const found = comments.find((c) => c.body?.includes(COMMENT_MARKER));
|
|
39
|
+
if (found)
|
|
40
|
+
return found.id;
|
|
41
|
+
if (comments.length < 100)
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
/** Create the comment, or update the one found earlier so a pull request only ever has one. */
|
|
47
|
+
export async function upsertComment(api, repo, pr, body, existing) {
|
|
48
|
+
if (existing !== undefined) {
|
|
49
|
+
try {
|
|
50
|
+
await request(api, "PATCH", `/repos/${repo}/issues/comments/${existing}`, { body });
|
|
51
|
+
return "updated";
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
// The old comment may have been deleted or belong to someone else: fall through and post a new one.
|
|
55
|
+
if (!(err instanceof GitHubError) || (err.status !== 404 && err.status !== 403))
|
|
56
|
+
throw err;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
await request(api, "POST", `/repos/${repo}/issues/${pr}/comments`, { body });
|
|
60
|
+
return "created";
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/action/github.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Split an input such as "design/**\/*.figcraft, assets/*.figcraft" (commas or new lines) into patterns. */
|
|
2
|
+
export declare function parsePatterns(input: string): string[];
|
|
3
|
+
/**
|
|
4
|
+
* Convert a glob to a regular expression. Supports `*` (within a folder), `**` (across folders)
|
|
5
|
+
* and `?`. `**\/` also matches no folder at all, so `design/**\/*.figcraft` matches
|
|
6
|
+
* `design/app.figcraft`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function globToRegExp(pattern: string): RegExp;
|
|
9
|
+
/** True when the path matches at least one pattern. */
|
|
10
|
+
export declare function matchesAny(path: string, patterns: string[]): boolean;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** Split an input such as "design/**\/*.figcraft, assets/*.figcraft" (commas or new lines) into patterns. */
|
|
2
|
+
export function parsePatterns(input) {
|
|
3
|
+
return input
|
|
4
|
+
.split(/[\n,]/)
|
|
5
|
+
.map((p) => p.trim().replace(/^\.\//, ""))
|
|
6
|
+
.filter((p) => p.length > 0);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Convert a glob to a regular expression. Supports `*` (within a folder), `**` (across folders)
|
|
10
|
+
* and `?`. `**\/` also matches no folder at all, so `design/**\/*.figcraft` matches
|
|
11
|
+
* `design/app.figcraft`.
|
|
12
|
+
*/
|
|
13
|
+
export function globToRegExp(pattern) {
|
|
14
|
+
let source = "";
|
|
15
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
16
|
+
const c = pattern[i];
|
|
17
|
+
if (c === "*") {
|
|
18
|
+
if (pattern[i + 1] === "*") {
|
|
19
|
+
i++;
|
|
20
|
+
if (pattern[i + 1] === "/") {
|
|
21
|
+
i++;
|
|
22
|
+
source += "(?:.*/)?";
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
source += ".*";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
source += "[^/]*";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else if (c === "?") {
|
|
33
|
+
source += "[^/]";
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
source += c.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return new RegExp(`^${source}$`);
|
|
40
|
+
}
|
|
41
|
+
/** True when the path matches at least one pattern. */
|
|
42
|
+
export function matchesAny(path, patterns) {
|
|
43
|
+
return patterns.some((p) => globToRegExp(p).test(path));
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=glob.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob.js","sourceRoot":"","sources":["../../src/action/glob.ts"],"names":[],"mappings":"AAAA,6GAA6G;AAC7G,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,KAAK;SACT,KAAK,CAAC,OAAO,CAAC;SACd,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;SACzC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAW,CAAC;QAC/B,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACd,IAAI,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBAC3B,CAAC,EAAE,CAAC;gBACJ,IAAI,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;oBAC3B,CAAC,EAAE,CAAC;oBACJ,MAAM,IAAI,UAAU,CAAC;gBACvB,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,IAAI,CAAC;gBACjB,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,OAAO,CAAC;YACpB,CAAC;QACH,CAAC;aAAM,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACrB,MAAM,IAAI,MAAM,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,CAAC,CAAC,OAAO,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IACD,OAAO,IAAI,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC;AACnC,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,QAAkB;IACzD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { run as runFigdiff } from "../run.js";
|
|
2
|
+
export interface ActionDeps {
|
|
3
|
+
git(args: string[], cwd: string): string;
|
|
4
|
+
readText(path: string): string;
|
|
5
|
+
writeText(path: string, content: string): void;
|
|
6
|
+
mkdirp(path: string): void;
|
|
7
|
+
fetch: typeof fetch;
|
|
8
|
+
run: typeof runFigdiff;
|
|
9
|
+
}
|
|
10
|
+
export interface ActionResult {
|
|
11
|
+
code: number;
|
|
12
|
+
log: string[];
|
|
13
|
+
comment?: "created" | "updated" | "skipped";
|
|
14
|
+
/** Number of design files with real changes. */
|
|
15
|
+
changed: number;
|
|
16
|
+
}
|
|
17
|
+
type Env = Record<string, string | undefined>;
|
|
18
|
+
/** The entry point of the GitHub Action. Everything it needs comes in through `env` and `deps`. */
|
|
19
|
+
export declare function runAction(env: Env, overrides?: Partial<ActionDeps>): Promise<ActionResult>;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { basename, join } from "node:path";
|
|
4
|
+
import { formatText } from "../report.js";
|
|
5
|
+
import { run as runFigdiff } from "../run.js";
|
|
6
|
+
import { filterByPatterns, parseNameStatus } from "./changed-files.js";
|
|
7
|
+
import { buildComment, buildEmptyComment, isSubstantive } from "./comment.js";
|
|
8
|
+
import { parsePatterns } from "./glob.js";
|
|
9
|
+
import { findComment, GitHubError, upsertComment } from "./github.js";
|
|
10
|
+
const defaultDeps = {
|
|
11
|
+
git: (args, cwd) => execFileSync("git", args, { cwd, encoding: "utf8", maxBuffer: 64 * 1024 * 1024 }),
|
|
12
|
+
readText: (p) => readFileSync(p, "utf8"),
|
|
13
|
+
writeText: (p, c) => writeFileSync(p, c),
|
|
14
|
+
mkdirp: (p) => void mkdirSync(p, { recursive: true }),
|
|
15
|
+
fetch: (...a) => fetch(...a),
|
|
16
|
+
run: runFigdiff,
|
|
17
|
+
};
|
|
18
|
+
function input(env, name, fallback) {
|
|
19
|
+
const v = env[`INPUT_${name.toUpperCase().replace(/-/g, "_")}`];
|
|
20
|
+
return v !== undefined && v.trim() !== "" ? v.trim() : fallback;
|
|
21
|
+
}
|
|
22
|
+
/** Compare one modified file with its version at the base commit. */
|
|
23
|
+
function compareFile(file, root, base, reportDir, deps) {
|
|
24
|
+
const reportName = `${file.path.replace(/[^A-Za-z0-9._-]+/g, "_")}.html`;
|
|
25
|
+
const result = deps.run([join(root, file.path), "--against", base, "--json", "--html", join(reportDir, reportName)]);
|
|
26
|
+
if (result.code !== 0) {
|
|
27
|
+
const message = result.stderr.replace(/^figdiff:\s*/gm, "").trim().split("\n")[0] ?? "unknown error";
|
|
28
|
+
return { file, error: message };
|
|
29
|
+
}
|
|
30
|
+
for (const w of result.writes) {
|
|
31
|
+
deps.mkdirp(reportDir);
|
|
32
|
+
deps.writeText(w.path, w.content);
|
|
33
|
+
}
|
|
34
|
+
const parsed = JSON.parse(result.stdout);
|
|
35
|
+
return { file, summary: parsed.summary, text: formatText(parsed.changes), reportName };
|
|
36
|
+
}
|
|
37
|
+
/** The entry point of the GitHub Action. Everything it needs comes in through `env` and `deps`. */
|
|
38
|
+
export async function runAction(env, overrides = {}) {
|
|
39
|
+
const deps = { ...defaultDeps, ...overrides };
|
|
40
|
+
const log = [];
|
|
41
|
+
const done = (code, extra = {}) => ({ code, log, changed: 0, ...extra });
|
|
42
|
+
if (!env.GITHUB_EVENT_PATH) {
|
|
43
|
+
log.push("figdiff: GITHUB_EVENT_PATH is not set. Run this action in a GitHub workflow.");
|
|
44
|
+
return done(2);
|
|
45
|
+
}
|
|
46
|
+
const event = JSON.parse(deps.readText(env.GITHUB_EVENT_PATH));
|
|
47
|
+
const pr = event.pull_request;
|
|
48
|
+
if (!pr) {
|
|
49
|
+
log.push("figdiff: this action only works on pull_request events; nothing to do.");
|
|
50
|
+
return done(0, { comment: "skipped" });
|
|
51
|
+
}
|
|
52
|
+
const root = env.GITHUB_WORKSPACE ?? process.cwd();
|
|
53
|
+
const patterns = parsePatterns(input(env, "files", "**/*.figcraft"));
|
|
54
|
+
const reportDir = input(env, "report-dir", "figdiff-reports");
|
|
55
|
+
const wantComment = input(env, "comment", "true") !== "false";
|
|
56
|
+
const maxFiles = Math.max(1, Number.parseInt(input(env, "max-files", "20"), 10) || 20);
|
|
57
|
+
let listed;
|
|
58
|
+
try {
|
|
59
|
+
listed = parseNameStatus(deps.git(["diff", "--name-status", "-z", "--no-renames", `${pr.base.sha}...${pr.head.sha}`], root));
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
log.push("figdiff: could not list the changed files. Check out the repository with `fetch-depth: 0` so the base commit is available.");
|
|
63
|
+
return done(2);
|
|
64
|
+
}
|
|
65
|
+
const files = filterByPatterns(listed, patterns);
|
|
66
|
+
log.push(`figdiff: ${files.length} design file(s) changed in this pull request.`);
|
|
67
|
+
const results = [];
|
|
68
|
+
for (const file of files.slice(0, maxFiles)) {
|
|
69
|
+
results.push(file.status === "modified" ? compareFile(file, root, pr.base.sha, reportDir, deps) : { file });
|
|
70
|
+
}
|
|
71
|
+
if (files.length > maxFiles)
|
|
72
|
+
log.push(`figdiff: only the first ${maxFiles} files were compared (max-files).`);
|
|
73
|
+
const changed = results.filter(isSubstantive);
|
|
74
|
+
for (const r of results)
|
|
75
|
+
log.push(`figdiff: ${r.file.path}: ${r.error ?? r.summary?.changes ?? r.file.status}`);
|
|
76
|
+
if (!wantComment)
|
|
77
|
+
return done(0, { comment: "skipped", changed: changed.length });
|
|
78
|
+
const token = env.GITHUB_TOKEN ?? env.INPUT_TOKEN;
|
|
79
|
+
const repo = env.GITHUB_REPOSITORY;
|
|
80
|
+
if (!token || !repo) {
|
|
81
|
+
log.push("figdiff: no token or repository available, so no comment was posted.");
|
|
82
|
+
return done(0, { comment: "skipped", changed: changed.length });
|
|
83
|
+
}
|
|
84
|
+
const api = { fetch: deps.fetch, baseUrl: env.GITHUB_API_URL ?? "https://api.github.com", token };
|
|
85
|
+
try {
|
|
86
|
+
const existing = await findComment(api, repo, pr.number);
|
|
87
|
+
if (changed.length === 0 && existing === undefined) {
|
|
88
|
+
log.push("figdiff: no design changes and no earlier comment; staying quiet.");
|
|
89
|
+
return done(0, { comment: "skipped" });
|
|
90
|
+
}
|
|
91
|
+
const runUrl = env.GITHUB_SERVER_URL && env.GITHUB_RUN_ID ? `${env.GITHUB_SERVER_URL}/${repo}/actions/runs/${env.GITHUB_RUN_ID}` : undefined;
|
|
92
|
+
const body = changed.length === 0
|
|
93
|
+
? buildEmptyComment()
|
|
94
|
+
: buildComment(changed, { runUrl, reportsUploaded: input(env, "upload-reports", "true") !== "false", version: env.FIGDIFF_VERSION });
|
|
95
|
+
const outcome = await upsertComment(api, repo, pr.number, body, existing);
|
|
96
|
+
log.push(`figdiff: comment ${outcome}.`);
|
|
97
|
+
return done(0, { comment: outcome, changed: changed.length });
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
if (err instanceof GitHubError && err.status === 403) {
|
|
101
|
+
// Pull requests from forks get a read-only token: report instead of failing the build.
|
|
102
|
+
log.push("figdiff: not allowed to comment (403). On pull requests from forks the token is read-only; the changes are in the job log.");
|
|
103
|
+
for (const r of changed)
|
|
104
|
+
log.push(`${basename(r.file.path)}:\n${r.text ?? r.error ?? r.file.status}`);
|
|
105
|
+
return done(0, { comment: "skipped", changed: changed.length });
|
|
106
|
+
}
|
|
107
|
+
log.push(`figdiff: ${err instanceof Error ? err.message : String(err)}`);
|
|
108
|
+
return done(2, { changed: changed.length });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/action/main.ts"],"names":[],"mappings":"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"}
|
package/dist/action.d.ts
ADDED
package/dist/action.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action.js","sourceRoot":"","sources":["../src/action.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC5C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,GAAG;IAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACjD,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC"}
|