@intentius/chant-lexicon-github 0.0.18
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/integrity.json +31 -0
- package/dist/manifest.json +15 -0
- package/dist/meta.json +135 -0
- package/dist/rules/deprecated-action-version.ts +49 -0
- package/dist/rules/detect-secrets.ts +53 -0
- package/dist/rules/extract-inline-structs.ts +62 -0
- package/dist/rules/file-job-limit.ts +49 -0
- package/dist/rules/gha006.ts +58 -0
- package/dist/rules/gha009.ts +42 -0
- package/dist/rules/gha011.ts +40 -0
- package/dist/rules/gha017.ts +32 -0
- package/dist/rules/gha018.ts +40 -0
- package/dist/rules/gha019.ts +72 -0
- package/dist/rules/job-timeout.ts +59 -0
- package/dist/rules/missing-recommended-inputs.ts +61 -0
- package/dist/rules/no-hardcoded-secrets.ts +46 -0
- package/dist/rules/no-raw-expressions.ts +51 -0
- package/dist/rules/suggest-cache.ts +71 -0
- package/dist/rules/use-condition-builders.ts +45 -0
- package/dist/rules/use-matrix-builder.ts +44 -0
- package/dist/rules/use-typed-actions.ts +47 -0
- package/dist/rules/validate-concurrency.ts +66 -0
- package/dist/rules/yaml-helpers.ts +129 -0
- package/dist/skills/chant-github.md +29 -0
- package/dist/skills/github-actions-patterns.md +93 -0
- package/dist/types/index.d.ts +358 -0
- package/package.json +33 -0
- package/src/codegen/docs-cli.ts +3 -0
- package/src/codegen/docs.ts +1138 -0
- package/src/codegen/generate-cli.ts +36 -0
- package/src/codegen/generate-lexicon.ts +58 -0
- package/src/codegen/generate-typescript.ts +149 -0
- package/src/codegen/generate.ts +141 -0
- package/src/codegen/naming.ts +57 -0
- package/src/codegen/package.ts +65 -0
- package/src/codegen/parse.ts +700 -0
- package/src/codegen/patches.ts +46 -0
- package/src/composites/cache.ts +25 -0
- package/src/composites/checkout.ts +31 -0
- package/src/composites/composites.test.ts +675 -0
- package/src/composites/deploy-environment.ts +77 -0
- package/src/composites/docker-build.ts +120 -0
- package/src/composites/download-artifact.ts +24 -0
- package/src/composites/go-ci.ts +91 -0
- package/src/composites/index.ts +26 -0
- package/src/composites/node-ci.ts +71 -0
- package/src/composites/node-pipeline.ts +151 -0
- package/src/composites/python-ci.ts +92 -0
- package/src/composites/setup-go.ts +24 -0
- package/src/composites/setup-node.ts +26 -0
- package/src/composites/setup-python.ts +24 -0
- package/src/composites/upload-artifact.ts +27 -0
- package/src/coverage.ts +49 -0
- package/src/expression.test.ts +147 -0
- package/src/expression.ts +214 -0
- package/src/generated/index.d.ts +358 -0
- package/src/generated/index.ts +29 -0
- package/src/generated/lexicon-github.json +135 -0
- package/src/generated/runtime.ts +4 -0
- package/src/import/generator.test.ts +110 -0
- package/src/import/generator.ts +119 -0
- package/src/import/parser.test.ts +98 -0
- package/src/import/parser.ts +73 -0
- package/src/index.ts +53 -0
- package/src/lint/post-synth/gha006.ts +58 -0
- package/src/lint/post-synth/gha009.ts +42 -0
- package/src/lint/post-synth/gha011.ts +40 -0
- package/src/lint/post-synth/gha017.ts +32 -0
- package/src/lint/post-synth/gha018.ts +40 -0
- package/src/lint/post-synth/gha019.ts +72 -0
- package/src/lint/post-synth/post-synth.test.ts +318 -0
- package/src/lint/post-synth/yaml-helpers.ts +129 -0
- package/src/lint/rules/data/deprecated-versions.ts +13 -0
- package/src/lint/rules/data/known-actions.ts +13 -0
- package/src/lint/rules/data/recommended-inputs.ts +10 -0
- package/src/lint/rules/data/secret-patterns.ts +31 -0
- package/src/lint/rules/deprecated-action-version.ts +49 -0
- package/src/lint/rules/detect-secrets.ts +53 -0
- package/src/lint/rules/extract-inline-structs.ts +62 -0
- package/src/lint/rules/file-job-limit.ts +49 -0
- package/src/lint/rules/index.ts +17 -0
- package/src/lint/rules/job-timeout.ts +59 -0
- package/src/lint/rules/missing-recommended-inputs.ts +61 -0
- package/src/lint/rules/no-hardcoded-secrets.ts +46 -0
- package/src/lint/rules/no-raw-expressions.ts +51 -0
- package/src/lint/rules/rules.test.ts +365 -0
- package/src/lint/rules/suggest-cache.ts +71 -0
- package/src/lint/rules/use-condition-builders.ts +45 -0
- package/src/lint/rules/use-matrix-builder.ts +44 -0
- package/src/lint/rules/use-typed-actions.ts +47 -0
- package/src/lint/rules/validate-concurrency.ts +66 -0
- package/src/lsp/completions.test.ts +9 -0
- package/src/lsp/completions.ts +20 -0
- package/src/lsp/hover.test.ts +9 -0
- package/src/lsp/hover.ts +38 -0
- package/src/package-cli.ts +42 -0
- package/src/plugin.test.ts +128 -0
- package/src/plugin.ts +408 -0
- package/src/serializer.test.ts +270 -0
- package/src/serializer.ts +383 -0
- package/src/skills/github-actions-patterns.md +93 -0
- package/src/spec/fetch.ts +55 -0
- package/src/validate-cli.ts +19 -0
- package/src/validate.test.ts +12 -0
- package/src/validate.ts +32 -0
- package/src/variables.ts +44 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Composite } from "@intentius/chant";
|
|
2
|
+
|
|
3
|
+
export interface DeployEnvironmentProps {
|
|
4
|
+
/** Environment name. Required. */
|
|
5
|
+
name: string;
|
|
6
|
+
/** Deploy command(s). Required. */
|
|
7
|
+
deployScript: string | string[];
|
|
8
|
+
/** Cleanup command(s). Default: 'echo "Cleaning up..."' */
|
|
9
|
+
cleanupScript?: string | string[];
|
|
10
|
+
/** Environment URL */
|
|
11
|
+
url?: string;
|
|
12
|
+
/** Concurrency group. Default: "deploy-{name}" */
|
|
13
|
+
concurrencyGroup?: string;
|
|
14
|
+
/** Cancel in-progress deploys. Default: true */
|
|
15
|
+
cancelInProgress?: boolean;
|
|
16
|
+
/** Runner label. Default: "ubuntu-latest" */
|
|
17
|
+
runsOn?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const DeployEnvironment = Composite<DeployEnvironmentProps>((props) => {
|
|
21
|
+
const {
|
|
22
|
+
name,
|
|
23
|
+
deployScript,
|
|
24
|
+
cleanupScript = 'echo "Cleaning up..."',
|
|
25
|
+
url,
|
|
26
|
+
concurrencyGroup,
|
|
27
|
+
cancelInProgress = true,
|
|
28
|
+
runsOn = "ubuntu-latest",
|
|
29
|
+
} = props;
|
|
30
|
+
|
|
31
|
+
const group = concurrencyGroup ?? `deploy-${name}`;
|
|
32
|
+
const deployScriptArr = Array.isArray(deployScript) ? deployScript : [deployScript];
|
|
33
|
+
const cleanupScriptArr = Array.isArray(cleanupScript) ? cleanupScript : [cleanupScript];
|
|
34
|
+
|
|
35
|
+
const { createProperty, createResource } = require("@intentius/chant/runtime");
|
|
36
|
+
const StepClass = createProperty("GitHub::Actions::Step", "github");
|
|
37
|
+
const JobClass = createResource("GitHub::Actions::Job", "github", {});
|
|
38
|
+
|
|
39
|
+
// ── Deploy job ─────────────────────────────────────────────────────
|
|
40
|
+
const deploySteps = [
|
|
41
|
+
new StepClass({ name: "Checkout", uses: "actions/checkout@v4" }),
|
|
42
|
+
...deployScriptArr.map(
|
|
43
|
+
(cmd: string) => new StepClass({ name: "Deploy", run: cmd }),
|
|
44
|
+
),
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
const environment: Record<string, string> = { name };
|
|
48
|
+
if (url) {
|
|
49
|
+
environment.url = url;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const deployJob = new JobClass({
|
|
53
|
+
"runs-on": runsOn,
|
|
54
|
+
environment,
|
|
55
|
+
concurrency: {
|
|
56
|
+
group,
|
|
57
|
+
"cancel-in-progress": cancelInProgress,
|
|
58
|
+
},
|
|
59
|
+
steps: deploySteps,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// ── Cleanup job ────────────────────────────────────────────────────
|
|
63
|
+
const cleanupSteps = [
|
|
64
|
+
new StepClass({ name: "Checkout", uses: "actions/checkout@v4" }),
|
|
65
|
+
...cleanupScriptArr.map(
|
|
66
|
+
(cmd: string) => new StepClass({ name: "Cleanup", run: cmd }),
|
|
67
|
+
),
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
const cleanupJob = new JobClass({
|
|
71
|
+
"runs-on": runsOn,
|
|
72
|
+
environment: { name },
|
|
73
|
+
steps: cleanupSteps,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
return { deployJob, cleanupJob };
|
|
77
|
+
}, "DeployEnvironment");
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { Composite } from "@intentius/chant";
|
|
2
|
+
|
|
3
|
+
export interface DockerBuildProps {
|
|
4
|
+
/** Image tag. Default: "${{ github.sha }}" */
|
|
5
|
+
tag?: string;
|
|
6
|
+
/** Dockerfile path. Default: "Dockerfile" */
|
|
7
|
+
dockerfile?: string;
|
|
8
|
+
/** Build context. Default: "." */
|
|
9
|
+
context?: string;
|
|
10
|
+
/** Container registry. Default: "ghcr.io" */
|
|
11
|
+
registry?: string;
|
|
12
|
+
/** Full image name. Default: "ghcr.io/${{ github.repository }}" */
|
|
13
|
+
imageName?: string;
|
|
14
|
+
/** Also tag as :latest. Default: true */
|
|
15
|
+
tagLatest?: boolean;
|
|
16
|
+
/** Extra docker build-args */
|
|
17
|
+
buildArgs?: Record<string, string>;
|
|
18
|
+
/** Push image after build. Default: true */
|
|
19
|
+
push?: boolean;
|
|
20
|
+
/** Multi-platform targets. e.g. ["linux/amd64", "linux/arm64"] */
|
|
21
|
+
platforms?: string[];
|
|
22
|
+
/** Runner label. Default: "ubuntu-latest" */
|
|
23
|
+
runsOn?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const DockerBuild = Composite<DockerBuildProps>((props) => {
|
|
27
|
+
const {
|
|
28
|
+
tag = "${{ github.sha }}",
|
|
29
|
+
dockerfile = "Dockerfile",
|
|
30
|
+
context = ".",
|
|
31
|
+
registry = "ghcr.io",
|
|
32
|
+
imageName = "ghcr.io/${{ github.repository }}",
|
|
33
|
+
tagLatest = true,
|
|
34
|
+
buildArgs,
|
|
35
|
+
push = true,
|
|
36
|
+
platforms,
|
|
37
|
+
runsOn = "ubuntu-latest",
|
|
38
|
+
} = props;
|
|
39
|
+
|
|
40
|
+
const { createProperty, createResource } = require("@intentius/chant/runtime");
|
|
41
|
+
const StepClass = createProperty("GitHub::Actions::Step", "github");
|
|
42
|
+
const JobClass = createResource("GitHub::Actions::Job", "github", {});
|
|
43
|
+
const WorkflowClass = createResource("GitHub::Actions::Workflow", "github", {});
|
|
44
|
+
|
|
45
|
+
// ── Steps ──────────────────────────────────────────────────────────
|
|
46
|
+
const checkout = new StepClass({ name: "Checkout", uses: "actions/checkout@v4" });
|
|
47
|
+
|
|
48
|
+
const login = new StepClass({
|
|
49
|
+
name: "Log in to container registry",
|
|
50
|
+
uses: "docker/login-action@v3",
|
|
51
|
+
with: {
|
|
52
|
+
registry,
|
|
53
|
+
username: "${{ github.actor }}",
|
|
54
|
+
password: "${{ secrets.GITHUB_TOKEN }}",
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const setupBuildx = new StepClass({
|
|
59
|
+
name: "Set up Docker Buildx",
|
|
60
|
+
uses: "docker/setup-buildx-action@v3",
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Build tags for metadata action
|
|
64
|
+
const tags = [`${imageName}:${tag}`];
|
|
65
|
+
if (tagLatest) {
|
|
66
|
+
tags.push(`${imageName}:latest`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const metadata = new StepClass({
|
|
70
|
+
name: "Extract metadata",
|
|
71
|
+
id: "meta",
|
|
72
|
+
uses: "docker/metadata-action@v5",
|
|
73
|
+
with: {
|
|
74
|
+
images: imageName,
|
|
75
|
+
tags: tags.join("\n"),
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const buildPushWith: Record<string, string> = {
|
|
80
|
+
context,
|
|
81
|
+
file: dockerfile,
|
|
82
|
+
push: String(push),
|
|
83
|
+
tags: "${{ steps.meta.outputs.tags }}",
|
|
84
|
+
labels: "${{ steps.meta.outputs.labels }}",
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
if (platforms && platforms.length > 0) {
|
|
88
|
+
buildPushWith.platforms = platforms.join(",");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (buildArgs) {
|
|
92
|
+
buildPushWith["build-args"] = Object.entries(buildArgs)
|
|
93
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
94
|
+
.join("\n");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const buildPush = new StepClass({
|
|
98
|
+
name: "Build and push",
|
|
99
|
+
uses: "docker/build-push-action@v6",
|
|
100
|
+
with: buildPushWith,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const job = new JobClass({
|
|
104
|
+
"runs-on": runsOn,
|
|
105
|
+
steps: [checkout, login, setupBuildx, metadata, buildPush],
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const workflow = new WorkflowClass({
|
|
109
|
+
name: "Docker Build",
|
|
110
|
+
on: {
|
|
111
|
+
push: { branches: ["main"] },
|
|
112
|
+
},
|
|
113
|
+
permissions: {
|
|
114
|
+
contents: "read",
|
|
115
|
+
packages: "write",
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
return { workflow, job };
|
|
120
|
+
}, "DockerBuild");
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Composite } from "@intentius/chant";
|
|
2
|
+
|
|
3
|
+
export interface DownloadArtifactProps {
|
|
4
|
+
name?: string;
|
|
5
|
+
path?: string;
|
|
6
|
+
mergeMultiple?: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const DownloadArtifact = Composite<DownloadArtifactProps>((props) => {
|
|
10
|
+
const withObj: Record<string, string> = {};
|
|
11
|
+
if (props.name !== undefined) withObj.name = props.name;
|
|
12
|
+
if (props.path !== undefined) withObj.path = props.path;
|
|
13
|
+
if (props.mergeMultiple !== undefined) withObj["merge-multiple"] = String(props.mergeMultiple);
|
|
14
|
+
|
|
15
|
+
const { createProperty } = require("@intentius/chant/runtime");
|
|
16
|
+
const StepClass = createProperty("GitHub::Actions::Step", "github");
|
|
17
|
+
const step = new StepClass({
|
|
18
|
+
name: "Download Artifact",
|
|
19
|
+
uses: "actions/download-artifact@v4",
|
|
20
|
+
...(Object.keys(withObj).length > 0 ? { with: withObj } : {}),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return { step };
|
|
24
|
+
}, "DownloadArtifact");
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Composite } from "@intentius/chant";
|
|
2
|
+
|
|
3
|
+
export interface GoCIProps {
|
|
4
|
+
/** Go version. Default: "1.22" */
|
|
5
|
+
goVersion?: string;
|
|
6
|
+
/** Test command. Default: "go test ./... -v -race" */
|
|
7
|
+
testCommand?: string;
|
|
8
|
+
/** Build command. Default: "go build ./..." */
|
|
9
|
+
buildCommand?: string;
|
|
10
|
+
/** Lint command. Set to null to omit lint job. Default: "golangci-lint run" */
|
|
11
|
+
lintCommand?: string | null;
|
|
12
|
+
/** Runner label. Default: "ubuntu-latest" */
|
|
13
|
+
runsOn?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const GoCI = Composite<GoCIProps>((props) => {
|
|
17
|
+
const {
|
|
18
|
+
goVersion = "1.22",
|
|
19
|
+
testCommand = "go test ./... -v -race",
|
|
20
|
+
buildCommand = "go build ./...",
|
|
21
|
+
lintCommand = "golangci-lint run",
|
|
22
|
+
runsOn = "ubuntu-latest",
|
|
23
|
+
} = props;
|
|
24
|
+
|
|
25
|
+
const { createProperty, createResource } = require("@intentius/chant/runtime");
|
|
26
|
+
const StepClass = createProperty("GitHub::Actions::Step", "github");
|
|
27
|
+
const JobClass = createResource("GitHub::Actions::Job", "github", {});
|
|
28
|
+
const WorkflowClass = createResource("GitHub::Actions::Workflow", "github", {});
|
|
29
|
+
|
|
30
|
+
// ── Build job ──────────────────────────────────────────────────────
|
|
31
|
+
const buildJob = new JobClass({
|
|
32
|
+
"runs-on": runsOn,
|
|
33
|
+
steps: [
|
|
34
|
+
new StepClass({ name: "Checkout", uses: "actions/checkout@v4" }),
|
|
35
|
+
new StepClass({
|
|
36
|
+
name: "Setup Go",
|
|
37
|
+
uses: "actions/setup-go@v5",
|
|
38
|
+
with: { "go-version": goVersion },
|
|
39
|
+
}),
|
|
40
|
+
new StepClass({ name: "Build", run: buildCommand }),
|
|
41
|
+
],
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// ── Test job ───────────────────────────────────────────────────────
|
|
45
|
+
const testJob = new JobClass({
|
|
46
|
+
"runs-on": runsOn,
|
|
47
|
+
steps: [
|
|
48
|
+
new StepClass({ name: "Checkout", uses: "actions/checkout@v4" }),
|
|
49
|
+
new StepClass({
|
|
50
|
+
name: "Setup Go",
|
|
51
|
+
uses: "actions/setup-go@v5",
|
|
52
|
+
with: { "go-version": goVersion },
|
|
53
|
+
}),
|
|
54
|
+
new StepClass({ name: "Test", run: testCommand }),
|
|
55
|
+
],
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// ── Lint job (optional) ────────────────────────────────────────────
|
|
59
|
+
const lintJob =
|
|
60
|
+
lintCommand !== null
|
|
61
|
+
? new JobClass({
|
|
62
|
+
"runs-on": runsOn,
|
|
63
|
+
steps: [
|
|
64
|
+
new StepClass({ name: "Checkout", uses: "actions/checkout@v4" }),
|
|
65
|
+
new StepClass({
|
|
66
|
+
name: "Setup Go",
|
|
67
|
+
uses: "actions/setup-go@v5",
|
|
68
|
+
with: { "go-version": goVersion },
|
|
69
|
+
}),
|
|
70
|
+
new StepClass({
|
|
71
|
+
name: "Lint",
|
|
72
|
+
uses: "golangci/golangci-lint-action@v6",
|
|
73
|
+
with: { args: lintCommand },
|
|
74
|
+
}),
|
|
75
|
+
],
|
|
76
|
+
})
|
|
77
|
+
: undefined;
|
|
78
|
+
|
|
79
|
+
const workflow = new WorkflowClass({
|
|
80
|
+
name: "Go CI",
|
|
81
|
+
on: {
|
|
82
|
+
push: { branches: ["main"] },
|
|
83
|
+
pull_request: { branches: ["main"] },
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
if (lintJob) {
|
|
88
|
+
return { workflow, buildJob, testJob, lintJob };
|
|
89
|
+
}
|
|
90
|
+
return { workflow, buildJob, testJob } as any;
|
|
91
|
+
}, "GoCI");
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export { Checkout } from "./checkout";
|
|
2
|
+
export type { CheckoutProps } from "./checkout";
|
|
3
|
+
export { SetupNode } from "./setup-node";
|
|
4
|
+
export type { SetupNodeProps } from "./setup-node";
|
|
5
|
+
export { SetupGo } from "./setup-go";
|
|
6
|
+
export type { SetupGoProps } from "./setup-go";
|
|
7
|
+
export { SetupPython } from "./setup-python";
|
|
8
|
+
export type { SetupPythonProps } from "./setup-python";
|
|
9
|
+
export { CacheAction } from "./cache";
|
|
10
|
+
export type { CacheActionProps } from "./cache";
|
|
11
|
+
export { UploadArtifact } from "./upload-artifact";
|
|
12
|
+
export type { UploadArtifactProps } from "./upload-artifact";
|
|
13
|
+
export { DownloadArtifact } from "./download-artifact";
|
|
14
|
+
export type { DownloadArtifactProps } from "./download-artifact";
|
|
15
|
+
export { NodeCI } from "./node-ci";
|
|
16
|
+
export type { NodeCIProps } from "./node-ci";
|
|
17
|
+
export { NodePipeline, BunPipeline, PnpmPipeline, YarnPipeline } from "./node-pipeline";
|
|
18
|
+
export type { NodePipelineProps } from "./node-pipeline";
|
|
19
|
+
export { PythonCI } from "./python-ci";
|
|
20
|
+
export type { PythonCIProps } from "./python-ci";
|
|
21
|
+
export { DockerBuild } from "./docker-build";
|
|
22
|
+
export type { DockerBuildProps } from "./docker-build";
|
|
23
|
+
export { DeployEnvironment } from "./deploy-environment";
|
|
24
|
+
export type { DeployEnvironmentProps } from "./deploy-environment";
|
|
25
|
+
export { GoCI } from "./go-ci";
|
|
26
|
+
export type { GoCIProps } from "./go-ci";
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Composite } from "@intentius/chant";
|
|
2
|
+
|
|
3
|
+
export interface NodeCIProps {
|
|
4
|
+
nodeVersion?: string;
|
|
5
|
+
packageManager?: "npm" | "pnpm" | "yarn" | "bun";
|
|
6
|
+
buildScript?: string;
|
|
7
|
+
testScript?: string;
|
|
8
|
+
installCommand?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const NodeCI = Composite<NodeCIProps>((props) => {
|
|
12
|
+
const {
|
|
13
|
+
nodeVersion = "22",
|
|
14
|
+
packageManager = "npm",
|
|
15
|
+
buildScript = "build",
|
|
16
|
+
testScript = "test",
|
|
17
|
+
installCommand,
|
|
18
|
+
} = props;
|
|
19
|
+
|
|
20
|
+
const install = installCommand ?? (packageManager === "npm" ? "npm ci" : `${packageManager} install`);
|
|
21
|
+
const run = packageManager === "npm" ? "npm run" : packageManager;
|
|
22
|
+
|
|
23
|
+
const { createProperty, createResource } = require("@intentius/chant/runtime");
|
|
24
|
+
const StepClass = createProperty("GitHub::Actions::Step", "github");
|
|
25
|
+
const JobClass = createResource("GitHub::Actions::Job", "github", {});
|
|
26
|
+
const WorkflowClass = createResource("GitHub::Actions::Workflow", "github", {});
|
|
27
|
+
|
|
28
|
+
const checkoutStep = new StepClass({
|
|
29
|
+
name: "Checkout",
|
|
30
|
+
uses: "actions/checkout@v4",
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const setupNodeStep = new StepClass({
|
|
34
|
+
name: "Setup Node.js",
|
|
35
|
+
uses: "actions/setup-node@v4",
|
|
36
|
+
with: {
|
|
37
|
+
"node-version": nodeVersion,
|
|
38
|
+
cache: packageManager === "bun" ? undefined : packageManager,
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const installStep = new StepClass({
|
|
43
|
+
name: "Install dependencies",
|
|
44
|
+
run: install,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const buildStep = new StepClass({
|
|
48
|
+
name: "Build",
|
|
49
|
+
run: `${run} ${buildScript}`,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const testStep = new StepClass({
|
|
53
|
+
name: "Test",
|
|
54
|
+
run: `${run} ${testScript}`,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const job = new JobClass({
|
|
58
|
+
"runs-on": "ubuntu-latest",
|
|
59
|
+
steps: [checkoutStep, setupNodeStep, installStep, buildStep, testStep],
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const workflow = new WorkflowClass({
|
|
63
|
+
name: "CI",
|
|
64
|
+
on: {
|
|
65
|
+
push: { branches: ["main"] },
|
|
66
|
+
pull_request: { branches: ["main"] },
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
return { workflow, job };
|
|
71
|
+
}, "NodeCI");
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { Composite, withDefaults } from "@intentius/chant";
|
|
2
|
+
|
|
3
|
+
export interface NodePipelineProps {
|
|
4
|
+
/** Node.js version. Default: "22" */
|
|
5
|
+
nodeVersion?: string;
|
|
6
|
+
/** Package manager. Default: "npm" */
|
|
7
|
+
packageManager?: "npm" | "pnpm" | "yarn" | "bun";
|
|
8
|
+
/** Build script name. Default: "build" */
|
|
9
|
+
buildScript?: string;
|
|
10
|
+
/** Test script name. Default: "test" */
|
|
11
|
+
testScript?: string;
|
|
12
|
+
/** Override auto-detected install command */
|
|
13
|
+
installCommand?: string;
|
|
14
|
+
/** Build artifact paths. Default: ["dist/"] */
|
|
15
|
+
buildArtifactPaths?: string[];
|
|
16
|
+
/** Artifact name. Default: "build-output" */
|
|
17
|
+
artifactName?: string;
|
|
18
|
+
/** Artifact retention days. Default: 1 */
|
|
19
|
+
artifactRetentionDays?: number;
|
|
20
|
+
/** Runner label. Default: "ubuntu-latest" */
|
|
21
|
+
runsOn?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const cacheConfig = {
|
|
25
|
+
npm: {
|
|
26
|
+
cache: "npm",
|
|
27
|
+
installCmd: "npm ci",
|
|
28
|
+
runPrefix: "npm run",
|
|
29
|
+
setupAction: "actions/setup-node@v4",
|
|
30
|
+
},
|
|
31
|
+
pnpm: {
|
|
32
|
+
cache: "pnpm",
|
|
33
|
+
installCmd: "pnpm install --frozen-lockfile",
|
|
34
|
+
runPrefix: "pnpm run",
|
|
35
|
+
setupAction: "actions/setup-node@v4",
|
|
36
|
+
},
|
|
37
|
+
yarn: {
|
|
38
|
+
cache: "yarn",
|
|
39
|
+
installCmd: "yarn install --frozen-lockfile",
|
|
40
|
+
runPrefix: "yarn",
|
|
41
|
+
setupAction: "actions/setup-node@v4",
|
|
42
|
+
},
|
|
43
|
+
bun: {
|
|
44
|
+
cache: undefined,
|
|
45
|
+
installCmd: "bun install --frozen-lockfile",
|
|
46
|
+
runPrefix: "bun run",
|
|
47
|
+
setupAction: "oven-sh/setup-bun@v2",
|
|
48
|
+
},
|
|
49
|
+
} as const;
|
|
50
|
+
|
|
51
|
+
export const NodePipeline = Composite<NodePipelineProps>((props) => {
|
|
52
|
+
const {
|
|
53
|
+
nodeVersion = "22",
|
|
54
|
+
packageManager = "npm",
|
|
55
|
+
buildScript = "build",
|
|
56
|
+
testScript = "test",
|
|
57
|
+
installCommand,
|
|
58
|
+
buildArtifactPaths = ["dist/"],
|
|
59
|
+
artifactName = "build-output",
|
|
60
|
+
artifactRetentionDays = 1,
|
|
61
|
+
runsOn = "ubuntu-latest",
|
|
62
|
+
} = props;
|
|
63
|
+
|
|
64
|
+
const pm = cacheConfig[packageManager];
|
|
65
|
+
const install = installCommand ?? pm.installCmd;
|
|
66
|
+
const run = pm.runPrefix;
|
|
67
|
+
|
|
68
|
+
const { createProperty, createResource } = require("@intentius/chant/runtime");
|
|
69
|
+
const StepClass = createProperty("GitHub::Actions::Step", "github");
|
|
70
|
+
const JobClass = createResource("GitHub::Actions::Job", "github", {});
|
|
71
|
+
const WorkflowClass = createResource("GitHub::Actions::Workflow", "github", {});
|
|
72
|
+
|
|
73
|
+
const isBun = packageManager === "bun";
|
|
74
|
+
|
|
75
|
+
// ── Build job steps ────────────────────────────────────────────────
|
|
76
|
+
const buildCheckout = new StepClass({ name: "Checkout", uses: "actions/checkout@v4" });
|
|
77
|
+
|
|
78
|
+
const buildSetup = isBun
|
|
79
|
+
? new StepClass({ name: "Setup Bun", uses: "oven-sh/setup-bun@v2" })
|
|
80
|
+
: new StepClass({
|
|
81
|
+
name: "Setup Node.js",
|
|
82
|
+
uses: "actions/setup-node@v4",
|
|
83
|
+
with: { "node-version": nodeVersion, cache: pm.cache },
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const buildInstall = new StepClass({ name: "Install dependencies", run: install });
|
|
87
|
+
|
|
88
|
+
const buildRun = new StepClass({ name: "Build", run: `${run} ${buildScript}` });
|
|
89
|
+
|
|
90
|
+
const buildUpload = new StepClass({
|
|
91
|
+
name: "Upload build artifacts",
|
|
92
|
+
uses: "actions/upload-artifact@v4",
|
|
93
|
+
with: {
|
|
94
|
+
name: artifactName,
|
|
95
|
+
path: buildArtifactPaths.join("\n"),
|
|
96
|
+
"retention-days": String(artifactRetentionDays),
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const buildJob = new JobClass({
|
|
101
|
+
"runs-on": runsOn,
|
|
102
|
+
steps: [buildCheckout, buildSetup, buildInstall, buildRun, buildUpload],
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// ── Test job steps ─────────────────────────────────────────────────
|
|
106
|
+
const testCheckout = new StepClass({ name: "Checkout", uses: "actions/checkout@v4" });
|
|
107
|
+
|
|
108
|
+
const testSetup = isBun
|
|
109
|
+
? new StepClass({ name: "Setup Bun", uses: "oven-sh/setup-bun@v2" })
|
|
110
|
+
: new StepClass({
|
|
111
|
+
name: "Setup Node.js",
|
|
112
|
+
uses: "actions/setup-node@v4",
|
|
113
|
+
with: { "node-version": nodeVersion, cache: pm.cache },
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const testInstall = new StepClass({ name: "Install dependencies", run: install });
|
|
117
|
+
|
|
118
|
+
const testDownload = new StepClass({
|
|
119
|
+
name: "Download build artifacts",
|
|
120
|
+
uses: "actions/download-artifact@v4",
|
|
121
|
+
with: { name: artifactName },
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const testRun = new StepClass({ name: "Test", run: `${run} ${testScript}` });
|
|
125
|
+
|
|
126
|
+
const testJob = new JobClass({
|
|
127
|
+
"runs-on": runsOn,
|
|
128
|
+
needs: ["build"],
|
|
129
|
+
steps: [testCheckout, testSetup, testInstall, testDownload, testRun],
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// ── Workflow ───────────────────────────────────────────────────────
|
|
133
|
+
const workflow = new WorkflowClass({
|
|
134
|
+
name: "Node Pipeline",
|
|
135
|
+
on: {
|
|
136
|
+
push: { branches: ["main"] },
|
|
137
|
+
pull_request: { branches: ["main"] },
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
return { workflow, buildJob, testJob };
|
|
142
|
+
}, "NodePipeline");
|
|
143
|
+
|
|
144
|
+
/** NodePipeline preset for Bun projects. */
|
|
145
|
+
export const BunPipeline = withDefaults(NodePipeline, { packageManager: "bun" as const });
|
|
146
|
+
|
|
147
|
+
/** NodePipeline preset for pnpm projects. */
|
|
148
|
+
export const PnpmPipeline = withDefaults(NodePipeline, { packageManager: "pnpm" as const });
|
|
149
|
+
|
|
150
|
+
/** NodePipeline preset for Yarn projects. */
|
|
151
|
+
export const YarnPipeline = withDefaults(NodePipeline, { packageManager: "yarn" as const });
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Composite } from "@intentius/chant";
|
|
2
|
+
|
|
3
|
+
export interface PythonCIProps {
|
|
4
|
+
/** Python version. Default: "3.12" */
|
|
5
|
+
pythonVersion?: string;
|
|
6
|
+
/** Test command. Default: "pytest --junitxml=report.xml --cov" */
|
|
7
|
+
testCommand?: string;
|
|
8
|
+
/** Lint command. Set to null to omit lint job. Default: "ruff check ." */
|
|
9
|
+
lintCommand?: string | null;
|
|
10
|
+
/** Requirements file. Default: "requirements.txt" */
|
|
11
|
+
requirementsFile?: string;
|
|
12
|
+
/** Use poetry instead of pip. Default: false */
|
|
13
|
+
usePoetry?: boolean;
|
|
14
|
+
/** Runner label. Default: "ubuntu-latest" */
|
|
15
|
+
runsOn?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const PythonCI = Composite<PythonCIProps>((props) => {
|
|
19
|
+
const {
|
|
20
|
+
pythonVersion = "3.12",
|
|
21
|
+
testCommand = "pytest --junitxml=report.xml --cov",
|
|
22
|
+
lintCommand = "ruff check .",
|
|
23
|
+
requirementsFile = "requirements.txt",
|
|
24
|
+
usePoetry = false,
|
|
25
|
+
runsOn = "ubuntu-latest",
|
|
26
|
+
} = props;
|
|
27
|
+
|
|
28
|
+
const { createProperty, createResource } = require("@intentius/chant/runtime");
|
|
29
|
+
const StepClass = createProperty("GitHub::Actions::Step", "github");
|
|
30
|
+
const JobClass = createResource("GitHub::Actions::Job", "github", {});
|
|
31
|
+
const WorkflowClass = createResource("GitHub::Actions::Workflow", "github", {});
|
|
32
|
+
|
|
33
|
+
const cacheType = usePoetry ? "poetry" : "pip";
|
|
34
|
+
const installSteps = usePoetry
|
|
35
|
+
? [
|
|
36
|
+
new StepClass({ name: "Install Poetry", run: "pip install poetry" }),
|
|
37
|
+
new StepClass({ name: "Install dependencies", run: "poetry install" }),
|
|
38
|
+
]
|
|
39
|
+
: [
|
|
40
|
+
new StepClass({ name: "Install dependencies", run: `pip install -r ${requirementsFile}` }),
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
// ── Test job ───────────────────────────────────────────────────────
|
|
44
|
+
const testJob = new JobClass({
|
|
45
|
+
"runs-on": runsOn,
|
|
46
|
+
steps: [
|
|
47
|
+
new StepClass({ name: "Checkout", uses: "actions/checkout@v4" }),
|
|
48
|
+
new StepClass({
|
|
49
|
+
name: "Setup Python",
|
|
50
|
+
uses: "actions/setup-python@v5",
|
|
51
|
+
with: { "python-version": pythonVersion, cache: cacheType },
|
|
52
|
+
}),
|
|
53
|
+
...installSteps,
|
|
54
|
+
new StepClass({ name: "Test", run: testCommand }),
|
|
55
|
+
],
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// ── Lint job (optional) ────────────────────────────────────────────
|
|
59
|
+
const lintJob =
|
|
60
|
+
lintCommand !== null
|
|
61
|
+
? new JobClass({
|
|
62
|
+
"runs-on": runsOn,
|
|
63
|
+
steps: [
|
|
64
|
+
new StepClass({ name: "Checkout", uses: "actions/checkout@v4" }),
|
|
65
|
+
new StepClass({
|
|
66
|
+
name: "Setup Python",
|
|
67
|
+
uses: "actions/setup-python@v5",
|
|
68
|
+
with: { "python-version": pythonVersion, cache: cacheType },
|
|
69
|
+
}),
|
|
70
|
+
...installSteps.map((s: any) => {
|
|
71
|
+
// Create fresh step instances for the lint job
|
|
72
|
+
return new StepClass({ name: s.props.name, run: s.props.run });
|
|
73
|
+
}),
|
|
74
|
+
new StepClass({ name: "Lint", run: lintCommand }),
|
|
75
|
+
],
|
|
76
|
+
})
|
|
77
|
+
: undefined;
|
|
78
|
+
|
|
79
|
+
// ── Workflow ───────────────────────────────────────────────────────
|
|
80
|
+
const workflow = new WorkflowClass({
|
|
81
|
+
name: "Python CI",
|
|
82
|
+
on: {
|
|
83
|
+
push: { branches: ["main"] },
|
|
84
|
+
pull_request: { branches: ["main"] },
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
if (lintJob) {
|
|
89
|
+
return { workflow, testJob, lintJob };
|
|
90
|
+
}
|
|
91
|
+
return { workflow, testJob } as any;
|
|
92
|
+
}, "PythonCI");
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Composite } from "@intentius/chant";
|
|
2
|
+
|
|
3
|
+
export interface SetupGoProps {
|
|
4
|
+
goVersion?: string;
|
|
5
|
+
goVersionFile?: string;
|
|
6
|
+
cache?: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const SetupGo = Composite<SetupGoProps>((props) => {
|
|
10
|
+
const withObj: Record<string, string> = {};
|
|
11
|
+
if (props.goVersion !== undefined) withObj["go-version"] = props.goVersion;
|
|
12
|
+
if (props.goVersionFile !== undefined) withObj["go-version-file"] = props.goVersionFile;
|
|
13
|
+
if (props.cache !== undefined) withObj.cache = String(props.cache);
|
|
14
|
+
|
|
15
|
+
const { createProperty } = require("@intentius/chant/runtime");
|
|
16
|
+
const StepClass = createProperty("GitHub::Actions::Step", "github");
|
|
17
|
+
const step = new StepClass({
|
|
18
|
+
name: "Setup Go",
|
|
19
|
+
uses: "actions/setup-go@v5",
|
|
20
|
+
...(Object.keys(withObj).length > 0 ? { with: withObj } : {}),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return { step };
|
|
24
|
+
}, "SetupGo");
|