@intentius/chant-lexicon-github 0.51.0 → 0.52.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/dist/composites/index.d.ts +2 -0
- package/dist/composites/index.d.ts.map +1 -1
- package/dist/composites/pr-plan-report.d.ts +64 -0
- package/dist/composites/pr-plan-report.d.ts.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/integrity.json +2 -2
- package/dist/manifest.json +1 -1
- package/package.json +2 -2
- package/src/codegen/docs.ts +1 -1
- package/src/composites/index.ts +2 -0
- package/src/composites/pr-plan-report.test.ts +109 -0
- package/src/composites/pr-plan-report.ts +150 -0
- package/src/index.ts +2 -0
|
@@ -26,4 +26,6 @@ export { GoCI } from "./go-ci.js";
|
|
|
26
26
|
export type { GoCIProps } from "./go-ci.js";
|
|
27
27
|
export { Dependabot, DependabotConfig } from "./dependabot.js";
|
|
28
28
|
export type { DependabotProps, DependabotConfigProps, DependabotUpdate, DependabotEcosystem } from "./dependabot.js";
|
|
29
|
+
export { PrPlanReport } from "./pr-plan-report.js";
|
|
30
|
+
export type { PrPlanReportProps } from "./pr-plan-report.js";
|
|
29
31
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/composites/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,YAAY,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,YAAY,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACxF,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,YAAY,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,YAAY,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC5D,YAAY,EAAE,eAAe,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/composites/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,YAAY,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,YAAY,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACxF,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,YAAY,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,YAAY,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC5D,YAAY,EAAE,eAAe,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAClH,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Job } from "../generated/index.js";
|
|
2
|
+
export interface PrPlanReportProps {
|
|
3
|
+
/**
|
|
4
|
+
* Lifecycle environment to plan against — the `<environment>` argument of
|
|
5
|
+
* `chant lifecycle plan`.
|
|
6
|
+
*/
|
|
7
|
+
environment: string;
|
|
8
|
+
/** Restrict the plan to one lexicon (the optional `[lexicon]` argument). */
|
|
9
|
+
lexicon?: string;
|
|
10
|
+
/** Plan against chant-owned resources only (passes `--owned`). */
|
|
11
|
+
ownedOnly?: boolean;
|
|
12
|
+
/** Runner label. Default: `"ubuntu-latest"` */
|
|
13
|
+
runsOn?: string;
|
|
14
|
+
/** Node.js version for chant's own toolchain. Default: `"22"` */
|
|
15
|
+
nodeVersion?: string;
|
|
16
|
+
/** Install command, run after checkout. Default: `"npm ci"` */
|
|
17
|
+
installCommand?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Commands to run before the plan — typically cloud-credential setup, since
|
|
20
|
+
* the plan queries the live system to classify create/update/delete.
|
|
21
|
+
*/
|
|
22
|
+
before?: string[];
|
|
23
|
+
/**
|
|
24
|
+
* Post the plan as a sticky PR comment. Default: `true` — the point of this
|
|
25
|
+
* composite is that the compiled diff reaches the reviewer without being
|
|
26
|
+
* asked for, so the manual step it replaces stops being skippable because
|
|
27
|
+
* it stops being manual. Set `false` to run the plan without posting —
|
|
28
|
+
* the explicit opt-out.
|
|
29
|
+
*/
|
|
30
|
+
postComment?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Hidden marker that makes the comment findable across pushes. Defaults to
|
|
33
|
+
* one keyed on `environment`, so a repo planning two environments gets two
|
|
34
|
+
* comments and each updates in place; override only to share one comment
|
|
35
|
+
* across environments.
|
|
36
|
+
*/
|
|
37
|
+
marker?: string;
|
|
38
|
+
/** Per-member defaults for customizing the generated job. */
|
|
39
|
+
defaults?: {
|
|
40
|
+
job?: Partial<ConstructorParameters<typeof Job>[0]>;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* A CI job that builds, plans, and posts `chant lifecycle plan --report
|
|
45
|
+
* markdown` as a sticky PR comment (#1983) — the compiled diff reaches the
|
|
46
|
+
* reviewer without being asked for.
|
|
47
|
+
*
|
|
48
|
+
* A sibling of the gitlab lexicon's `MrPlanReport`, but where GitLab renders
|
|
49
|
+
* a native merge-request widget from a counts artifact, GitHub has no such
|
|
50
|
+
* widget: the mechanism is the sticky-comment recipe `examples/github-pr-preview`
|
|
51
|
+
* proved (#1223), reused here rather than reinvented. The forgejo lexicon
|
|
52
|
+
* inherits this composite through its github re-export, since Forgejo Actions
|
|
53
|
+
* runs the same workflow shape and the Forgejo API accepts the same `gh api`
|
|
54
|
+
* calls against its GitHub-compatible surface.
|
|
55
|
+
*
|
|
56
|
+
* Only meaningful on a `pull_request`-triggered workflow — the job guards on
|
|
57
|
+
* `github.event_name` since the comment targets `github.event.number`, which
|
|
58
|
+
* a push-triggered run does not have. The plan reads the live system, so wire
|
|
59
|
+
* cloud credentials via `before` or CI variables.
|
|
60
|
+
*/
|
|
61
|
+
export declare const PrPlanReport: import("@intentius/chant").CompositeDefinition<PrPlanReportProps, {
|
|
62
|
+
job: import("@intentius/chant").Declarable & Record<string, string>;
|
|
63
|
+
}>;
|
|
64
|
+
//# sourceMappingURL=pr-plan-report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-plan-report.d.ts","sourceRoot":"","sources":["../../src/composites/pr-plan-report.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAqB,MAAM,oBAAoB,CAAC;AAI5D,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,+CAA+C;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE;QACT,GAAG,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACrD,CAAC;CACH;AAoBD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,YAAY;;EAkEP,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ export { githubPlugin } from "./plugin.js";
|
|
|
3
3
|
export { Expression, github, runner, secrets, matrix, steps, needs, inputs, vars, env, always, failure, success, cancelled, contains, startsWith, toJSON, fromJSON, format, branch, tag, } from "./expression.js";
|
|
4
4
|
export { GitHub, Runner } from "./variables.js";
|
|
5
5
|
export * from "./generated/index.js";
|
|
6
|
-
export { Checkout, SetupNode, SetupGo, SetupPython, CacheAction, UploadArtifact, DownloadArtifact, NodeCI, NodePipeline, BunPipeline, PnpmPipeline, YarnPipeline, PythonCI, DockerBuild, DeployEnvironment, GoCI, Dependabot, DependabotConfig, } from "./composites/index.js";
|
|
7
|
-
export type { CheckoutProps, SetupNodeProps, SetupGoProps, SetupPythonProps, CacheActionProps, UploadArtifactProps, DownloadArtifactProps, NodeCIProps, NodePipelineProps, PythonCIProps, DockerBuildProps, DeployEnvironmentProps, GoCIProps, DependabotProps, DependabotConfigProps, DependabotUpdate, DependabotEcosystem, } from "./composites/index.js";
|
|
6
|
+
export { Checkout, SetupNode, SetupGo, SetupPython, CacheAction, UploadArtifact, DownloadArtifact, NodeCI, NodePipeline, BunPipeline, PnpmPipeline, YarnPipeline, PythonCI, DockerBuild, DeployEnvironment, GoCI, Dependabot, DependabotConfig, PrPlanReport, } from "./composites/index.js";
|
|
7
|
+
export type { CheckoutProps, SetupNodeProps, SetupGoProps, SetupPythonProps, CacheActionProps, UploadArtifactProps, DownloadArtifactProps, NodeCIProps, NodePipelineProps, PythonCIProps, DockerBuildProps, DeployEnvironmentProps, GoCIProps, DependabotProps, DependabotConfigProps, DependabotUpdate, DependabotEcosystem, PrPlanReportProps, } from "./composites/index.js";
|
|
8
8
|
export { fetchWorkflowSchema, fetchSchemas } from "./spec/fetch.js";
|
|
9
9
|
export { parseWorkflowSchema, githubShortName, githubServiceName } from "./codegen/parse.js";
|
|
10
10
|
export type { GitHubParseResult, ParsedResource, ParsedProperty, ParsedPropertyType, ParsedEnum } from "./codegen/parse.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhD,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGxC,OAAO,EACL,UAAU,EACV,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAChE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EACnC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAC9C,MAAM,EAAE,GAAG,GACZ,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAI7C,cAAc,mBAAmB,CAAC;AAGlC,OAAO,EACL,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EACzC,WAAW,EAAE,cAAc,EAAE,gBAAgB,EAC7C,MAAM,EACN,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EACrD,QAAQ,EACR,WAAW,EACX,iBAAiB,EACjB,IAAI,EACJ,UAAU,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhD,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGxC,OAAO,EACL,UAAU,EACV,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAChE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EACnC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAC9C,MAAM,EAAE,GAAG,GACZ,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAI7C,cAAc,mBAAmB,CAAC;AAGlC,OAAO,EACL,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EACzC,WAAW,EAAE,cAAc,EAAE,gBAAgB,EAC7C,MAAM,EACN,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EACrD,QAAQ,EACR,WAAW,EACX,iBAAiB,EACjB,IAAI,EACJ,UAAU,EAAE,gBAAgB,EAC5B,YAAY,GACb,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,gBAAgB,EAC7D,gBAAgB,EAAE,mBAAmB,EAAE,qBAAqB,EAC5D,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,sBAAsB,EACtB,SAAS,EACT,eAAe,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,mBAAmB,EAC7E,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC1F,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,cAAc,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGzH,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/integrity.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"algorithm": "sha256",
|
|
3
3
|
"artifacts": {
|
|
4
|
-
"manifest.json": "
|
|
4
|
+
"manifest.json": "f34639b85f5e99781f6774eb1855b1988b7da79dbe2f03650e2e1d7af7d64b2c",
|
|
5
5
|
"meta.json": "e891b1214d530fd676172e3f7e0734995b9f839b7659eb2d53f43ffc97dcd21b",
|
|
6
6
|
"types/index.d.ts": "7eab3c62c76bff65d68765609e9b6151844a1f581b0c648d0eda779b4252adaf",
|
|
7
7
|
"rules/deprecated-action-version.ts": "d41e6e532ab7f623af1bee4ac5279fcb2baada7defa1c5d022a5bc71983e8797",
|
|
@@ -77,5 +77,5 @@
|
|
|
77
77
|
"skills/chant-github-patterns.md": "bb3abef289a8fdfcf07d6bb2d7289dcb2f38bc0cb0321ea320b78b45a6f548c0",
|
|
78
78
|
"skills/chant-github-security.md": "aab111cb0871cad30281ce48d7da23663689619351029219e2be019a1a61e394"
|
|
79
79
|
},
|
|
80
|
-
"composite": "
|
|
80
|
+
"composite": "d29354b7bf24d3c4017d583c09798d87ace0c5d51ad9cc63573cd8ca3e73958c"
|
|
81
81
|
}
|
package/dist/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-github",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.52.0",
|
|
4
4
|
"description": "GitHub Actions lexicon for chant — declarative IaC in TypeScript",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://intentius.io/chant",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"typescript": "^5.9.3"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
|
-
"@intentius/chant": "^0.
|
|
64
|
+
"@intentius/chant": "^0.52.0",
|
|
65
65
|
"typescript": "^5.9.3"
|
|
66
66
|
}
|
|
67
67
|
}
|
package/src/codegen/docs.ts
CHANGED
|
@@ -25,7 +25,7 @@ npm install --save-dev @intentius/chant-lexicon-github
|
|
|
25
25
|
|
|
26
26
|
{{file:docs-snippets/src/quickstart.ts}}
|
|
27
27
|
|
|
28
|
-
The lexicon provides **3 resources** (Workflow, Job, Dependabot config), **
|
|
28
|
+
The lexicon provides **3 resources** (Workflow, Job, Dependabot config), **15 composites** (Checkout, SetupNode, SetupGo, SetupPython, CacheAction, UploadArtifact, DownloadArtifact, NodeCI, NodePipeline, PythonCI, DockerBuild, DeployEnvironment, GoCI, Dependabot, PrPlanReport) + **3 presets** (BunPipeline, PnpmPipeline, YarnPipeline), a typed **Expression** system with 24 GitHub and 5 Runner context variables, and **13 lint rules** + **49 post-synth checks** (including a CI/CD supply-chain security pass, GHA029–062).
|
|
29
29
|
`;
|
|
30
30
|
|
|
31
31
|
const outputFormat = `The GitHub Actions lexicon serializes resources into **\`.github/workflows/*.yml\`** YAML files.
|
package/src/composites/index.ts
CHANGED
|
@@ -26,3 +26,5 @@ export { GoCI } from "./go-ci";
|
|
|
26
26
|
export type { GoCIProps } from "./go-ci";
|
|
27
27
|
export { Dependabot, DependabotConfig } from "./dependabot";
|
|
28
28
|
export type { DependabotProps, DependabotConfigProps, DependabotUpdate, DependabotEcosystem } from "./dependabot";
|
|
29
|
+
export { PrPlanReport } from "./pr-plan-report";
|
|
30
|
+
export type { PrPlanReportProps } from "./pr-plan-report";
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { describe, test, expect } from "vitest";
|
|
2
|
+
import type { PostSynthContext } from "@intentius/chant/lint/post-synth";
|
|
3
|
+
import { PrPlanReport } from "./pr-plan-report";
|
|
4
|
+
import { githubPlugin } from "../plugin";
|
|
5
|
+
import { githubSerializer } from "../serializer";
|
|
6
|
+
import { Workflow } from "../generated/index";
|
|
7
|
+
import type { SerializerResult } from "@intentius/chant/serializer";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* `Job`/`Step` (`../generated/index`) come from core's `createResource`/
|
|
11
|
+
* `createProperty` (`packages/core/src/runtime.ts`), whose constructor type
|
|
12
|
+
* is `new (...) => Declarable & Record<string, string>` — every property,
|
|
13
|
+
* `.props` included, reads back as `string` regardless of what was actually
|
|
14
|
+
* passed in. That is a known, tracked gap (chant #1388's shrinking
|
|
15
|
+
* typecheck baseline; `composites.test.ts` in this same directory is
|
|
16
|
+
* grandfathered into it for exactly this reason). This file is new, so
|
|
17
|
+
* rather than add to that backlog, these two interfaces describe the real
|
|
18
|
+
* runtime shape for the fields this file asserts on, and `asJob` narrows the
|
|
19
|
+
* composite's output into it once instead of reading `.props` off the
|
|
20
|
+
* loosely-typed instance directly.
|
|
21
|
+
*/
|
|
22
|
+
interface StepLike {
|
|
23
|
+
props: { name?: string; run?: string };
|
|
24
|
+
}
|
|
25
|
+
interface JobLike {
|
|
26
|
+
props: {
|
|
27
|
+
"runs-on": string;
|
|
28
|
+
if?: string;
|
|
29
|
+
permissions?: unknown;
|
|
30
|
+
env?: Record<string, string>;
|
|
31
|
+
steps?: StepLike[];
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function asJob(job: unknown): JobLike {
|
|
36
|
+
return job as JobLike;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function steps(job: unknown): StepLike[] {
|
|
40
|
+
return asJob(job).props.steps ?? [];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
describe("PrPlanReport composite (#1983)", () => {
|
|
44
|
+
test("defaults: guarded on pull_request, posts by default, marker keyed on environment", () => {
|
|
45
|
+
const { job } = PrPlanReport({ environment: "prod" });
|
|
46
|
+
expect(asJob(job).props["runs-on"]).toBe("ubuntu-latest");
|
|
47
|
+
expect(asJob(job).props.if).toBe("github.event_name == 'pull_request'");
|
|
48
|
+
expect(asJob(job).props.permissions).toMatchObject({ props: { contents: "read", "pull-requests": "write" } });
|
|
49
|
+
expect(asJob(job).props.env?.MARKER).toBe("<!-- chant-pr-plan-report:prod -->");
|
|
50
|
+
const names = steps(job).map((s) => s.props.name);
|
|
51
|
+
expect(names).toContain("Post or update PR comment");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("two environments get two distinct markers", () => {
|
|
55
|
+
const prod = PrPlanReport({ environment: "prod" }).job;
|
|
56
|
+
const staging = PrPlanReport({ environment: "staging" }).job;
|
|
57
|
+
expect(asJob(prod).props.env?.MARKER).not.toBe(asJob(staging).props.env?.MARKER);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("postComment: false is the explicit opt-out — no comment step, plan still runs", () => {
|
|
61
|
+
const { job } = PrPlanReport({ environment: "prod", postComment: false });
|
|
62
|
+
const names = steps(job).map((s) => s.props.name);
|
|
63
|
+
expect(names).not.toContain("Post or update PR comment");
|
|
64
|
+
expect(names.some((n) => n?.startsWith("Plan "))).toBe(true);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("lexicon and --owned reach the plan command", () => {
|
|
68
|
+
const { job } = PrPlanReport({ environment: "prod", lexicon: "aws", ownedOnly: true });
|
|
69
|
+
const planStep = steps(job).find((s) => s.props.name === "Plan prod")!;
|
|
70
|
+
expect(planStep.props.run).toContain("lifecycle plan prod aws --owned --report markdown");
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("before commands become their own credential-setup steps, in order, ahead of the plan", () => {
|
|
74
|
+
const { job } = PrPlanReport({ environment: "prod", before: ["aws sts get-caller-identity", "echo ready"] });
|
|
75
|
+
const names = steps(job).map((s) => s.props.name);
|
|
76
|
+
const planIndex = names.indexOf("Plan prod");
|
|
77
|
+
const credIndexes = names.reduce<number[]>((acc, n, i) => (n === "Live credentials" ? [...acc, i] : acc), []);
|
|
78
|
+
expect(credIndexes).toHaveLength(2);
|
|
79
|
+
expect(Math.max(...credIndexes)).toBeLessThan(planIndex);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("the emitted workflow passes the github lexicon's own lint — no errors, pinned actions included", () => {
|
|
83
|
+
const { job } = PrPlanReport({ environment: "prod", before: ["aws sts get-caller-identity"] });
|
|
84
|
+
const workflow = new Workflow({
|
|
85
|
+
name: "pr-plan",
|
|
86
|
+
on: { pull_request: { types: ["opened", "synchronize", "reopened"] } },
|
|
87
|
+
});
|
|
88
|
+
const result = githubSerializer.serialize(
|
|
89
|
+
new Map<string, unknown>([["workflow", workflow], ["plan", job]]) as never,
|
|
90
|
+
) as SerializerResult;
|
|
91
|
+
const yaml = typeof result === "string" ? result : result.primary!;
|
|
92
|
+
expect(yaml).toContain("Post or update PR comment");
|
|
93
|
+
|
|
94
|
+
const ctx: PostSynthContext = {
|
|
95
|
+
outputs: new Map([["github", yaml]]),
|
|
96
|
+
entities: new Map(),
|
|
97
|
+
buildResult: {
|
|
98
|
+
outputs: new Map([["github", yaml]]),
|
|
99
|
+
entities: new Map(),
|
|
100
|
+
warnings: [],
|
|
101
|
+
errors: [],
|
|
102
|
+
sourceFileCount: 1,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
const diagnostics = githubPlugin.postSynthChecks!().flatMap((check) => check.check(ctx));
|
|
106
|
+
const errors = diagnostics.filter((d) => d.severity === "error");
|
|
107
|
+
expect(errors).toEqual([]);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { Composite, mergeDefaults } from "@intentius/chant";
|
|
2
|
+
import { Job, Step, Permissions } from "../generated/index";
|
|
3
|
+
import { Checkout } from "./checkout";
|
|
4
|
+
import { SetupNode } from "./setup-node";
|
|
5
|
+
|
|
6
|
+
export interface PrPlanReportProps {
|
|
7
|
+
/**
|
|
8
|
+
* Lifecycle environment to plan against — the `<environment>` argument of
|
|
9
|
+
* `chant lifecycle plan`.
|
|
10
|
+
*/
|
|
11
|
+
environment: string;
|
|
12
|
+
/** Restrict the plan to one lexicon (the optional `[lexicon]` argument). */
|
|
13
|
+
lexicon?: string;
|
|
14
|
+
/** Plan against chant-owned resources only (passes `--owned`). */
|
|
15
|
+
ownedOnly?: boolean;
|
|
16
|
+
/** Runner label. Default: `"ubuntu-latest"` */
|
|
17
|
+
runsOn?: string;
|
|
18
|
+
/** Node.js version for chant's own toolchain. Default: `"22"` */
|
|
19
|
+
nodeVersion?: string;
|
|
20
|
+
/** Install command, run after checkout. Default: `"npm ci"` */
|
|
21
|
+
installCommand?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Commands to run before the plan — typically cloud-credential setup, since
|
|
24
|
+
* the plan queries the live system to classify create/update/delete.
|
|
25
|
+
*/
|
|
26
|
+
before?: string[];
|
|
27
|
+
/**
|
|
28
|
+
* Post the plan as a sticky PR comment. Default: `true` — the point of this
|
|
29
|
+
* composite is that the compiled diff reaches the reviewer without being
|
|
30
|
+
* asked for, so the manual step it replaces stops being skippable because
|
|
31
|
+
* it stops being manual. Set `false` to run the plan without posting —
|
|
32
|
+
* the explicit opt-out.
|
|
33
|
+
*/
|
|
34
|
+
postComment?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Hidden marker that makes the comment findable across pushes. Defaults to
|
|
37
|
+
* one keyed on `environment`, so a repo planning two environments gets two
|
|
38
|
+
* comments and each updates in place; override only to share one comment
|
|
39
|
+
* across environments.
|
|
40
|
+
*/
|
|
41
|
+
marker?: string;
|
|
42
|
+
/** Per-member defaults for customizing the generated job. */
|
|
43
|
+
defaults?: {
|
|
44
|
+
job?: Partial<ConstructorParameters<typeof Job>[0]>;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Sticky-comment script (#1223's mechanism, reused as-is): find the comment
|
|
50
|
+
* whose body starts with `$MARKER`, PATCH it if found, POST otherwise. No
|
|
51
|
+
* marketplace action, nothing extra to pin — `gh` ships on GitHub's hosted
|
|
52
|
+
* runners. `-f body=@plan.md` reads the comment body from the file the plan
|
|
53
|
+
* step wrote, so a large or multi-line plan never has to survive shell
|
|
54
|
+
* quoting.
|
|
55
|
+
*/
|
|
56
|
+
const stickyCommentScript = [
|
|
57
|
+
'comment_id=$(gh api "repos/$REPO/issues/$PR_NUMBER/comments" --paginate ' +
|
|
58
|
+
'--jq "map(select(.body | startswith(\\"$MARKER\\"))) | .[0].id // empty")',
|
|
59
|
+
'if [ -n "$comment_id" ]; then',
|
|
60
|
+
' gh api -X PATCH "repos/$REPO/issues/comments/$comment_id" -f body=@plan.md > /dev/null',
|
|
61
|
+
"else",
|
|
62
|
+
' gh api -X POST "repos/$REPO/issues/$PR_NUMBER/comments" -f body=@plan.md > /dev/null',
|
|
63
|
+
"fi",
|
|
64
|
+
].join("\n");
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* A CI job that builds, plans, and posts `chant lifecycle plan --report
|
|
68
|
+
* markdown` as a sticky PR comment (#1983) — the compiled diff reaches the
|
|
69
|
+
* reviewer without being asked for.
|
|
70
|
+
*
|
|
71
|
+
* A sibling of the gitlab lexicon's `MrPlanReport`, but where GitLab renders
|
|
72
|
+
* a native merge-request widget from a counts artifact, GitHub has no such
|
|
73
|
+
* widget: the mechanism is the sticky-comment recipe `examples/github-pr-preview`
|
|
74
|
+
* proved (#1223), reused here rather than reinvented. The forgejo lexicon
|
|
75
|
+
* inherits this composite through its github re-export, since Forgejo Actions
|
|
76
|
+
* runs the same workflow shape and the Forgejo API accepts the same `gh api`
|
|
77
|
+
* calls against its GitHub-compatible surface.
|
|
78
|
+
*
|
|
79
|
+
* Only meaningful on a `pull_request`-triggered workflow — the job guards on
|
|
80
|
+
* `github.event_name` since the comment targets `github.event.number`, which
|
|
81
|
+
* a push-triggered run does not have. The plan reads the live system, so wire
|
|
82
|
+
* cloud credentials via `before` or CI variables.
|
|
83
|
+
*/
|
|
84
|
+
export const PrPlanReport = Composite((props: PrPlanReportProps) => {
|
|
85
|
+
const {
|
|
86
|
+
environment,
|
|
87
|
+
lexicon,
|
|
88
|
+
ownedOnly = false,
|
|
89
|
+
runsOn = "ubuntu-latest",
|
|
90
|
+
nodeVersion = "22",
|
|
91
|
+
installCommand = "npm ci",
|
|
92
|
+
before,
|
|
93
|
+
postComment = true,
|
|
94
|
+
marker = `<!-- chant-pr-plan-report:${environment} -->`,
|
|
95
|
+
defaults: defs,
|
|
96
|
+
} = props;
|
|
97
|
+
|
|
98
|
+
const planArgs = [
|
|
99
|
+
"lifecycle",
|
|
100
|
+
"plan",
|
|
101
|
+
environment,
|
|
102
|
+
...(lexicon ? [lexicon] : []),
|
|
103
|
+
...(ownedOnly ? ["--owned"] : []),
|
|
104
|
+
"--report",
|
|
105
|
+
"markdown",
|
|
106
|
+
].join(" ");
|
|
107
|
+
|
|
108
|
+
const steps = [
|
|
109
|
+
Checkout({}).step,
|
|
110
|
+
SetupNode({ nodeVersion, cache: "npm" }).step,
|
|
111
|
+
new Step({ name: "Install", run: installCommand }),
|
|
112
|
+
...(before ?? []).map((cmd) => new Step({ name: "Live credentials", run: cmd })),
|
|
113
|
+
new Step({ name: "Build", run: "npx chant build" }),
|
|
114
|
+
new Step({
|
|
115
|
+
name: `Plan ${environment}`,
|
|
116
|
+
// The marker (and an "updated for" footer, same spirit as the preview
|
|
117
|
+
// tutorial's) is prepended to the rendered plan before anything is
|
|
118
|
+
// posted, so the comment body itself carries the identity the search
|
|
119
|
+
// step below keys on.
|
|
120
|
+
run: [
|
|
121
|
+
`npx chant ${planArgs} > plan-body.md`,
|
|
122
|
+
'{ printf \'%s\\n\\n\' "$MARKER"; printf \'_Updated for %s._\\n\\n\' "$HEAD_SHA"; cat plan-body.md; } > plan.md',
|
|
123
|
+
].join("\n"),
|
|
124
|
+
}),
|
|
125
|
+
...(postComment
|
|
126
|
+
? [
|
|
127
|
+
new Step({
|
|
128
|
+
name: "Post or update PR comment",
|
|
129
|
+
env: { GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}" },
|
|
130
|
+
run: stickyCommentScript,
|
|
131
|
+
}),
|
|
132
|
+
]
|
|
133
|
+
: []),
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
const job = new Job(mergeDefaults({
|
|
137
|
+
"runs-on": runsOn,
|
|
138
|
+
if: "github.event_name == 'pull_request'",
|
|
139
|
+
permissions: new Permissions({ contents: "read", "pull-requests": "write" }),
|
|
140
|
+
env: {
|
|
141
|
+
MARKER: marker,
|
|
142
|
+
HEAD_SHA: "${{ github.event.pull_request.head.sha }}",
|
|
143
|
+
PR_NUMBER: "${{ github.event.number }}",
|
|
144
|
+
REPO: "${{ github.repository }}",
|
|
145
|
+
},
|
|
146
|
+
steps,
|
|
147
|
+
}, defs?.job));
|
|
148
|
+
|
|
149
|
+
return { job };
|
|
150
|
+
}, "PrPlanReport");
|
package/src/index.ts
CHANGED
|
@@ -31,6 +31,7 @@ export {
|
|
|
31
31
|
DeployEnvironment,
|
|
32
32
|
GoCI,
|
|
33
33
|
Dependabot, DependabotConfig,
|
|
34
|
+
PrPlanReport,
|
|
34
35
|
} from "./composites/index";
|
|
35
36
|
export type {
|
|
36
37
|
CheckoutProps, SetupNodeProps, SetupGoProps, SetupPythonProps,
|
|
@@ -42,6 +43,7 @@ export type {
|
|
|
42
43
|
DeployEnvironmentProps,
|
|
43
44
|
GoCIProps,
|
|
44
45
|
DependabotProps, DependabotConfigProps, DependabotUpdate, DependabotEcosystem,
|
|
46
|
+
PrPlanReportProps,
|
|
45
47
|
} from "./composites/index";
|
|
46
48
|
|
|
47
49
|
// Spec utilities (for tooling)
|