@xpertss/projen-types 0.0.1 → 0.0.3
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/.jsii +1083 -92
- package/API.md +7459 -4313
- package/README.md +127 -25
- package/lib/actions/action-build-workflow.d.ts +17 -0
- package/lib/actions/action-build-workflow.js +52 -0
- package/lib/actions/action-dogfood-workflow.d.ts +47 -0
- package/lib/actions/action-dogfood-workflow.js +84 -0
- package/lib/actions/action-sonar-workflow.d.ts +25 -0
- package/lib/actions/action-sonar-workflow.js +64 -0
- package/lib/actions/github-action-project.d.ts +60 -0
- package/lib/actions/github-action-project.js +157 -0
- package/lib/cdk/app-runtime-scaffold.js +1 -1
- package/lib/cdk/cdk-app-project.js +2 -4
- package/lib/cdk/cdk-infra-project.js +1 -1
- package/lib/cdk/cdk-typescript-base.js +16 -3
- package/lib/cdk/components/ecr-ecs-constructs.js +1 -1
- package/lib/cdk/components/edge-networking-constructs.js +1 -1
- package/lib/cdk/database-component.js +1 -1
- package/lib/cdk/options.d.ts +0 -2
- package/lib/cdk/options.js +1 -1
- package/lib/common/actions-allowlist-guard.d.ts +37 -0
- package/lib/common/actions-allowlist-guard.js +70 -0
- package/lib/common/internal-actions.d.ts +10 -0
- package/lib/common/internal-actions.js +33 -0
- package/lib/common/manual-deploy-workflow.d.ts +0 -2
- package/lib/common/manual-deploy-workflow.js +1 -12
- package/lib/common/projen-drift-check-workflow.d.ts +36 -0
- package/lib/common/projen-drift-check-workflow.js +77 -0
- package/lib/common/upgrade-workflow.js +6 -2
- package/lib/common/workflow-change-notice-workflow.d.ts +33 -0
- package/lib/common/workflow-change-notice-workflow.js +58 -0
- package/lib/index.d.ts +8 -0
- package/lib/index.js +9 -1
- package/lib/java/components/cdk-deploy-hook.js +1 -1
- package/lib/java/components/code-index-workflow.js +1 -1
- package/lib/java/components/docker-publish.js +1 -1
- package/lib/java/components/flyway-migration.js +1 -1
- package/lib/java/components/github-packages-publish.js +1 -1
- package/lib/java/components/maven-central-publish.js +1 -1
- package/lib/java/java-app-project.js +1 -1
- package/lib/java/java-library-project.js +1 -1
- package/lib/java/java-maven-base.js +21 -4
- package/lib/java/java-service-project.js +1 -1
- package/package.json +2 -2
- package/release-publishing.md +57 -66
- package/lib/common/drift-check.d.ts +0 -8
- package/lib/common/drift-check.js +0 -18
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Projen project types for CDK/TypeScript and Java/Maven projects.
|
|
4
4
|
|
|
5
|
-
Instead of hand-maintaining `pom.xml`, `cdk.json`, and GitHub workflows, you declare a project type in a `.projenrc.
|
|
5
|
+
Instead of hand-maintaining `pom.xml`, `cdk.json`, and GitHub workflows, you declare a project type in a plain-JavaScript `.projenrc.js` file and let [projen](https://github.com/projen/projen) generate (and keep up to date) the whole scaffold: build files, source skeletons, CI workflows, and deploy pipelines.
|
|
6
6
|
|
|
7
7
|
## Project types at a glance
|
|
8
8
|
|
|
@@ -13,12 +13,13 @@ Instead of hand-maintaining `pom.xml`, `cdk.json`, and GitHub workflows, you dec
|
|
|
13
13
|
| `JavaLibraryProject` | Reusable Java library | Maven Central | `build`, `upgrade` (nightly), `publish-maven-central`, `codeindex` |
|
|
14
14
|
| `JavaServiceProject` | Spring Boot service | Docker Hub | `build`, `upgrade` (nightly), `publish-docker`, `deploy-cdk` |
|
|
15
15
|
| `JavaAppProject` | GUI/TUI/CLI Java application | GitHub Packages | `build`, `upgrade` (nightly), `publish-ghpackages` |
|
|
16
|
+
| `GitHubActionProject` | Reusable GitHub Action or Workflow | GitHub Releases | `build`, `test-dogfood`, `sonar`, `release` |
|
|
16
17
|
|
|
17
18
|
Two foundation classes are also exported for advanced use: `CdkTypescriptProject` (shared CDK + TypeScript base for the CDK types) and `JavaMavenProject` (shared Maven base for the Java types).
|
|
18
19
|
|
|
19
20
|
All project types:
|
|
20
21
|
|
|
21
|
-
- run a **drift check** in PR builds - a job that re-runs projen and fails if generated files were hand-edited. Edit `.projenrc.
|
|
22
|
+
- run a **drift check** in PR builds - a job that re-runs projen and fails if generated files were hand-edited. Edit `.projenrc.js`, then run `npx projen`; never edit generated files directly.
|
|
22
23
|
- use the GitHub secret `PROJEN_GITHUB_TOKEN` (a fine-grained PAT) for projen's automation. Override with `gheTokenSecret`.
|
|
23
24
|
- make all publishing/deploying **manual** (workflow_dispatch) rather than on every merge.
|
|
24
25
|
|
|
@@ -32,13 +33,13 @@ git init
|
|
|
32
33
|
npm install -D projen constructs @xpertss/projen-types
|
|
33
34
|
```
|
|
34
35
|
|
|
35
|
-
Write a `.projenrc.
|
|
36
|
+
Write a `.projenrc.js` (see examples below), then bootstrap the project by running it directly - `npx projen` alone can't do this on a brand-new repo, since it only re-runs a `default` task that doesn't exist yet:
|
|
36
37
|
|
|
37
38
|
```bash
|
|
38
|
-
|
|
39
|
+
node .projenrc.js
|
|
39
40
|
```
|
|
40
41
|
|
|
41
|
-
Commit the result. From then on, every change to the scaffold goes through `.projenrc.
|
|
42
|
+
Commit the result. From then on, every change to the scaffold goes through `.projenrc.js` followed by plain `npx projen`.
|
|
42
43
|
|
|
43
44
|
The `name` option must match the `name` field in the project's `package.json` (for the CDK types) or the project name used by projen's `java.JavaProject` (for the Java types).
|
|
44
45
|
|
|
@@ -48,9 +49,9 @@ The `name` option must match the `name` field in the project's `package.json` (f
|
|
|
48
49
|
|
|
49
50
|
Pure infrastructure stacks with optional ECR/ECS and edge-networking constructs.
|
|
50
51
|
|
|
51
|
-
```
|
|
52
|
-
// .projenrc.
|
|
53
|
-
|
|
52
|
+
```javascript
|
|
53
|
+
// .projenrc.js
|
|
54
|
+
const { CdkInfraProject } = require('@xpertss/projen-types');
|
|
54
55
|
|
|
55
56
|
const project = new CdkInfraProject({
|
|
56
57
|
name: 'media-edge-infra',
|
|
@@ -79,9 +80,9 @@ You get:
|
|
|
79
80
|
|
|
80
81
|
`CdkInfraProject` plus application source, a database construct, and an app-level build workflow.
|
|
81
82
|
|
|
82
|
-
```
|
|
83
|
-
// .projenrc.
|
|
84
|
-
|
|
83
|
+
```javascript
|
|
84
|
+
// .projenrc.js
|
|
85
|
+
const { CdkAppProject } = require('@xpertss/projen-types');
|
|
85
86
|
|
|
86
87
|
const project = new CdkAppProject({
|
|
87
88
|
name: 'video-api',
|
|
@@ -105,9 +106,9 @@ Everything from `CdkInfraProject`, plus:
|
|
|
105
106
|
|
|
106
107
|
A reusable Java library published to Maven Central.
|
|
107
108
|
|
|
108
|
-
```
|
|
109
|
-
// .projenrc.
|
|
110
|
-
|
|
109
|
+
```javascript
|
|
110
|
+
// .projenrc.js
|
|
111
|
+
const { JavaLibraryProject } = require('@xpertss/projen-types');
|
|
111
112
|
|
|
112
113
|
const project = new JavaLibraryProject({
|
|
113
114
|
name: 'common-utils',
|
|
@@ -133,9 +134,9 @@ You get:
|
|
|
133
134
|
|
|
134
135
|
A Spring Boot service that publishes a Docker image and can trigger deploys in a companion CDK repo.
|
|
135
136
|
|
|
136
|
-
```
|
|
137
|
-
// .projenrc.
|
|
138
|
-
|
|
137
|
+
```javascript
|
|
138
|
+
// .projenrc.js
|
|
139
|
+
const { JavaServiceProject } = require('@xpertss/projen-types');
|
|
139
140
|
|
|
140
141
|
const project = new JavaServiceProject({
|
|
141
142
|
name: 'stream-processor',
|
|
@@ -160,9 +161,9 @@ You get (everything from `JavaMavenProject` - `pom.xml`, `build` + drift check,
|
|
|
160
161
|
|
|
161
162
|
A GUI/TUI/CLI Java application published to GitHub Packages only - no Maven Central, no Docker, no CDK deploy hook.
|
|
162
163
|
|
|
163
|
-
```
|
|
164
|
-
// .projenrc.
|
|
165
|
-
|
|
164
|
+
```javascript
|
|
165
|
+
// .projenrc.js
|
|
166
|
+
const { JavaAppProject } = require('@xpertss/projen-types');
|
|
166
167
|
|
|
167
168
|
const project = new JavaAppProject({
|
|
168
169
|
name: 'studio-cli',
|
|
@@ -176,6 +177,72 @@ project.synth();
|
|
|
176
177
|
|
|
177
178
|
You get everything from `JavaMavenProject`, plus `.github/workflows/publish-ghpackages.yml` - manual dispatch running `mvn -B deploy -DaltDeploymentRepository=github::<registry>`, authenticated with `GITHUB_TOKEN`. `ghPackagesRegistry` defaults to `https://maven.pkg.github.com/<repo>` derived from the repository URL.
|
|
178
179
|
|
|
180
|
+
### GitHubActionProject
|
|
181
|
+
|
|
182
|
+
A reusable GitHub Action or Workflow. This example scaffolds an action that stages a folder and, only if it changed, commits and pushes it.
|
|
183
|
+
|
|
184
|
+
```javascript
|
|
185
|
+
// .projenrc.js
|
|
186
|
+
const { GitHubActionProject } = require('@xpertss/projen-types');
|
|
187
|
+
|
|
188
|
+
const project = new GitHubActionProject({
|
|
189
|
+
name: 'auto-commit',
|
|
190
|
+
description: 'Stage a folder and, only if it changed, commit and push it',
|
|
191
|
+
sonarHostUrl: 'https://sonar.xpertss.org', // required, no default - your self-hosted SonarQube
|
|
192
|
+
dogfood: {
|
|
193
|
+
// Two scenario steps: the "changed" path and the "no-op" path are both
|
|
194
|
+
// load-bearing behavior for this action (a double-commit or a
|
|
195
|
+
// push-when-empty bug is the failure mode a hand-rolled inline-shell
|
|
196
|
+
// alternative is most likely to introduce).
|
|
197
|
+
scenario: [
|
|
198
|
+
{
|
|
199
|
+
name: 'Changed path',
|
|
200
|
+
fixtureSteps: [
|
|
201
|
+
'echo "$(date -u +%Y%m%dT%H%M%SZ)" >> test/fixtures/dogfood-state.txt',
|
|
202
|
+
],
|
|
203
|
+
inputs: {
|
|
204
|
+
commit_message: 'test: dogfood',
|
|
205
|
+
branches: 'test/dogfood',
|
|
206
|
+
},
|
|
207
|
+
assertions: [
|
|
208
|
+
// step id defaults to a slug of `name` - here "changed-path-0"
|
|
209
|
+
'[ "${{ steps.changed-path-0.outputs.committed }}" = "true" ]',
|
|
210
|
+
],
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
// No fixture change this time - nothing new to commit.
|
|
214
|
+
name: 'No-op path',
|
|
215
|
+
id: 'no-op-check', // pin an explicit id instead of relying on the default slug
|
|
216
|
+
inputs: {
|
|
217
|
+
commit_message: 'test: dogfood',
|
|
218
|
+
branches: 'test/dogfood',
|
|
219
|
+
},
|
|
220
|
+
assertions: [
|
|
221
|
+
'[ "${{ steps.no-op-check.outputs.committed }}" = "false" ]',
|
|
222
|
+
],
|
|
223
|
+
},
|
|
224
|
+
],
|
|
225
|
+
cleanup: [
|
|
226
|
+
'git push origin --delete test/dogfood || true',
|
|
227
|
+
],
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
project.synth();
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
You get:
|
|
235
|
+
|
|
236
|
+
- `action.yml` and `auto-commit.sh` are hand-written - this type only lints their content via `build.yml`'s shellcheck/yamllint/actionlint checks.
|
|
237
|
+
- `.github/workflows/build.yml` - lint gate: `apt`-installed shellcheck/yamllint plus a pinned, SHA-256-verified `actionlint` release binary. Gates `main` alongside `sonar.yml`.
|
|
238
|
+
- `.github/workflows/test-dogfood.yml` - runs the `dogfood.scenario` steps above against this repo's own `action.yml` (via `uses: .`), then the shared `cleanup`, on `workflow_dispatch`, every `pull_request`, and nightly.
|
|
239
|
+
- `.github/workflows/sonar.yml` - self-hosted SonarQube via the Scanner CLI, scanning `action.yml`/`.github/workflows/**`/`**/*.sh` explicitly.
|
|
240
|
+
- `.github/workflows/release.yml` - `feat:`/`fix:` commits on `main` bump the version, tag `vX.Y.Z`, and create a GitHub Release.
|
|
241
|
+
- `.github/workflows/projen-drift-check.yml`, `workflow-change-notice.yml`, `actions-allowlist-guard.yml` - drift detection, a change notice, and an action allow-list guard, always included.
|
|
242
|
+
- `package.json` (**private**, version source only), `.yamllint`, `LICENSE` (MIT by default), and a `README.md` template - all regenerated by `npx projen`.
|
|
243
|
+
|
|
244
|
+
Needs the same two secrets as everything else in this package: `PROJEN_GITHUB_TOKEN` (used for automated PR comments) and `SONAR_TOKEN` (the Sonar scan). Onboard a brand-new action repo following [Getting started](#getting-started), write the `.projenrc.js` above, then hand-write `action.yml`/`auto-commit.sh`/`test/fixtures/`.
|
|
245
|
+
|
|
179
246
|
## Common options
|
|
180
247
|
|
|
181
248
|
CDK project types (`CdkInfraProjectOptions` / `CdkAppProjectOptions`):
|
|
@@ -205,7 +272,7 @@ Java project types (`JavaLibraryProjectOptions` / `JavaServiceProjectOptions` /
|
|
|
205
272
|
|
|
206
273
|
`EnvironmentOptions` for deploy targets:
|
|
207
274
|
|
|
208
|
-
```
|
|
275
|
+
```text
|
|
209
276
|
interface EnvironmentOptions {
|
|
210
277
|
readonly name: string; // e.g. "dev", "stage", "prod"
|
|
211
278
|
readonly accountId?: string; // AWS account id (CDK deploys)
|
|
@@ -216,12 +283,44 @@ interface EnvironmentOptions {
|
|
|
216
283
|
|
|
217
284
|
Plain strings (`'dev'`) are shorthand for `{ name: 'dev' }`.
|
|
218
285
|
|
|
286
|
+
`GitHubActionProjectOptions`:
|
|
287
|
+
|
|
288
|
+
| Option | Default | Description |
|
|
289
|
+
| --- | --- | --- |
|
|
290
|
+
| `name` | - (required) | Project name |
|
|
291
|
+
| `description` | - | One-line description; used in the default README template and recorded in the private `package.json` |
|
|
292
|
+
| `sonarHostUrl` | - (required) | URL of your self-hosted SonarQube instance; must be reachable from github.com-hosted runners |
|
|
293
|
+
| `sonarTokenSecret` | `SONAR_TOKEN` | GitHub secret holding the Sonar token |
|
|
294
|
+
| `sonarPullRequestGate` | `true` | Whether `sonar.yml` also runs on `pull_request` as a pass/fail gate |
|
|
295
|
+
| `dogfood` | - (required) | `ActionDogfoodOptions` - the scenario that exercises the action end-to-end via `uses: .` |
|
|
296
|
+
| `license` | `MIT` | SPDX identifier for the generated `LICENSE` |
|
|
297
|
+
| `gheTokenSecret` | `PROJEN_GITHUB_TOKEN` | GitHub secret holding projen's PAT |
|
|
298
|
+
|
|
299
|
+
`ActionDogfoodOptions`/`ActionDogfoodStep` - the dogfood scenario (`test-dogfood.yml`):
|
|
300
|
+
|
|
301
|
+
```text
|
|
302
|
+
interface ActionDogfoodOptions {
|
|
303
|
+
readonly scenario: ActionDogfoodStep[]; // one or more, run in order - required
|
|
304
|
+
readonly cleanup: string[]; // shared, run once at the end with `if: always()` - required
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
interface ActionDogfoodStep {
|
|
308
|
+
readonly name: string; // labels this step-group's generated workflow steps
|
|
309
|
+
readonly id?: string; // step id for the `uses: .` call; default: a slug of `name`
|
|
310
|
+
readonly fixtureSteps?: string[]; // shell, before the invocation (default: none)
|
|
311
|
+
readonly inputs?: Record<string, string>; // `with:` for this invocation (default: none)
|
|
312
|
+
readonly assertions: string[]; // shell, after the invocation - required, job fails unless all exit 0
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Most actions need exactly one `scenario` step. Actions with a re-run/no-op/idempotency behavior to verify (e.g. `auto-commit`'s no-op-on-no-change path, `create-pull-request`'s reuse-the-PR path) declare two - the second typically omits `fixtureSteps` so its invocation sees no new state, and its assertion checks the opposite outcome of the first. Reference an invocation's own outputs from a later assertion via `${{ steps.<id>.outputs.<name> }}`, using either the default slug or an explicit `id`.
|
|
317
|
+
|
|
219
318
|
## Required GitHub secrets
|
|
220
319
|
|
|
221
320
|
| Secret | Used by | Notes |
|
|
222
321
|
| --- | --- | --- |
|
|
223
322
|
| `PROJEN_GITHUB_TOKEN` | all types | PAT for projen's self-mutation/automation; override via `gheTokenSecret` |
|
|
224
|
-
| `SONAR_TOKEN` | Java types with `sonarProjectKey` | SonarQube scan step in `build.yml` |
|
|
323
|
+
| `SONAR_TOKEN` | Java types with `sonarProjectKey`; `GitHubActionProject` | SonarQube scan step in `build.yml` / `sonar.yml`; override via `sonarTokenSecret` on `GitHubActionProject` |
|
|
225
324
|
| `DOCKER_USERNAME` / `DOCKER_PASSWORD` | `JavaServiceProject` | Docker image push |
|
|
226
325
|
| `MAVEN_GPG_PRIVATE_KEY`, `MAVEN_GPG_PASSPHRASE`, `MAVEN_CENTRAL_USERNAME`, `MAVEN_CENTRAL_PASSWORD` | `JavaLibraryProject` without `mavenCentralOidc` | Not needed with OIDC trusted publishing |
|
|
227
326
|
| (your Slack webhook secret) | CDK types with `slackWebhookSecret` | Deploy notifications |
|
|
@@ -242,12 +341,15 @@ The project types are composed from smaller components you can also attach to yo
|
|
|
242
341
|
| `FlywayMigration` | `JavaProject` | Flyway plugin/dependency + migrations directory |
|
|
243
342
|
| `CdkDeployHook` | `JavaProject` | Manual-dispatch workflow that triggers `deploy.yml` in a companion CDK repo |
|
|
244
343
|
| `CodeIndexWorkflow` | `JavaProject` | Code index generation on push to `main` |
|
|
344
|
+
| `ActionBuildWorkflow` | `GitHubProject` | The `lint` task (shellcheck/yamllint/pinned actionlint) + `build.yml` |
|
|
345
|
+
| `ActionDogfoodWorkflow` | `GitHubProject` | `test-dogfood.yml` from an `ActionDogfoodOptions` scenario |
|
|
346
|
+
| `ActionSonarWorkflow` | `GitHubProject` | `sonar.yml` (self-hosted SonarQube via the Scanner CLI) |
|
|
245
347
|
|
|
246
348
|
Example - adding a Docker publish to a plain projen `JavaProject`:
|
|
247
349
|
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
|
|
350
|
+
```javascript
|
|
351
|
+
const { java } = require('projen');
|
|
352
|
+
const { DockerPublish } = require('@xpertss/projen-types');
|
|
251
353
|
|
|
252
354
|
const project = new java.JavaProject({
|
|
253
355
|
name: 'my-service',
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Component, Task, github } from 'projen';
|
|
2
|
+
/**
|
|
3
|
+
* The AD-001 Layer-1 lint gate for a composite-action repo: shellcheck,
|
|
4
|
+
* yamllint, and a pinned `actionlint` release binary (verified by SHA-256,
|
|
5
|
+
* never a marketplace action - org policy). Creates a dedicated `lint` task
|
|
6
|
+
* (named to avoid colliding with projen's own reserved `build` task, which
|
|
7
|
+
* spawns the unrelated default/pre-compile/compile/post-compile/test/package
|
|
8
|
+
* chain - including `default`, i.e. re-running `.projenrc.ts`, which is not
|
|
9
|
+
* what this gate is for) and wraps it in a `TaskWorkflow` (`build.yml`)
|
|
10
|
+
* triggered on push-to-`main` and `pull_request`. The same task is reused by
|
|
11
|
+
* the release build job, so the lint commands exist in exactly one place.
|
|
12
|
+
*/
|
|
13
|
+
export declare class ActionBuildWorkflow extends Component {
|
|
14
|
+
readonly task: Task;
|
|
15
|
+
readonly workflow: github.TaskWorkflow;
|
|
16
|
+
constructor(scope: github.GitHubProject);
|
|
17
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ActionBuildWorkflow = void 0;
|
|
4
|
+
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
5
|
+
const projen_1 = require("projen");
|
|
6
|
+
// Pinned release + verified SHA-256 (linux_amd64) - upgrade is a reviewed
|
|
7
|
+
// diff of this constant, never a floating version (AD-001).
|
|
8
|
+
const ACTIONLINT_VERSION = '1.7.12';
|
|
9
|
+
const ACTIONLINT_SHA256 = '8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8';
|
|
10
|
+
/**
|
|
11
|
+
* The AD-001 Layer-1 lint gate for a composite-action repo: shellcheck,
|
|
12
|
+
* yamllint, and a pinned `actionlint` release binary (verified by SHA-256,
|
|
13
|
+
* never a marketplace action - org policy). Creates a dedicated `lint` task
|
|
14
|
+
* (named to avoid colliding with projen's own reserved `build` task, which
|
|
15
|
+
* spawns the unrelated default/pre-compile/compile/post-compile/test/package
|
|
16
|
+
* chain - including `default`, i.e. re-running `.projenrc.ts`, which is not
|
|
17
|
+
* what this gate is for) and wraps it in a `TaskWorkflow` (`build.yml`)
|
|
18
|
+
* triggered on push-to-`main` and `pull_request`. The same task is reused by
|
|
19
|
+
* the release build job, so the lint commands exist in exactly one place.
|
|
20
|
+
*/
|
|
21
|
+
class ActionBuildWorkflow extends projen_1.Component {
|
|
22
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "@xpertss/projen-types.ActionBuildWorkflow", version: "0.0.3" };
|
|
23
|
+
task;
|
|
24
|
+
workflow;
|
|
25
|
+
constructor(scope) {
|
|
26
|
+
super(scope, 'ActionBuildWorkflow');
|
|
27
|
+
const gh = scope.github;
|
|
28
|
+
if (!gh) {
|
|
29
|
+
throw new Error('ActionBuildWorkflow requires GitHub integration to be enabled');
|
|
30
|
+
}
|
|
31
|
+
this.task = scope.addTask('lint', {
|
|
32
|
+
description: 'Lint the action (shellcheck, yamllint, actionlint)',
|
|
33
|
+
});
|
|
34
|
+
this.task.exec('sudo apt-get update -y && sudo apt-get install -y shellcheck yamllint');
|
|
35
|
+
this.task.exec(`curl -fsSL -o /tmp/actionlint.tar.gz "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"`);
|
|
36
|
+
this.task.exec(`echo "${ACTIONLINT_SHA256} /tmp/actionlint.tar.gz" | sha256sum -c -`);
|
|
37
|
+
this.task.exec('tar -xzf /tmp/actionlint.tar.gz -C /tmp actionlint');
|
|
38
|
+
this.task.exec('find . -path ./node_modules -prune -o -name "*.sh" -print0 | xargs -0 -r shellcheck');
|
|
39
|
+
this.task.exec('yamllint -c .yamllint action.yml .github/workflows/*.yml');
|
|
40
|
+
this.task.exec('/tmp/actionlint action.yml .github/workflows/*.yml');
|
|
41
|
+
this.workflow = new projen_1.github.TaskWorkflow(gh, {
|
|
42
|
+
name: 'build',
|
|
43
|
+
jobId: 'build',
|
|
44
|
+
task: this.task,
|
|
45
|
+
triggers: { push: { branches: ['main'] }, pullRequest: {} },
|
|
46
|
+
permissions: { contents: projen_1.github.workflows.JobPermission.READ },
|
|
47
|
+
preBuildSteps: [{ name: 'Install dependencies', run: 'npm ci' }],
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.ActionBuildWorkflow = ActionBuildWorkflow;
|
|
52
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWN0aW9uLWJ1aWxkLXdvcmtmbG93LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FjdGlvbnMvYWN0aW9uLWJ1aWxkLXdvcmtmbG93LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxtQ0FBaUQ7QUFFakQsMEVBQTBFO0FBQzFFLDREQUE0RDtBQUM1RCxNQUFNLGtCQUFrQixHQUFHLFFBQVEsQ0FBQztBQUNwQyxNQUFNLGlCQUFpQixHQUNyQixrRUFBa0UsQ0FBQztBQUVyRTs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBYSxtQkFBb0IsU0FBUSxrQkFBUzs7SUFDaEMsSUFBSSxDQUFPO0lBQ1gsUUFBUSxDQUFzQjtJQUU5QyxZQUFZLEtBQTJCO1FBQ3JDLEtBQUssQ0FBQyxLQUFLLEVBQUUscUJBQXFCLENBQUMsQ0FBQztRQUVwQyxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNSLE1BQU0sSUFBSSxLQUFLLENBQ2IsK0RBQStELENBQ2hFLENBQUM7UUFDSixDQUFDO1FBRUQsSUFBSSxDQUFDLElBQUksR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRTtZQUNoQyxXQUFXLEVBQUUsb0RBQW9EO1NBQ2xFLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUNaLHVFQUF1RSxDQUN4RSxDQUFDO1FBQ0YsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQ1osZ0dBQWdHLGtCQUFrQixlQUFlLGtCQUFrQixzQkFBc0IsQ0FDMUssQ0FBQztRQUNGLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUNaLFNBQVMsaUJBQWlCLDRDQUE0QyxDQUN2RSxDQUFDO1FBQ0YsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsb0RBQW9ELENBQUMsQ0FBQztRQUNyRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FDWixxRkFBcUYsQ0FDdEYsQ0FBQztRQUNGLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLDBEQUEwRCxDQUFDLENBQUM7UUFDM0UsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsb0RBQW9ELENBQUMsQ0FBQztRQUVyRSxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksZUFBTSxDQUFDLFlBQVksQ0FBQyxFQUFFLEVBQUU7WUFDMUMsSUFBSSxFQUFFLE9BQU87WUFDYixLQUFLLEVBQUUsT0FBTztZQUNkLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSTtZQUNmLFFBQVEsRUFBRSxFQUFFLElBQUksRUFBRSxFQUFFLFFBQVEsRUFBRSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsV0FBVyxFQUFFLEVBQUUsRUFBRTtZQUMzRCxXQUFXLEVBQUUsRUFBRSxRQUFRLEVBQUUsZUFBTSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFO1lBQzlELGFBQWEsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLHNCQUFzQixFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsQ0FBQztTQUNqRSxDQUFDLENBQUM7SUFDTCxDQUFDOztBQXpDSCxrREEwQ0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIFRhc2ssIGdpdGh1YiB9IGZyb20gJ3Byb2plbic7XG5cbi8vIFBpbm5lZCByZWxlYXNlICsgdmVyaWZpZWQgU0hBLTI1NiAobGludXhfYW1kNjQpIC0gdXBncmFkZSBpcyBhIHJldmlld2VkXG4vLyBkaWZmIG9mIHRoaXMgY29uc3RhbnQsIG5ldmVyIGEgZmxvYXRpbmcgdmVyc2lvbiAoQUQtMDAxKS5cbmNvbnN0IEFDVElPTkxJTlRfVkVSU0lPTiA9ICcxLjcuMTInO1xuY29uc3QgQUNUSU9OTElOVF9TSEEyNTYgPVxuICAnOGFjYThkYjk2ZjFiOTQ3NzBmMWIwZDcyYjZkZGRjYjFlYmI4MTIzY2IzNzEyNTMwYjA4Y2MzODdiMzQ5YTNkOCc7XG5cbi8qKlxuICogVGhlIEFELTAwMSBMYXllci0xIGxpbnQgZ2F0ZSBmb3IgYSBjb21wb3NpdGUtYWN0aW9uIHJlcG86IHNoZWxsY2hlY2ssXG4gKiB5YW1sbGludCwgYW5kIGEgcGlubmVkIGBhY3Rpb25saW50YCByZWxlYXNlIGJpbmFyeSAodmVyaWZpZWQgYnkgU0hBLTI1NixcbiAqIG5ldmVyIGEgbWFya2V0cGxhY2UgYWN0aW9uIC0gb3JnIHBvbGljeSkuIENyZWF0ZXMgYSBkZWRpY2F0ZWQgYGxpbnRgIHRhc2tcbiAqIChuYW1lZCB0byBhdm9pZCBjb2xsaWRpbmcgd2l0aCBwcm9qZW4ncyBvd24gcmVzZXJ2ZWQgYGJ1aWxkYCB0YXNrLCB3aGljaFxuICogc3Bhd25zIHRoZSB1bnJlbGF0ZWQgZGVmYXVsdC9wcmUtY29tcGlsZS9jb21waWxlL3Bvc3QtY29tcGlsZS90ZXN0L3BhY2thZ2VcbiAqIGNoYWluIC0gaW5jbHVkaW5nIGBkZWZhdWx0YCwgaS5lLiByZS1ydW5uaW5nIGAucHJvamVucmMudHNgLCB3aGljaCBpcyBub3RcbiAqIHdoYXQgdGhpcyBnYXRlIGlzIGZvcikgYW5kIHdyYXBzIGl0IGluIGEgYFRhc2tXb3JrZmxvd2AgKGBidWlsZC55bWxgKVxuICogdHJpZ2dlcmVkIG9uIHB1c2gtdG8tYG1haW5gIGFuZCBgcHVsbF9yZXF1ZXN0YC4gVGhlIHNhbWUgdGFzayBpcyByZXVzZWQgYnlcbiAqIHRoZSByZWxlYXNlIGJ1aWxkIGpvYiwgc28gdGhlIGxpbnQgY29tbWFuZHMgZXhpc3QgaW4gZXhhY3RseSBvbmUgcGxhY2UuXG4gKi9cbmV4cG9ydCBjbGFzcyBBY3Rpb25CdWlsZFdvcmtmbG93IGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgcHVibGljIHJlYWRvbmx5IHRhc2s6IFRhc2s7XG4gIHB1YmxpYyByZWFkb25seSB3b3JrZmxvdzogZ2l0aHViLlRhc2tXb3JrZmxvdztcblxuICBjb25zdHJ1Y3RvcihzY29wZTogZ2l0aHViLkdpdEh1YlByb2plY3QpIHtcbiAgICBzdXBlcihzY29wZSwgJ0FjdGlvbkJ1aWxkV29ya2Zsb3cnKTtcblxuICAgIGNvbnN0IGdoID0gc2NvcGUuZ2l0aHViO1xuICAgIGlmICghZ2gpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ0FjdGlvbkJ1aWxkV29ya2Zsb3cgcmVxdWlyZXMgR2l0SHViIGludGVncmF0aW9uIHRvIGJlIGVuYWJsZWQnLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLnRhc2sgPSBzY29wZS5hZGRUYXNrKCdsaW50Jywge1xuICAgICAgZGVzY3JpcHRpb246ICdMaW50IHRoZSBhY3Rpb24gKHNoZWxsY2hlY2ssIHlhbWxsaW50LCBhY3Rpb25saW50KScsXG4gICAgfSk7XG4gICAgdGhpcy50YXNrLmV4ZWMoXG4gICAgICAnc3VkbyBhcHQtZ2V0IHVwZGF0ZSAteSAmJiBzdWRvIGFwdC1nZXQgaW5zdGFsbCAteSBzaGVsbGNoZWNrIHlhbWxsaW50JyxcbiAgICApO1xuICAgIHRoaXMudGFzay5leGVjKFxuICAgICAgYGN1cmwgLWZzU0wgLW8gL3RtcC9hY3Rpb25saW50LnRhci5neiBcImh0dHBzOi8vZ2l0aHViLmNvbS9yaHlzZC9hY3Rpb25saW50L3JlbGVhc2VzL2Rvd25sb2FkL3Yke0FDVElPTkxJTlRfVkVSU0lPTn0vYWN0aW9ubGludF8ke0FDVElPTkxJTlRfVkVSU0lPTn1fbGludXhfYW1kNjQudGFyLmd6XCJgLFxuICAgICk7XG4gICAgdGhpcy50YXNrLmV4ZWMoXG4gICAgICBgZWNobyBcIiR7QUNUSU9OTElOVF9TSEEyNTZ9ICAvdG1wL2FjdGlvbmxpbnQudGFyLmd6XCIgfCBzaGEyNTZzdW0gLWMgLWAsXG4gICAgKTtcbiAgICB0aGlzLnRhc2suZXhlYygndGFyIC14emYgL3RtcC9hY3Rpb25saW50LnRhci5neiAtQyAvdG1wIGFjdGlvbmxpbnQnKTtcbiAgICB0aGlzLnRhc2suZXhlYyhcbiAgICAgICdmaW5kIC4gLXBhdGggLi9ub2RlX21vZHVsZXMgLXBydW5lIC1vIC1uYW1lIFwiKi5zaFwiIC1wcmludDAgfCB4YXJncyAtMCAtciBzaGVsbGNoZWNrJyxcbiAgICApO1xuICAgIHRoaXMudGFzay5leGVjKCd5YW1sbGludCAtYyAueWFtbGxpbnQgYWN0aW9uLnltbCAuZ2l0aHViL3dvcmtmbG93cy8qLnltbCcpO1xuICAgIHRoaXMudGFzay5leGVjKCcvdG1wL2FjdGlvbmxpbnQgYWN0aW9uLnltbCAuZ2l0aHViL3dvcmtmbG93cy8qLnltbCcpO1xuXG4gICAgdGhpcy53b3JrZmxvdyA9IG5ldyBnaXRodWIuVGFza1dvcmtmbG93KGdoLCB7XG4gICAgICBuYW1lOiAnYnVpbGQnLFxuICAgICAgam9iSWQ6ICdidWlsZCcsXG4gICAgICB0YXNrOiB0aGlzLnRhc2ssXG4gICAgICB0cmlnZ2VyczogeyBwdXNoOiB7IGJyYW5jaGVzOiBbJ21haW4nXSB9LCBwdWxsUmVxdWVzdDoge30gfSxcbiAgICAgIHBlcm1pc3Npb25zOiB7IGNvbnRlbnRzOiBnaXRodWIud29ya2Zsb3dzLkpvYlBlcm1pc3Npb24uUkVBRCB9LFxuICAgICAgcHJlQnVpbGRTdGVwczogW3sgbmFtZTogJ0luc3RhbGwgZGVwZW5kZW5jaWVzJywgcnVuOiAnbnBtIGNpJyB9XSxcbiAgICB9KTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Component, github } from 'projen';
|
|
2
|
+
/**
|
|
3
|
+
* One invocation of the action within the dogfood scenario: optional fixture
|
|
4
|
+
* setup, the `uses: .` call with this step's inputs, then this step's
|
|
5
|
+
* assertions. Most actions need exactly one; actions with a re-run/no-op
|
|
6
|
+
* behavior to verify (e.g. F006's reuse-the-PR path, F007's no-op-commit
|
|
7
|
+
* path) declare two.
|
|
8
|
+
*/
|
|
9
|
+
export interface ActionDogfoodStep {
|
|
10
|
+
/** Label used to name this step-group's generated workflow steps. */
|
|
11
|
+
readonly name: string;
|
|
12
|
+
/**
|
|
13
|
+
* Step id for the `uses: .` invocation, so a later assertion can
|
|
14
|
+
* reference this step's outputs via `${{ steps.<id>.outputs.<name> }}`.
|
|
15
|
+
* @default - a slug derived from `name`, disambiguated by position
|
|
16
|
+
*/
|
|
17
|
+
readonly id?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Shell steps executed before this invocation, to produce or alter
|
|
20
|
+
* fixture state.
|
|
21
|
+
* @default []
|
|
22
|
+
*/
|
|
23
|
+
readonly fixtureSteps?: string[];
|
|
24
|
+
/**
|
|
25
|
+
* `with:` inputs for this invocation's local `uses: .` call.
|
|
26
|
+
* @default {}
|
|
27
|
+
*/
|
|
28
|
+
readonly inputs?: Record<string, string>;
|
|
29
|
+
/** Shell assertions after this invocation - the job fails unless every one exits 0. */
|
|
30
|
+
readonly assertions: string[];
|
|
31
|
+
}
|
|
32
|
+
export interface ActionDogfoodOptions {
|
|
33
|
+
/** One or more scenario steps, run in order, in the dogfood job. */
|
|
34
|
+
readonly scenario: ActionDogfoodStep[];
|
|
35
|
+
/** Shell cleanup, run once at the end with `if: always()`, so repeated runs start clean. */
|
|
36
|
+
readonly cleanup: string[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Per AD-001's dogfood test: the composite action is run **against this
|
|
40
|
+
* repo**, end-to-end, via a local `uses: .` reference - no external harness.
|
|
41
|
+
* Builds `test-dogfood.yml` from an ordered `scenario` of invocation steps
|
|
42
|
+
* (see `ActionDogfoodStep`) followed by a shared cleanup step.
|
|
43
|
+
*/
|
|
44
|
+
export declare class ActionDogfoodWorkflow extends Component {
|
|
45
|
+
readonly workflow: github.GithubWorkflow;
|
|
46
|
+
constructor(scope: github.GitHubProject, options: ActionDogfoodOptions);
|
|
47
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ActionDogfoodWorkflow = void 0;
|
|
4
|
+
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
5
|
+
const projen_1 = require("projen");
|
|
6
|
+
// Nightly environment-regression canary (AD-001/F006): re-runs the same
|
|
7
|
+
// scenario against settled `main` in today's runner image, independent of
|
|
8
|
+
// the pull_request gate. Quiet UTC hour; a component constant, not a
|
|
9
|
+
// project option - upgrading it is a reviewed diff.
|
|
10
|
+
const NIGHTLY_DOGFOOD_SCHEDULE = '17 3 * * *';
|
|
11
|
+
// Lowercase, non-alphanumerics collapsed to a single `-`, trimmed - then
|
|
12
|
+
// disambiguated by position so two steps sharing a name (or an unnamed
|
|
13
|
+
// slug, e.g. punctuation-only) never collide.
|
|
14
|
+
function slug(name, index) {
|
|
15
|
+
const base = name
|
|
16
|
+
.toLowerCase()
|
|
17
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
18
|
+
.replace(/^-+|-+$/g, '');
|
|
19
|
+
return `${base || 'step'}-${index}`;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Per AD-001's dogfood test: the composite action is run **against this
|
|
23
|
+
* repo**, end-to-end, via a local `uses: .` reference - no external harness.
|
|
24
|
+
* Builds `test-dogfood.yml` from an ordered `scenario` of invocation steps
|
|
25
|
+
* (see `ActionDogfoodStep`) followed by a shared cleanup step.
|
|
26
|
+
*/
|
|
27
|
+
class ActionDogfoodWorkflow extends projen_1.Component {
|
|
28
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "@xpertss/projen-types.ActionDogfoodWorkflow", version: "0.0.3" };
|
|
29
|
+
workflow;
|
|
30
|
+
constructor(scope, options) {
|
|
31
|
+
super(scope, 'ActionDogfoodWorkflow');
|
|
32
|
+
if (!options.scenario || options.scenario.length === 0) {
|
|
33
|
+
throw new Error('ActionDogfoodWorkflow requires at least one dogfood.scenario step');
|
|
34
|
+
}
|
|
35
|
+
if (!options.cleanup || options.cleanup.length === 0) {
|
|
36
|
+
throw new Error('ActionDogfoodWorkflow requires dogfood.cleanup');
|
|
37
|
+
}
|
|
38
|
+
const gh = scope.github;
|
|
39
|
+
if (!gh) {
|
|
40
|
+
throw new Error('ActionDogfoodWorkflow requires GitHub integration to be enabled');
|
|
41
|
+
}
|
|
42
|
+
const steps = [projen_1.github.WorkflowSteps.checkout()];
|
|
43
|
+
options.scenario.forEach((step, index) => {
|
|
44
|
+
if (step.fixtureSteps && step.fixtureSteps.length > 0) {
|
|
45
|
+
steps.push({
|
|
46
|
+
name: `${step.name}: fixture`,
|
|
47
|
+
run: step.fixtureSteps.join('\n'),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const hasInputs = step.inputs && Object.keys(step.inputs).length > 0;
|
|
51
|
+
steps.push({
|
|
52
|
+
id: step.id ?? slug(step.name, index),
|
|
53
|
+
name: `${step.name}: run the action`,
|
|
54
|
+
uses: '.',
|
|
55
|
+
...(hasInputs ? { with: step.inputs } : {}),
|
|
56
|
+
});
|
|
57
|
+
steps.push({
|
|
58
|
+
name: `${step.name}: assert`,
|
|
59
|
+
run: step.assertions.join('\n'),
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
steps.push({
|
|
63
|
+
name: 'Cleanup',
|
|
64
|
+
if: 'always()',
|
|
65
|
+
run: options.cleanup.join('\n'),
|
|
66
|
+
});
|
|
67
|
+
this.workflow = new projen_1.github.GithubWorkflow(gh, 'test-dogfood');
|
|
68
|
+
this.workflow.on({
|
|
69
|
+
workflowDispatch: {},
|
|
70
|
+
pullRequest: { branches: ['main'] },
|
|
71
|
+
schedule: [{ cron: NIGHTLY_DOGFOOD_SCHEDULE }],
|
|
72
|
+
});
|
|
73
|
+
this.workflow.addJob('dogfood', {
|
|
74
|
+
runsOn: ['ubuntu-latest'],
|
|
75
|
+
permissions: {
|
|
76
|
+
contents: projen_1.github.workflows.JobPermission.WRITE,
|
|
77
|
+
pullRequests: projen_1.github.workflows.JobPermission.WRITE,
|
|
78
|
+
},
|
|
79
|
+
steps,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
exports.ActionDogfoodWorkflow = ActionDogfoodWorkflow;
|
|
84
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWN0aW9uLWRvZ2Zvb2Qtd29ya2Zsb3cuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYWN0aW9ucy9hY3Rpb24tZG9nZm9vZC13b3JrZmxvdy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsbUNBQTJDO0FBRTNDLHdFQUF3RTtBQUN4RSwwRUFBMEU7QUFDMUUscUVBQXFFO0FBQ3JFLG9EQUFvRDtBQUNwRCxNQUFNLHdCQUF3QixHQUFHLFlBQVksQ0FBQztBQXFDOUMseUVBQXlFO0FBQ3pFLHVFQUF1RTtBQUN2RSw4Q0FBOEM7QUFDOUMsU0FBUyxJQUFJLENBQUMsSUFBWSxFQUFFLEtBQWE7SUFDdkMsTUFBTSxJQUFJLEdBQUcsSUFBSTtTQUNkLFdBQVcsRUFBRTtTQUNiLE9BQU8sQ0FBQyxhQUFhLEVBQUUsR0FBRyxDQUFDO1NBQzNCLE9BQU8sQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDM0IsT0FBTyxHQUFHLElBQUksSUFBSSxNQUFNLElBQUksS0FBSyxFQUFFLENBQUM7QUFDdEMsQ0FBQztBQVVEOzs7OztHQUtHO0FBQ0gsTUFBYSxxQkFBc0IsU0FBUSxrQkFBUzs7SUFDbEMsUUFBUSxDQUF3QjtJQUVoRCxZQUFZLEtBQTJCLEVBQUUsT0FBNkI7UUFDcEUsS0FBSyxDQUFDLEtBQUssRUFBRSx1QkFBdUIsQ0FBQyxDQUFDO1FBRXRDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3ZELE1BQU0sSUFBSSxLQUFLLENBQ2IsbUVBQW1FLENBQ3BFLENBQUM7UUFDSixDQUFDO1FBQ0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDckQsTUFBTSxJQUFJLEtBQUssQ0FBQyxnREFBZ0QsQ0FBQyxDQUFDO1FBQ3BFLENBQUM7UUFFRCxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNSLE1BQU0sSUFBSSxLQUFLLENBQ2IsaUVBQWlFLENBQ2xFLENBQUM7UUFDSixDQUFDO1FBRUQsTUFBTSxLQUFLLEdBQStCLENBQUMsZUFBTSxDQUFDLGFBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO1FBRTVFLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFO1lBQ3ZDLElBQUksSUFBSSxDQUFDLFlBQVksSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDdEQsS0FBSyxDQUFDLElBQUksQ0FBQztvQkFDVCxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsSUFBSSxXQUFXO29CQUM3QixHQUFHLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO2lCQUNsQyxDQUFDLENBQUM7WUFDTCxDQUFDO1lBRUQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLE1BQU0sSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1lBQ3JFLEtBQUssQ0FBQyxJQUFJLENBQUM7Z0JBQ1QsRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDO2dCQUNyQyxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsSUFBSSxrQkFBa0I7Z0JBQ3BDLElBQUksRUFBRSxHQUFHO2dCQUNULEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2FBQzVDLENBQUMsQ0FBQztZQUVILEtBQUssQ0FBQyxJQUFJLENBQUM7Z0JBQ1QsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLElBQUksVUFBVTtnQkFDNUIsR0FBRyxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQzthQUNoQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztRQUVILEtBQUssQ0FBQyxJQUFJLENBQUM7WUFDVCxJQUFJLEVBQUUsU0FBUztZQUNmLEVBQUUsRUFBRSxVQUFVO1lBQ2QsR0FBRyxFQUFFLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztTQUNoQyxDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksZUFBTSxDQUFDLGNBQWMsQ0FBQyxFQUFFLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDOUQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFDZixnQkFBZ0IsRUFBRSxFQUFFO1lBQ3BCLFdBQVcsRUFBRSxFQUFFLFFBQVEsRUFBRSxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQ25DLFFBQVEsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLHdCQUF3QixFQUFFLENBQUM7U0FDL0MsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFO1lBQzlCLE1BQU0sRUFBRSxDQUFDLGVBQWUsQ0FBQztZQUN6QixXQUFXLEVBQUU7Z0JBQ1gsUUFBUSxFQUFFLGVBQU0sQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLEtBQUs7Z0JBQzlDLFlBQVksRUFBRSxlQUFNLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxLQUFLO2FBQ25EO1lBQ0QsS0FBSztTQUNOLENBQUMsQ0FBQztJQUNMLENBQUM7O0FBbEVILHNEQW1FQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgZ2l0aHViIH0gZnJvbSAncHJvamVuJztcblxuLy8gTmlnaHRseSBlbnZpcm9ubWVudC1yZWdyZXNzaW9uIGNhbmFyeSAoQUQtMDAxL0YwMDYpOiByZS1ydW5zIHRoZSBzYW1lXG4vLyBzY2VuYXJpbyBhZ2FpbnN0IHNldHRsZWQgYG1haW5gIGluIHRvZGF5J3MgcnVubmVyIGltYWdlLCBpbmRlcGVuZGVudCBvZlxuLy8gdGhlIHB1bGxfcmVxdWVzdCBnYXRlLiBRdWlldCBVVEMgaG91cjsgYSBjb21wb25lbnQgY29uc3RhbnQsIG5vdCBhXG4vLyBwcm9qZWN0IG9wdGlvbiAtIHVwZ3JhZGluZyBpdCBpcyBhIHJldmlld2VkIGRpZmYuXG5jb25zdCBOSUdIVExZX0RPR0ZPT0RfU0NIRURVTEUgPSAnMTcgMyAqICogKic7XG5cbi8qKlxuICogT25lIGludm9jYXRpb24gb2YgdGhlIGFjdGlvbiB3aXRoaW4gdGhlIGRvZ2Zvb2Qgc2NlbmFyaW86IG9wdGlvbmFsIGZpeHR1cmVcbiAqIHNldHVwLCB0aGUgYHVzZXM6IC5gIGNhbGwgd2l0aCB0aGlzIHN0ZXAncyBpbnB1dHMsIHRoZW4gdGhpcyBzdGVwJ3NcbiAqIGFzc2VydGlvbnMuIE1vc3QgYWN0aW9ucyBuZWVkIGV4YWN0bHkgb25lOyBhY3Rpb25zIHdpdGggYSByZS1ydW4vbm8tb3BcbiAqIGJlaGF2aW9yIHRvIHZlcmlmeSAoZS5nLiBGMDA2J3MgcmV1c2UtdGhlLVBSIHBhdGgsIEYwMDcncyBuby1vcC1jb21taXRcbiAqIHBhdGgpIGRlY2xhcmUgdHdvLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFjdGlvbkRvZ2Zvb2RTdGVwIHtcbiAgLyoqIExhYmVsIHVzZWQgdG8gbmFtZSB0aGlzIHN0ZXAtZ3JvdXAncyBnZW5lcmF0ZWQgd29ya2Zsb3cgc3RlcHMuICovXG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogU3RlcCBpZCBmb3IgdGhlIGB1c2VzOiAuYCBpbnZvY2F0aW9uLCBzbyBhIGxhdGVyIGFzc2VydGlvbiBjYW5cbiAgICogcmVmZXJlbmNlIHRoaXMgc3RlcCdzIG91dHB1dHMgdmlhIGAke3sgc3RlcHMuPGlkPi5vdXRwdXRzLjxuYW1lPiB9fWAuXG4gICAqIEBkZWZhdWx0IC0gYSBzbHVnIGRlcml2ZWQgZnJvbSBgbmFtZWAsIGRpc2FtYmlndWF0ZWQgYnkgcG9zaXRpb25cbiAgICovXG4gIHJlYWRvbmx5IGlkPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBTaGVsbCBzdGVwcyBleGVjdXRlZCBiZWZvcmUgdGhpcyBpbnZvY2F0aW9uLCB0byBwcm9kdWNlIG9yIGFsdGVyXG4gICAqIGZpeHR1cmUgc3RhdGUuXG4gICAqIEBkZWZhdWx0IFtdXG4gICAqL1xuICByZWFkb25seSBmaXh0dXJlU3RlcHM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogYHdpdGg6YCBpbnB1dHMgZm9yIHRoaXMgaW52b2NhdGlvbidzIGxvY2FsIGB1c2VzOiAuYCBjYWxsLlxuICAgKiBAZGVmYXVsdCB7fVxuICAgKi9cbiAgcmVhZG9ubHkgaW5wdXRzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcblxuICAvKiogU2hlbGwgYXNzZXJ0aW9ucyBhZnRlciB0aGlzIGludm9jYXRpb24gLSB0aGUgam9iIGZhaWxzIHVubGVzcyBldmVyeSBvbmUgZXhpdHMgMC4gKi9cbiAgcmVhZG9ubHkgYXNzZXJ0aW9uczogc3RyaW5nW107XG59XG5cbi8vIExvd2VyY2FzZSwgbm9uLWFscGhhbnVtZXJpY3MgY29sbGFwc2VkIHRvIGEgc2luZ2xlIGAtYCwgdHJpbW1lZCAtIHRoZW5cbi8vIGRpc2FtYmlndWF0ZWQgYnkgcG9zaXRpb24gc28gdHdvIHN0ZXBzIHNoYXJpbmcgYSBuYW1lIChvciBhbiB1bm5hbWVkXG4vLyBzbHVnLCBlLmcuIHB1bmN0dWF0aW9uLW9ubHkpIG5ldmVyIGNvbGxpZGUuXG5mdW5jdGlvbiBzbHVnKG5hbWU6IHN0cmluZywgaW5kZXg6IG51bWJlcik6IHN0cmluZyB7XG4gIGNvbnN0IGJhc2UgPSBuYW1lXG4gICAgLnRvTG93ZXJDYXNlKClcbiAgICAucmVwbGFjZSgvW15hLXowLTldKy9nLCAnLScpXG4gICAgLnJlcGxhY2UoL14tK3wtKyQvZywgJycpO1xuICByZXR1cm4gYCR7YmFzZSB8fCAnc3RlcCd9LSR7aW5kZXh9YDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBY3Rpb25Eb2dmb29kT3B0aW9ucyB7XG4gIC8qKiBPbmUgb3IgbW9yZSBzY2VuYXJpbyBzdGVwcywgcnVuIGluIG9yZGVyLCBpbiB0aGUgZG9nZm9vZCBqb2IuICovXG4gIHJlYWRvbmx5IHNjZW5hcmlvOiBBY3Rpb25Eb2dmb29kU3RlcFtdO1xuXG4gIC8qKiBTaGVsbCBjbGVhbnVwLCBydW4gb25jZSBhdCB0aGUgZW5kIHdpdGggYGlmOiBhbHdheXMoKWAsIHNvIHJlcGVhdGVkIHJ1bnMgc3RhcnQgY2xlYW4uICovXG4gIHJlYWRvbmx5IGNsZWFudXA6IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIFBlciBBRC0wMDEncyBkb2dmb29kIHRlc3Q6IHRoZSBjb21wb3NpdGUgYWN0aW9uIGlzIHJ1biAqKmFnYWluc3QgdGhpc1xuICogcmVwbyoqLCBlbmQtdG8tZW5kLCB2aWEgYSBsb2NhbCBgdXNlczogLmAgcmVmZXJlbmNlIC0gbm8gZXh0ZXJuYWwgaGFybmVzcy5cbiAqIEJ1aWxkcyBgdGVzdC1kb2dmb29kLnltbGAgZnJvbSBhbiBvcmRlcmVkIGBzY2VuYXJpb2Agb2YgaW52b2NhdGlvbiBzdGVwc1xuICogKHNlZSBgQWN0aW9uRG9nZm9vZFN0ZXBgKSBmb2xsb3dlZCBieSBhIHNoYXJlZCBjbGVhbnVwIHN0ZXAuXG4gKi9cbmV4cG9ydCBjbGFzcyBBY3Rpb25Eb2dmb29kV29ya2Zsb3cgZXh0ZW5kcyBDb21wb25lbnQge1xuICBwdWJsaWMgcmVhZG9ubHkgd29ya2Zsb3c6IGdpdGh1Yi5HaXRodWJXb3JrZmxvdztcblxuICBjb25zdHJ1Y3RvcihzY29wZTogZ2l0aHViLkdpdEh1YlByb2plY3QsIG9wdGlvbnM6IEFjdGlvbkRvZ2Zvb2RPcHRpb25zKSB7XG4gICAgc3VwZXIoc2NvcGUsICdBY3Rpb25Eb2dmb29kV29ya2Zsb3cnKTtcblxuICAgIGlmICghb3B0aW9ucy5zY2VuYXJpbyB8fCBvcHRpb25zLnNjZW5hcmlvLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnQWN0aW9uRG9nZm9vZFdvcmtmbG93IHJlcXVpcmVzIGF0IGxlYXN0IG9uZSBkb2dmb29kLnNjZW5hcmlvIHN0ZXAnLFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKCFvcHRpb25zLmNsZWFudXAgfHwgb3B0aW9ucy5jbGVhbnVwLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBY3Rpb25Eb2dmb29kV29ya2Zsb3cgcmVxdWlyZXMgZG9nZm9vZC5jbGVhbnVwJyk7XG4gICAgfVxuXG4gICAgY29uc3QgZ2ggPSBzY29wZS5naXRodWI7XG4gICAgaWYgKCFnaCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnQWN0aW9uRG9nZm9vZFdvcmtmbG93IHJlcXVpcmVzIEdpdEh1YiBpbnRlZ3JhdGlvbiB0byBiZSBlbmFibGVkJyxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3Qgc3RlcHM6IGdpdGh1Yi53b3JrZmxvd3MuSm9iU3RlcFtdID0gW2dpdGh1Yi5Xb3JrZmxvd1N0ZXBzLmNoZWNrb3V0KCldO1xuXG4gICAgb3B0aW9ucy5zY2VuYXJpby5mb3JFYWNoKChzdGVwLCBpbmRleCkgPT4ge1xuICAgICAgaWYgKHN0ZXAuZml4dHVyZVN0ZXBzICYmIHN0ZXAuZml4dHVyZVN0ZXBzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgc3RlcHMucHVzaCh7XG4gICAgICAgICAgbmFtZTogYCR7c3RlcC5uYW1lfTogZml4dHVyZWAsXG4gICAgICAgICAgcnVuOiBzdGVwLmZpeHR1cmVTdGVwcy5qb2luKCdcXG4nKSxcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGhhc0lucHV0cyA9IHN0ZXAuaW5wdXRzICYmIE9iamVjdC5rZXlzKHN0ZXAuaW5wdXRzKS5sZW5ndGggPiAwO1xuICAgICAgc3RlcHMucHVzaCh7XG4gICAgICAgIGlkOiBzdGVwLmlkID8/IHNsdWcoc3RlcC5uYW1lLCBpbmRleCksXG4gICAgICAgIG5hbWU6IGAke3N0ZXAubmFtZX06IHJ1biB0aGUgYWN0aW9uYCxcbiAgICAgICAgdXNlczogJy4nLFxuICAgICAgICAuLi4oaGFzSW5wdXRzID8geyB3aXRoOiBzdGVwLmlucHV0cyB9IDoge30pLFxuICAgICAgfSk7XG5cbiAgICAgIHN0ZXBzLnB1c2goe1xuICAgICAgICBuYW1lOiBgJHtzdGVwLm5hbWV9OiBhc3NlcnRgLFxuICAgICAgICBydW46IHN0ZXAuYXNzZXJ0aW9ucy5qb2luKCdcXG4nKSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgc3RlcHMucHVzaCh7XG4gICAgICBuYW1lOiAnQ2xlYW51cCcsXG4gICAgICBpZjogJ2Fsd2F5cygpJyxcbiAgICAgIHJ1bjogb3B0aW9ucy5jbGVhbnVwLmpvaW4oJ1xcbicpLFxuICAgIH0pO1xuXG4gICAgdGhpcy53b3JrZmxvdyA9IG5ldyBnaXRodWIuR2l0aHViV29ya2Zsb3coZ2gsICd0ZXN0LWRvZ2Zvb2QnKTtcbiAgICB0aGlzLndvcmtmbG93Lm9uKHtcbiAgICAgIHdvcmtmbG93RGlzcGF0Y2g6IHt9LFxuICAgICAgcHVsbFJlcXVlc3Q6IHsgYnJhbmNoZXM6IFsnbWFpbiddIH0sXG4gICAgICBzY2hlZHVsZTogW3sgY3JvbjogTklHSFRMWV9ET0dGT09EX1NDSEVEVUxFIH1dLFxuICAgIH0pO1xuICAgIHRoaXMud29ya2Zsb3cuYWRkSm9iKCdkb2dmb29kJywge1xuICAgICAgcnVuc09uOiBbJ3VidW50dS1sYXRlc3QnXSxcbiAgICAgIHBlcm1pc3Npb25zOiB7XG4gICAgICAgIGNvbnRlbnRzOiBnaXRodWIud29ya2Zsb3dzLkpvYlBlcm1pc3Npb24uV1JJVEUsXG4gICAgICAgIHB1bGxSZXF1ZXN0czogZ2l0aHViLndvcmtmbG93cy5Kb2JQZXJtaXNzaW9uLldSSVRFLFxuICAgICAgfSxcbiAgICAgIHN0ZXBzLFxuICAgIH0pO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Component, github } from 'projen';
|
|
2
|
+
export interface ActionSonarWorkflowOptions {
|
|
3
|
+
/**
|
|
4
|
+
* URL of the org's self-hosted SonarQube instance. Required, no default -
|
|
5
|
+
* a guessed server is worse than a loud failure.
|
|
6
|
+
*/
|
|
7
|
+
readonly sonarHostUrl: string;
|
|
8
|
+
/** @default "SONAR_TOKEN" */
|
|
9
|
+
readonly sonarTokenSecret?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Whether `sonar.yml` also runs on `pull_request` as a pass/fail gate.
|
|
12
|
+
* @default true
|
|
13
|
+
*/
|
|
14
|
+
readonly sonarPullRequestGate?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* AD-001 Layer 2: self-hosted SonarQube Community Edition via the Scanner
|
|
18
|
+
* CLI only (never `SonarSource/sonarqube-scan-action` - third-party, and it
|
|
19
|
+
* carried a security advisory). `sonar.inclusions` is set explicitly since
|
|
20
|
+
* default inclusions may skip `action.yml` outside `.github/`.
|
|
21
|
+
*/
|
|
22
|
+
export declare class ActionSonarWorkflow extends Component {
|
|
23
|
+
readonly workflow: github.GithubWorkflow;
|
|
24
|
+
constructor(scope: github.GitHubProject, options: ActionSonarWorkflowOptions);
|
|
25
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ActionSonarWorkflow = void 0;
|
|
4
|
+
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
5
|
+
const projen_1 = require("projen");
|
|
6
|
+
// Pinned release + verified SHA-256 (linux-x64) - upgrade is a reviewed diff
|
|
7
|
+
// of this constant, never a floating version (AD-001).
|
|
8
|
+
const SONAR_SCANNER_VERSION = '8.1.0.6389';
|
|
9
|
+
const SONAR_SCANNER_SHA256 = 'bb8f709f9cb73352f8d1260a3b3c506c0f41146754bc630762c126d795499d0b';
|
|
10
|
+
/**
|
|
11
|
+
* AD-001 Layer 2: self-hosted SonarQube Community Edition via the Scanner
|
|
12
|
+
* CLI only (never `SonarSource/sonarqube-scan-action` - third-party, and it
|
|
13
|
+
* carried a security advisory). `sonar.inclusions` is set explicitly since
|
|
14
|
+
* default inclusions may skip `action.yml` outside `.github/`.
|
|
15
|
+
*/
|
|
16
|
+
class ActionSonarWorkflow extends projen_1.Component {
|
|
17
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "@xpertss/projen-types.ActionSonarWorkflow", version: "0.0.3" };
|
|
18
|
+
workflow;
|
|
19
|
+
constructor(scope, options) {
|
|
20
|
+
super(scope, 'ActionSonarWorkflow');
|
|
21
|
+
if (!options.sonarHostUrl) {
|
|
22
|
+
throw new Error('ActionSonarWorkflow requires sonarHostUrl');
|
|
23
|
+
}
|
|
24
|
+
const gh = scope.github;
|
|
25
|
+
if (!gh) {
|
|
26
|
+
throw new Error('ActionSonarWorkflow requires GitHub integration to be enabled');
|
|
27
|
+
}
|
|
28
|
+
const sonarTokenSecret = options.sonarTokenSecret ?? 'SONAR_TOKEN';
|
|
29
|
+
const pullRequestGate = options.sonarPullRequestGate ?? true;
|
|
30
|
+
this.workflow = new projen_1.github.GithubWorkflow(gh, 'sonar');
|
|
31
|
+
this.workflow.on({
|
|
32
|
+
push: { branches: ['main'] },
|
|
33
|
+
...(pullRequestGate ? { pullRequest: {} } : {}),
|
|
34
|
+
});
|
|
35
|
+
this.workflow.addJob('sonar', {
|
|
36
|
+
runsOn: ['ubuntu-latest'],
|
|
37
|
+
permissions: { contents: projen_1.github.workflows.JobPermission.READ },
|
|
38
|
+
env: { SONAR_TOKEN: `\${{ secrets.${sonarTokenSecret} }}` },
|
|
39
|
+
steps: [
|
|
40
|
+
projen_1.github.WorkflowSteps.checkout(),
|
|
41
|
+
{
|
|
42
|
+
name: 'Install sonar-scanner',
|
|
43
|
+
run: `set -euo pipefail
|
|
44
|
+
curl -fsSL -o /tmp/sonar-scanner.zip "https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_SCANNER_VERSION}-linux-x64.zip"
|
|
45
|
+
echo "${SONAR_SCANNER_SHA256} /tmp/sonar-scanner.zip" | sha256sum -c -
|
|
46
|
+
unzip -q /tmp/sonar-scanner.zip -d /tmp
|
|
47
|
+
echo "/tmp/sonar-scanner-${SONAR_SCANNER_VERSION}-linux-x64/bin" >> "$GITHUB_PATH"
|
|
48
|
+
`,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'Scan',
|
|
52
|
+
run: `sonar-scanner \\
|
|
53
|
+
-Dsonar.host.url=${options.sonarHostUrl} \\
|
|
54
|
+
-Dsonar.projectKey=${scope.name} \\
|
|
55
|
+
-Dsonar.projectVersion="$(git describe --tags --always)" \\
|
|
56
|
+
-Dsonar.inclusions=.github/workflows/**,action.yml,**/*.sh \\
|
|
57
|
+
-Dsonar.qualitygate.wait=true`,
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.ActionSonarWorkflow = ActionSonarWorkflow;
|
|
64
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWN0aW9uLXNvbmFyLXdvcmtmbG93LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FjdGlvbnMvYWN0aW9uLXNvbmFyLXdvcmtmbG93LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxtQ0FBMkM7QUFFM0MsNkVBQTZFO0FBQzdFLHVEQUF1RDtBQUN2RCxNQUFNLHFCQUFxQixHQUFHLFlBQVksQ0FBQztBQUMzQyxNQUFNLG9CQUFvQixHQUN4QixrRUFBa0UsQ0FBQztBQW1CckU7Ozs7O0dBS0c7QUFDSCxNQUFhLG1CQUFvQixTQUFRLGtCQUFTOztJQUNoQyxRQUFRLENBQXdCO0lBRWhELFlBQ0UsS0FBMkIsRUFDM0IsT0FBbUM7UUFFbkMsS0FBSyxDQUFDLEtBQUssRUFBRSxxQkFBcUIsQ0FBQyxDQUFDO1FBRXBDLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDMUIsTUFBTSxJQUFJLEtBQUssQ0FBQywyQ0FBMkMsQ0FBQyxDQUFDO1FBQy9ELENBQUM7UUFFRCxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNSLE1BQU0sSUFBSSxLQUFLLENBQ2IsK0RBQStELENBQ2hFLENBQUM7UUFDSixDQUFDO1FBRUQsTUFBTSxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsZ0JBQWdCLElBQUksYUFBYSxDQUFDO1FBQ25FLE1BQU0sZUFBZSxHQUFHLE9BQU8sQ0FBQyxvQkFBb0IsSUFBSSxJQUFJLENBQUM7UUFFN0QsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLGVBQU0sQ0FBQyxjQUFjLENBQUMsRUFBRSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3ZELElBQUksQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQ2YsSUFBSSxFQUFFLEVBQUUsUUFBUSxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDNUIsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsRUFBRSxXQUFXLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztTQUNoRCxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUU7WUFDNUIsTUFBTSxFQUFFLENBQUMsZUFBZSxDQUFDO1lBQ3pCLFdBQVcsRUFBRSxFQUFFLFFBQVEsRUFBRSxlQUFNLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUU7WUFDOUQsR0FBRyxFQUFFLEVBQUUsV0FBVyxFQUFFLGdCQUFnQixnQkFBZ0IsS0FBSyxFQUFFO1lBQzNELEtBQUssRUFBRTtnQkFDTCxlQUFNLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRTtnQkFDL0I7b0JBQ0UsSUFBSSxFQUFFLHVCQUF1QjtvQkFDN0IsR0FBRyxFQUFFOzBIQUMyRyxxQkFBcUI7UUFDdkksb0JBQW9COzsyQkFFRCxxQkFBcUI7Q0FDL0M7aUJBQ1E7Z0JBQ0Q7b0JBQ0UsSUFBSSxFQUFFLE1BQU07b0JBQ1osR0FBRyxFQUFFO3FCQUNNLE9BQU8sQ0FBQyxZQUFZO3VCQUNsQixLQUFLLENBQUMsSUFBSTs7O2dDQUdEO2lCQUN2QjthQUNGO1NBQ0YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7QUF0REgsa0RBdURDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBnaXRodWIgfSBmcm9tICdwcm9qZW4nO1xuXG4vLyBQaW5uZWQgcmVsZWFzZSArIHZlcmlmaWVkIFNIQS0yNTYgKGxpbnV4LXg2NCkgLSB1cGdyYWRlIGlzIGEgcmV2aWV3ZWQgZGlmZlxuLy8gb2YgdGhpcyBjb25zdGFudCwgbmV2ZXIgYSBmbG9hdGluZyB2ZXJzaW9uIChBRC0wMDEpLlxuY29uc3QgU09OQVJfU0NBTk5FUl9WRVJTSU9OID0gJzguMS4wLjYzODknO1xuY29uc3QgU09OQVJfU0NBTk5FUl9TSEEyNTYgPVxuICAnYmI4ZjcwOWY5Y2I3MzM1MmY4ZDEyNjBhM2IzYzUwNmMwZjQxMTQ2NzU0YmM2MzA3NjJjMTI2ZDc5NTQ5OWQwYic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQWN0aW9uU29uYXJXb3JrZmxvd09wdGlvbnMge1xuICAvKipcbiAgICogVVJMIG9mIHRoZSBvcmcncyBzZWxmLWhvc3RlZCBTb25hclF1YmUgaW5zdGFuY2UuIFJlcXVpcmVkLCBubyBkZWZhdWx0IC1cbiAgICogYSBndWVzc2VkIHNlcnZlciBpcyB3b3JzZSB0aGFuIGEgbG91ZCBmYWlsdXJlLlxuICAgKi9cbiAgcmVhZG9ubHkgc29uYXJIb3N0VXJsOiBzdHJpbmc7XG5cbiAgLyoqIEBkZWZhdWx0IFwiU09OQVJfVE9LRU5cIiAqL1xuICByZWFkb25seSBzb25hclRva2VuU2VjcmV0Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIGBzb25hci55bWxgIGFsc28gcnVucyBvbiBgcHVsbF9yZXF1ZXN0YCBhcyBhIHBhc3MvZmFpbCBnYXRlLlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBzb25hclB1bGxSZXF1ZXN0R2F0ZT86IGJvb2xlYW47XG59XG5cbi8qKlxuICogQUQtMDAxIExheWVyIDI6IHNlbGYtaG9zdGVkIFNvbmFyUXViZSBDb21tdW5pdHkgRWRpdGlvbiB2aWEgdGhlIFNjYW5uZXJcbiAqIENMSSBvbmx5IChuZXZlciBgU29uYXJTb3VyY2Uvc29uYXJxdWJlLXNjYW4tYWN0aW9uYCAtIHRoaXJkLXBhcnR5LCBhbmQgaXRcbiAqIGNhcnJpZWQgYSBzZWN1cml0eSBhZHZpc29yeSkuIGBzb25hci5pbmNsdXNpb25zYCBpcyBzZXQgZXhwbGljaXRseSBzaW5jZVxuICogZGVmYXVsdCBpbmNsdXNpb25zIG1heSBza2lwIGBhY3Rpb24ueW1sYCBvdXRzaWRlIGAuZ2l0aHViL2AuXG4gKi9cbmV4cG9ydCBjbGFzcyBBY3Rpb25Tb25hcldvcmtmbG93IGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgcHVibGljIHJlYWRvbmx5IHdvcmtmbG93OiBnaXRodWIuR2l0aHViV29ya2Zsb3c7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgc2NvcGU6IGdpdGh1Yi5HaXRIdWJQcm9qZWN0LFxuICAgIG9wdGlvbnM6IEFjdGlvblNvbmFyV29ya2Zsb3dPcHRpb25zLFxuICApIHtcbiAgICBzdXBlcihzY29wZSwgJ0FjdGlvblNvbmFyV29ya2Zsb3cnKTtcblxuICAgIGlmICghb3B0aW9ucy5zb25hckhvc3RVcmwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQWN0aW9uU29uYXJXb3JrZmxvdyByZXF1aXJlcyBzb25hckhvc3RVcmwnKTtcbiAgICB9XG5cbiAgICBjb25zdCBnaCA9IHNjb3BlLmdpdGh1YjtcbiAgICBpZiAoIWdoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdBY3Rpb25Tb25hcldvcmtmbG93IHJlcXVpcmVzIEdpdEh1YiBpbnRlZ3JhdGlvbiB0byBiZSBlbmFibGVkJyxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3Qgc29uYXJUb2tlblNlY3JldCA9IG9wdGlvbnMuc29uYXJUb2tlblNlY3JldCA/PyAnU09OQVJfVE9LRU4nO1xuICAgIGNvbnN0IHB1bGxSZXF1ZXN0R2F0ZSA9IG9wdGlvbnMuc29uYXJQdWxsUmVxdWVzdEdhdGUgPz8gdHJ1ZTtcblxuICAgIHRoaXMud29ya2Zsb3cgPSBuZXcgZ2l0aHViLkdpdGh1YldvcmtmbG93KGdoLCAnc29uYXInKTtcbiAgICB0aGlzLndvcmtmbG93Lm9uKHtcbiAgICAgIHB1c2g6IHsgYnJhbmNoZXM6IFsnbWFpbiddIH0sXG4gICAgICAuLi4ocHVsbFJlcXVlc3RHYXRlID8geyBwdWxsUmVxdWVzdDoge30gfSA6IHt9KSxcbiAgICB9KTtcbiAgICB0aGlzLndvcmtmbG93LmFkZEpvYignc29uYXInLCB7XG4gICAgICBydW5zT246IFsndWJ1bnR1LWxhdGVzdCddLFxuICAgICAgcGVybWlzc2lvbnM6IHsgY29udGVudHM6IGdpdGh1Yi53b3JrZmxvd3MuSm9iUGVybWlzc2lvbi5SRUFEIH0sXG4gICAgICBlbnY6IHsgU09OQVJfVE9LRU46IGBcXCR7eyBzZWNyZXRzLiR7c29uYXJUb2tlblNlY3JldH0gfX1gIH0sXG4gICAgICBzdGVwczogW1xuICAgICAgICBnaXRodWIuV29ya2Zsb3dTdGVwcy5jaGVja291dCgpLFxuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogJ0luc3RhbGwgc29uYXItc2Nhbm5lcicsXG4gICAgICAgICAgcnVuOiBgc2V0IC1ldW8gcGlwZWZhaWxcbmN1cmwgLWZzU0wgLW8gL3RtcC9zb25hci1zY2FubmVyLnppcCBcImh0dHBzOi8vYmluYXJpZXMuc29uYXJzb3VyY2UuY29tL0Rpc3RyaWJ1dGlvbi9zb25hci1zY2FubmVyLWNsaS9zb25hci1zY2FubmVyLWNsaS0ke1NPTkFSX1NDQU5ORVJfVkVSU0lPTn0tbGludXgteDY0LnppcFwiXG5lY2hvIFwiJHtTT05BUl9TQ0FOTkVSX1NIQTI1Nn0gIC90bXAvc29uYXItc2Nhbm5lci56aXBcIiB8IHNoYTI1NnN1bSAtYyAtXG51bnppcCAtcSAvdG1wL3NvbmFyLXNjYW5uZXIuemlwIC1kIC90bXBcbmVjaG8gXCIvdG1wL3NvbmFyLXNjYW5uZXItJHtTT05BUl9TQ0FOTkVSX1ZFUlNJT059LWxpbnV4LXg2NC9iaW5cIiA+PiBcIiRHSVRIVUJfUEFUSFwiXG5gLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogJ1NjYW4nLFxuICAgICAgICAgIHJ1bjogYHNvbmFyLXNjYW5uZXIgXFxcXFxuICAtRHNvbmFyLmhvc3QudXJsPSR7b3B0aW9ucy5zb25hckhvc3RVcmx9IFxcXFxcbiAgLURzb25hci5wcm9qZWN0S2V5PSR7c2NvcGUubmFtZX0gXFxcXFxuICAtRHNvbmFyLnByb2plY3RWZXJzaW9uPVwiJChnaXQgZGVzY3JpYmUgLS10YWdzIC0tYWx3YXlzKVwiIFxcXFxcbiAgLURzb25hci5pbmNsdXNpb25zPS5naXRodWIvd29ya2Zsb3dzLyoqLGFjdGlvbi55bWwsKiovKi5zaCBcXFxcXG4gIC1Ec29uYXIucXVhbGl0eWdhdGUud2FpdD10cnVlYCxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { github, release } from 'projen';
|
|
2
|
+
import { ActionBuildWorkflow } from './action-build-workflow';
|
|
3
|
+
import { ActionDogfoodOptions, ActionDogfoodWorkflow } from './action-dogfood-workflow';
|
|
4
|
+
import { ActionSonarWorkflow } from './action-sonar-workflow';
|
|
5
|
+
export interface GitHubActionProjectOptions extends github.GitHubProjectOptions {
|
|
6
|
+
/**
|
|
7
|
+
* One-line description of the action. Used in the default README
|
|
8
|
+
* template and recorded in the private `package.json`.
|
|
9
|
+
*/
|
|
10
|
+
readonly description?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Name of the GitHub Actions secret holding the PAT used for
|
|
13
|
+
* projen-automation PR comments (F003/F009) and, when the action has a
|
|
14
|
+
* `token` input, the dogfood's invocation of it.
|
|
15
|
+
* @default "PROJEN_GITHUB_TOKEN"
|
|
16
|
+
*/
|
|
17
|
+
readonly gheTokenSecret?: string;
|
|
18
|
+
/**
|
|
19
|
+
* URL of the org's self-hosted SonarQube instance. MUST be reachable from
|
|
20
|
+
* github.com-hosted (public) runners (AD-001). Required, no default: a
|
|
21
|
+
* guessed server is worse than a loud failure.
|
|
22
|
+
*/
|
|
23
|
+
readonly sonarHostUrl: string;
|
|
24
|
+
/** @default "SONAR_TOKEN" */
|
|
25
|
+
readonly sonarTokenSecret?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Whether `sonar.yml` also runs on `pull_request` as a pass/fail gate.
|
|
28
|
+
* @default true
|
|
29
|
+
*/
|
|
30
|
+
readonly sonarPullRequestGate?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* The dogfood scenario (AD-001). What fixture state, what to assert, and
|
|
33
|
+
* how to clean up are specified by the action's own F### spec - the
|
|
34
|
+
* highest-risk behavior of that action. Required: a default no-op
|
|
35
|
+
* dogfood would silently hollow out a load-bearing AD-001 workflow.
|
|
36
|
+
*/
|
|
37
|
+
readonly dogfood: ActionDogfoodOptions;
|
|
38
|
+
/**
|
|
39
|
+
* SPDX identifier for the generated `LICENSE`.
|
|
40
|
+
* @default "MIT"
|
|
41
|
+
*/
|
|
42
|
+
readonly license?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Scaffolds the repo lifecycle (AD-001) around a hand-committed, composite
|
|
46
|
+
* (shell) GitHub Action: the `build`/`test-dogfood`/`sonar`/`release`
|
|
47
|
+
* workflows, versioning and release discipline, the F003 verify components,
|
|
48
|
+
* the F009 allowlist guard, and repo boilerplate (a private version-source
|
|
49
|
+
* `package.json`, `.yamllint`, `LICENSE`, and a `README.md` template). The
|
|
50
|
+
* action's own content
|
|
51
|
+
* (`action.yml`, its shell scripts, `test/` fixtures) is authored by hand
|
|
52
|
+
* per the action's own F### spec - this type only lints it.
|
|
53
|
+
*/
|
|
54
|
+
export declare class GitHubActionProject extends github.GitHubProject {
|
|
55
|
+
readonly buildWorkflow: ActionBuildWorkflow;
|
|
56
|
+
readonly dogfoodWorkflow: ActionDogfoodWorkflow;
|
|
57
|
+
readonly sonarWorkflow: ActionSonarWorkflow;
|
|
58
|
+
readonly release: release.Release;
|
|
59
|
+
constructor(options: GitHubActionProjectOptions);
|
|
60
|
+
}
|