@xpertss/projen-types 0.0.19 → 0.0.21
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 +193 -46
- package/API.md +302 -10
- package/README.md +10 -3
- package/lib/actions/action-build-workflow.js +1 -1
- package/lib/actions/action-dogfood-workflow.d.ts +12 -2
- package/lib/actions/action-dogfood-workflow.js +3 -3
- package/lib/actions/action-sonar-workflow.d.ts +7 -0
- package/lib/actions/action-sonar-workflow.js +4 -2
- package/lib/actions/github-action-project.d.ts +20 -2
- package/lib/actions/github-action-project.js +5 -3
- package/lib/cdk/app-runtime-scaffold.js +1 -1
- package/lib/cdk/cdk-app-project.js +1 -1
- package/lib/cdk/cdk-infra-project.js +1 -1
- package/lib/cdk/cdk-typescript-base.js +13 -2
- 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 +20 -0
- package/lib/cdk/options.js +1 -1
- package/lib/common/projen-drift-check-workflow.js +1 -1
- package/lib/common/workflow-change-notice-workflow.js +1 -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/components/maven-upgrade-report.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 +3 -3
- package/lib/java/java-service-project.js +1 -1
- package/lib/java/java-spring-boot-project.js +1 -1
- package/lib/java/maven/maven-module.js +1 -1
- package/lib/java/maven/maven-pom.js +1 -1
- package/lib/java/options.d.ts +1 -1
- package/lib/java/options.js +1 -1
- package/package.json +1 -1
package/.jsii
CHANGED
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
},
|
|
107
107
|
"name": "@xpertss/projen-types",
|
|
108
108
|
"readme": {
|
|
109
|
-
"markdown": "# @xpertss/projen-types\n\nProjen project types for CDK/TypeScript and Java/Maven projects.\n\nInstead of hand-maintaining `pom.xml`, `cdk.json`, and GitHub workflows, you declare a project type in a `.projenrc.ts` 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.\n\n## Project types at a glance\n\n| Type | What it is | Publishes to | Generated workflows |\n| --- | --- | --- | --- |\n| `CdkInfraProject` | Pure-infrastructure CDK stacks (CloudFront, Route53, SQS, API Gateway, Cognito, ECR/ECS for externally-built images) | - | `build` (PR checks), `deploy` (manual dispatch) |\n| `CdkAppProject` | Full TypeScript service behind API Gateway: infra + app source + database | - | `build`, `deploy`, `app-build` (PR checks) |\n| `JavaMavenProject` | Plain Maven project, single- or multi-module, no framework | - | `build`, `upgrade` (nightly report) |\n| `JavaLibraryProject` | Reusable Java library | Maven Central | `build`, `upgrade` (nightly report), `publish-maven-central`, `codeindex` |\n| `JavaAppProject` | GUI/TUI/CLI Java application | GitHub Packages | `build`, `upgrade` (nightly report), `publish-ghpackages` |\n| `JavaSpringBootProject` | Spring Boot on Maven, single- or multi-module, **no Docker** | - | `build`, `upgrade` (nightly report) |\n| `JavaServiceProject` | Spring Boot service deployed as a container | Docker Hub | `build`, `upgrade` (nightly report), `publish-docker`, `deploy-cdk` |\n| `GitHubActionProject` | Reusable GitHub Action or Workflow | GitHub Releases | `build`, `test-dogfood`, `sonar`, `release` |\n\nThe Java types are layered, so pick the lowest layer that does what you need:\n\n```text\nJavaMavenProject java_maven Maven only; single- or multi-module; any supported Java line\n├── JavaLibraryProject java_library + Maven Central publish, source/javadoc jars, code index\n├── JavaAppProject java_app + GitHub Packages publish\n└── JavaSpringBootProject java_spring_boot + Spring Boot BOM and executable-jar repackaging; no Docker/Flyway/CDK\n └── JavaServiceProject java_service + Docker publish, Flyway, CDK deploy hook (single-module)\n```\n\nEvery Java type targets a configurable Java line (`javaVersion`: `1.8`, `17`, `21` or `25`; see [Java version support](#java-version-support)), and every one except `JavaServiceProject` can be a multi-module Maven reactor (see [JavaMavenProject](#javamavenproject)).\n\nOne foundation class is also exported for advanced use: `CdkTypescriptProject` (shared CDK + TypeScript base for the CDK types).\n\nAll project types:\n\n- run a **drift check** in PR builds - a job that re-runs projen and fails if generated files were hand-edited. Edit `.projenrc.ts`, then run `npx projen`; never edit generated files directly.\n- use the GitHub secret `PROJEN_GITHUB_TOKEN` (a fine-grained PAT) for projen's automation. Override with `gheTokenSecret`.\n- make all publishing/deploying **manual** (workflow_dispatch) rather than on every merge.\n\n## Getting started\n\nHow you start depends on what is already in the directory:\n\n| Starting point | Do this |\n| --- | --- |\n| Empty directory | `projen new --from` (below) |\n| Existing repo, no `.projenrc.ts` | `projen new --from ... --no-git` (below) |\n| A `.projenrc.ts` but no `.projen/` directory - copied from another repo, or one of the [examples](#examples) pasted into a fresh repo | [Starting from an existing `.projenrc.ts`](#starting-from-an-existing-projenrcts) |\n\nScaffold the repo with projen's own bootstrap, pointed at this package:\n\n```bash\nmkdir my-project && cd my-project\ngit init\nnpx projen new --from @xpertss/projen-types cdk_infra --name my-project\n```\n\nThat writes a starter `.projenrc.ts`, synthesizes the whole scaffold and\ninstalls dependencies. The type names `projen new` accepts are `cdk_infra`,\n`cdk_app`, `java_maven`, `java_library`, `java_app`, `java_spring_boot`,\n`java_service` and `git_hub_action`; pass a bogus one to have it list them.\nRequired options become flags: `--name` for every type, plus\n`--group-id`/`--artifact-id` (Java) and `--sonar-host-url`\n(`git_hub_action`). Any other plainly-typed option can be passed the same\nway - `--java-version 1.8`, `--cdk-deploy-target-repo owner/repo`,\n`--docker-registry ghcr.io`, `--no-use-flyway`, and so on. Modules can't be\npassed on the command line; add them to `.projenrc.ts` afterwards (see\n[JavaMavenProject](#javamavenproject)).\n\n**Adding projen to a repo that already has content.** `projen new` runs\n`git init` and commits the scaffold by default. In a repo with existing work,\npass `--no-git` so it writes the files and leaves committing to you:\n\n```bash\ncd existing-repo\nnpx projen new --from @xpertss/projen-types java_spring_boot --name obeya --group-id org.xpertss.obeya --artifact-id obeya-parent --no-git\n```\n\n**Commit a lockfile.** The generated `build.yml` and drift check install the\ntoolchain with `npm ci`, which needs a committed `package-lock.json`, and\n`projen new` doesn't always leave one behind. Run `npm install` once and\ncommit `package-lock.json` along with the scaffold. Without it those\nworkflows fail with an `::error::` that says exactly this. For the Java\ntypes, `package.json` is generated, and it pins `projen` and\n`@xpertss/projen-types` to **exact** versions (no `^`), so every machine and\nCI run uses the same generator. A floating range would make the drift check\nreport the differences between generator versions as drift.\n\nCommit the result. From then on, every change to the scaffold goes through\n`.projenrc.ts` followed by `npx projen`:\n\n```bash\nnpx projen\n```\n\nEvery type scaffolds from that one command; no option is *required* that\n`projen new` cannot pass. The structured options - `environments` and\n`GitHubActionProject`'s `dogfood` - are ones projen's CLI cannot render\ninto a projenrc, so they are added afterwards by editing `.projenrc.ts` and\nre-running `npx projen`. Leaving `environments` out simply generates no\ndeploy workflow; leaving `dogfood` out (or a service's\n`cdkDeployTargetRepo`) still generates the workflow, with one step that\nfails and tells you what to add - a gate this package considers load-bearing\nis allowed to be missing loudly, never silently.\n\nThe `name` option must match the `name` field in the project's `package.json` (for the CDK types). For the Java types it becomes the root pom's `<name>` and the generated `package.json` name.\n\n> **Never write projen's generated-file marker text literally in `.projenrc.ts`.** projen deletes, as an orphaned generated file, any file containing the marker line (`~~ Generated by projen. To modify, ...`), and that includes `.projenrc.ts` itself. When you generate a file yourself (for example with `TextFile`), insert the marker through the file's `marker` property: ``file.addLine(`# ${file.marker}`)``.\n\n## Starting from an existing `.projenrc.ts`\n\nA directory that has a `.projenrc.ts` but no `.projen/` directory has never\nbeen synthesized. This happens when you copy the rc from another repo, or paste\none of the [examples](#examples) into a fresh repo. In that state `npx projen`\nfails with:\n\n```\n👾 Unable to find projen project. Use \"projen new\" to create a new project.\n```\n\n`npx projen` doesn't run `.projenrc.ts` itself. It runs the `default` task\nlisted in `.projen/tasks.json`, and that file is written by the first synth.\nDo the first synth one of these two ways. After that, `npx projen` works as\nusual.\n\n**Option 1 (recommended): run `projen new` over the existing rc.** `projen\nnew` leaves an existing `.projenrc.ts` untouched and writes the rest of the\nscaffold, `.projen/` included. Pass the type and its required flags as you\nwould for a new repo. Their values don't have to match your rc, because the\n`npx projen` that follows re-synthesizes everything from the rc:\n\n```bash\nnpx projen new --from @xpertss/projen-types git_hub_action --name pull-request --sonar-host-url https://sonarcloud.io --no-git\nnpx projen\n```\n\nThe first command's output reflects only the flags. For example, a\n`GitHubActionProject`'s `test-dogfood.yml` is still the failing placeholder.\nThe second command applies everything in the rc (`dogfood`, `environments`,\nmodules, and so on).\n\n**Option 2 (Java types and `GitHubActionProject`): run the rc directly,\nonce.** The CDK types run their rc differently, so for those use option 1.\nInstall what the rc imports, give\nts-node a placeholder `tsconfig.projen.json` (the synth overwrites it with the\ngenerated one), and run the same command the generated `default` task runs:\n\n```bash\nnpm i -D projen @xpertss/projen-types constructs\necho '{}' > tsconfig.projen.json\nnpx -y -p ts-node@10.9.2 -p typescript@6.0.3 ts-node --project tsconfig.projen.json .projenrc.ts\nnpx projen\n```\n\nThe `echo` line works in bash and PowerShell. Don't drop `--project`: without\na tsconfig, ts-node fails on Node 22+ with `Unknown file extension \".ts\"`.\n\nEither way, commit `.projen/` along with the rest of the scaffold. A fresh\nclone then has its `tasks.json`, and `npx projen` works there straight away.\n\n## Updating an existing project when this package changes\n\nYour generated scaffold reflects the *installed* version of `@xpertss/projen-types` - `npx projen` reads your project type from the package in `node_modules`, not from this repository. So when this package ships a change (a bug fix, a new generated file, or altered workflow behavior), an existing project picks it up by bumping the dependency and re-synthesizing. A stale `node_modules` silently regenerates with the old behavior, so the bump is the load-bearing step.\n\nUsing the [`auto-commit` action](#githubactionproject) as a running example, say a new release adds the `# Purpose:` workflow header and SonarCloud wording. In the `auto-commit` repo:\n\n```bash\nnpm view @xpertss/projen-types version # what's the newest release?\nnpm i -D @xpertss/projen-types@latest # bump the installed project type\nnpx projen # re-synthesize every generated file\ngit diff # review before committing\n```\n\nThe diff here is the workflows gaining a `# Purpose:` comment and `sonar.yml` reflecting the SonarCloud wording. Commit the result with a normal `chore:` or `fix:` message - you never hand-edit the generated files themselves.\n\n## Examples\n\nEach example shows the `projen new` command first, then a fuller\n`.projenrc.ts`. Run the command first, then replace the generated\n`.projenrc.ts` with the example (or merge it in) and run `npx projen`. If you\npasted the example into a fresh repo first instead, see\n[Starting from an existing `.projenrc.ts`](#starting-from-an-existing-projenrcts).\n\n### CdkInfraProject\n\nPure infrastructure stacks with optional ECR/ECS and edge-networking constructs.\n\nScaffold it with the `cdk_infra` type:\n\n```bash\nnpx projen new --from @xpertss/projen-types cdk_infra --name media-edge-infra\n```\n\n```typescript\n// .projenrc.ts\nimport { CdkInfraProject } from '@xpertss/projen-types';\n\nconst project = new CdkInfraProject({\n name: 'media-edge-infra',\n environments: [\n 'dev',\n { name: 'stage', accountId: '111111111111', region: 'eu-central-1' },\n { name: 'prod', accountId: '222222222222', region: 'eu-central-1', requiresApproval: true },\n ],\n edgeResources: ['cloudfront', 'route53', 'sqs'],\n ecrEcs: { enabled: true, externalImageSource: true },\n});\n\nproject.synth();\n```\n\nYou get:\n\n- `cdk.json`, `cdk synth` / `cdk diff` / `cdk deploy` tasks, and the standard `AwsCdkTypeScriptApp` layout (CDK 2.189.1 by default).\n- `.github/workflows/build.yml` - PR build that hard-fails on projen drift.\n- `.github/workflows/deploy.yml` - manual dispatch with one `deploy-<env>` job per environment (runs `cdk deploy --all` with `--context environment=<env>`); `requiresApproval` environments get a GitHub Environment approval gate.\n- `src/constructs/edge-networking.ts` - helper constructs only for the requested `edgeResources` (`cloudfront`, `route53`, `apigateway`, `cognito`, `sqs`).\n- `src/constructs/ecr-ecs.ts` when `ecrEcs.enabled` - ECR repo + Fargate service; `externalImageSource: true` (default) means the service pulls an image built outside this repo.\n\n### CdkAppProject\n\n`CdkInfraProject` plus application source, a database construct, and an app-level build workflow.\n\nScaffold it with the `cdk_app` type:\n\n```bash\nnpx projen new --from @xpertss/projen-types cdk_app --name video-api\n```\n\n```typescript\n// .projenrc.ts\nimport { CdkAppProject } from '@xpertss/projen-types';\n\nconst project = new CdkAppProject({\n name: 'video-api',\n environments: ['dev', 'prod'],\n edgeResources: ['apigateway'],\n database: { engine: 'postgres', migrationTool: 'flyway' },\n appEntryPoint: 'src/app.ts',\n});\n\nproject.synth();\n```\n\nEverything from `CdkInfraProject`, plus:\n\n- `src/app.ts` - application entrypoint stub (`export function handler()`).\n- `src/handlers/example.ts` - API Gateway proxy handler stub, with `@types/aws-lambda` added as a dev dependency.\n- `src/constructs/database.ts` - a `Database` construct stub for the chosen engine (`postgres`/`mysql` -> RDS, `dynamodb` -> DynamoDB). `migrationTool` (no default, intentionally) is added as a dev dependency and referenced in the stub - wiring it up is left to you.\n- `.github/workflows/app-build.yml` - runs the project's test task on every PR, then checks for projen drift.\n\n### JavaMavenProject\n\nA plain Maven build with no framework and no publish target. It's the base of every other Java type, and it's usable on its own. It's single-module until you add a module, then it's a multi-module reactor.\n\nScaffold it with the `java_maven` type:\n\n```bash\nnpx projen new --from @xpertss/projen-types java_maven --name legacy-tools --group-id org.xpertss --artifact-id legacy-tools --java-version 1.8\n```\n\n**Single module:**\n\n```typescript\n// .projenrc.ts\nimport { JavaMavenProject } from '@xpertss/projen-types';\n\nconst project = new JavaMavenProject({\n name: 'legacy-tools',\n groupId: 'org.xpertss',\n artifactId: 'legacy-tools',\n javaVersion: '1.8',\n});\n\nproject.addDependency('commons-io/commons-io@2.20.0'); // exact version\nproject.addTestDependency('org.assertj/assertj-core@3.27.3');\n\nproject.synth();\n```\n\n**Multi-module:** each `addModule()` call adds a module directory with its own generated `pom.xml`. The root pom becomes the `pom`-packaged reactor parent. Everything stays one projen project, with one `.projen/`, one `.gitignore` and one `tasks.json`.\n\n```typescript\n// .projenrc.ts\nimport { JavaMavenProject } from '@xpertss/projen-types';\n\nconst project = new JavaMavenProject({\n name: 'toolkit',\n groupId: 'org.xpertss.toolkit',\n artifactId: 'toolkit-parent',\n version: '0.1.0-SNAPSHOT',\n javaVersion: '17',\n});\n\nconst model = project.addModule({ dir: 'toolkit-model', artifactId: 'toolkit-model', description: 'Domain model' });\nconst stub = project.addModule({ dir: 'tools/stub-model', artifactId: 'toolkit-stub-model' }); // nested dirs are fine\nconst cli = project.addModule({ dir: 'toolkit-cli', artifactId: 'toolkit-cli' });\n\nstub.addModuleDependency(model); // sibling module: versionless\ncli.addModuleDependency(model);\ncli.addDependency('info.picocli/picocli@4.7.7'); // pinned: the version moves to the parent\ncli.addDependency('org.yaml/snakeyaml'); // versionless: managed below\nproject.addManagedDependency('org.yaml/snakeyaml@2.4');\nproject.addBom('org.testcontainers/testcontainers-bom@1.21.3');\n\nproject.synth();\n```\n\nWhat the reactor looks like:\n\n- **Root `pom.xml`:**\n - `<packaging>pom</packaging>`, with `<modules>` in `addModule` order.\n - `<dependencyManagement>` holds the BOM imports first (`type=pom`, `scope=import`), then every module at `${project.version}`, then every pinned version.\n - `<pluginManagement>` holds the plugin versions, and versionless `<plugins>` are inherited by every module: compiler, surefire, failsafe, jar, and enforcer.\n - `junit-jupiter` is a test dependency every module inherits. Its version comes from `junit-bom`, or from the Spring Boot BOM in the Spring Boot types.\n- **Module `pom.xml`:** `<parent>` with the right `relativePath` (`tools/stub-model` → `../../pom.xml`), then `artifactId`, `name`, `description`, and versionless `<dependencies>`. Nothing else, unless the module adds plugins.\n- A version given to `module.addDependency`/`addTestDependency`/`addPlugin` is moved into the parent's `<dependencyManagement>`/`<pluginManagement>`, so every module that uses an artifact gets the same version. Pinning one artifact at two different versions fails the synth.\n- The synth fails with a clear message on:\n - two modules with the same `artifactId`\n - two modules with the same `dir`, or one `dir` nested inside another\n - a `dir` outside the repo\n - a module depending on itself\n - `packaging` set to anything but `pom` on a project with modules\n\nYou get:\n\n- the root `pom.xml` (and one per module), written by this package:\n - **exact versions only**: a range such as `^1`, `~1.2` or `[1,2)` fails the synth\n - the compiler level, enforcer rule and JUnit line all follow `javaVersion`\n- one Maven run per build. `npx projen build` synthesizes, then runs `mvn -B verify`: compile, unit tests (surefire), package, and `*IT` integration tests (failsafe). There is no `mvn deploy` and no `dist/`.\n- `.github/workflows/build.yml`: a PR build that installs the pinned Node toolchain (`npm ci`) and the project's JDK (`actions/setup-java`, Maven cache), then runs `npx projen build`, plus a SonarQube step when `sonarProjectKey` is set. See [Adding CI jobs](#adding-ci-jobs-to-a-java-project).\n- `.github/workflows/upgrade.yml`: a nightly (03:00 UTC) **report** of available dependency and plugin updates in the job summary. It changes nothing, because every version comes from `.projenrc.ts`; apply an update there. Turn it off with `upgradeWorkflow: false`. The same report runs locally with `npx projen upgrade`.\n- the projen drift check, `LICENSE` (MIT by default), `.editorconfig`, and a generated `package.json` that pins the projen toolchain exactly.\n- no sample code, unless `sample: true` on a single-module project.\n\n### JavaLibraryProject\n\nA reusable Java library published to Maven Central.\n\nScaffold it with the `java_library` type:\n\n```bash\nnpx projen new --from @xpertss/projen-types java_library --name common-utils --group-id org.xpertss --artifact-id common-utils\n```\n\n```typescript\n// .projenrc.ts\nimport { JavaLibraryProject } from '@xpertss/projen-types';\n\nconst project = new JavaLibraryProject({\n name: 'common-utils',\n groupId: 'org.xpertss',\n artifactId: 'common-utils',\n version: '1.0.0',\n sonarProjectKey: 'org.xpertss:common-utils',\n mavenCentralOidc: true,\n});\n\nproject.synth();\n```\n\nYou get everything from [`JavaMavenProject`](#javamavenproject), so modules work here too, plus:\n\n- `maven-source-plugin` and `maven-javadoc-plugin`, attaching the `-sources`/`-javadoc` jars Maven Central requires. In a multi-module library every module attaches them.\n- `.github/workflows/publish-maven-central.yml` - manual dispatch running `mvn -B deploy -P release`. With `mavenCentralOidc: true` it uses Maven Central's OIDC trusted publishing (no GPG secrets needed); otherwise it expects the secrets `MAVEN_GPG_PRIVATE_KEY`, `MAVEN_GPG_PASSPHRASE`, `MAVEN_CENTRAL_USERNAME`, `MAVEN_CENTRAL_PASSWORD`.\n- `.github/workflows/codeindex.yml` - on push to `main`, generates a Java source index under `.cai/` covering every module (disable with `publishCodeIndex: false`).\n\n### JavaSpringBootProject\n\nSpring Boot on Maven, single- or multi-module, **without** Docker, Flyway or a deploy hook. It's [`JavaMavenProject`](#javamavenproject) plus Spring Boot dependency management. Use it for a Spring Boot repo that ships something other than this package's container image, such as a multi-module control plane, or for a Boot app you deploy your own way.\n\nScaffold it with the `java_spring_boot` type:\n\n```bash\nnpx projen new --from @xpertss/projen-types java_spring_boot --name obeya --group-id org.xpertss.obeya --artifact-id obeya-parent\n```\n\n```typescript\n// .projenrc.ts\nimport { JavaSpringBootProject } from '@xpertss/projen-types';\n\nconst project = new JavaSpringBootProject({\n name: 'obeya',\n groupId: 'org.xpertss.obeya',\n artifactId: 'obeya-parent',\n version: '0.1.0-SNAPSHOT',\n javaVersion: '21',\n copyrightOwner: 'Xpert Software',\n});\n\n// plain jar modules: shared libraries, clients, tools\nconst model = project.addModule({ dir: 'obeya-model', artifactId: 'obeya-model' });\nconst client = project.addModule({ dir: 'obeya-api-client', artifactId: 'obeya-api-client' });\nclient.addModuleDependency(model);\n\n// a Spring Boot application module, repackaged into an executable jar\nconst server = project.addSpringBootModule({ dir: 'obeya-server', artifactId: 'obeya-server' });\nserver.addModuleDependency(model);\nserver.addDependency('org.springframework.boot/spring-boot-starter-web'); // versionless: Boot's BOM manages it\nserver.addTestDependency('org.springframework.boot/spring-boot-starter-test');\n\nproject.addBom('org.testcontainers/testcontainers-bom@1.21.3');\n\nproject.synth();\n```\n\nYou get everything from [`JavaMavenProject`](#javamavenproject), plus:\n\n- `spring-boot-dependencies` imported as the **first** BOM, so starters and every library Boot manages (JUnit included) are added without a version. `springBootVersion` sets it; the default is the newest release of the line that supports `javaVersion` (see [Java version support](#java-version-support)).\n- `spring-boot-maven-plugin`, versioned in `<pluginManagement>`:\n - In a **single-module** project the root jar is repackaged into an executable jar.\n - In a **multi-module** project only modules added with `addSpringBootModule()` are repackaged; `addModule()` modules stay plain jars.\n - A repackaged module needs its `@SpringBootApplication` class before `mvn verify` passes, because `repackage` fails with `Unable to find main class` until one exists. Add a module as a plain `addModule()` while it's still empty.\n- failsafe configured to run integration tests against the compiled classes rather than the repackaged jar (as `spring-boot-starter-parent` does).\n- no starters, no Docker, no Flyway, no CDK. Add the starters you need with `addDependency`.\n\n### JavaServiceProject\n\nA Spring Boot service that publishes a Docker image and can trigger deploys in a companion CDK repo. It is [`JavaSpringBootProject`](#javaspringbootproject) plus Docker, Flyway and a deploy hook. It is **single-module**, because the Docker build, the migrations and the deploy hook all assume one deployable at the repo root; `addModule()` fails and points you to `JavaSpringBootProject`.\n\nScaffold it with the `java_service` type:\n\n```bash\nnpx projen new --from @xpertss/projen-types java_service --name stream-processor --group-id org.xpertss --artifact-id stream-processor\n```\n\n```typescript\n// .projenrc.ts\nimport { JavaServiceProject } from '@xpertss/projen-types';\n\nconst project = new JavaServiceProject({\n name: 'stream-processor',\n groupId: 'org.xpertss',\n artifactId: 'stream-processor',\n dockerRegistry: 'docker.io/xpertss',\n cdkDeployTargetRepo: 'xpertss/stream-infra',\n environments: ['dev', { name: 'prod', requiresApproval: true }],\n});\n\nproject.synth();\n```\n\nYou get everything from [`JavaSpringBootProject`](#javaspringbootproject) (and so from `JavaMavenProject`), plus:\n\n- `spring-boot-starter-web` added to the pom (versionless; Boot's BOM manages it).\n- `.github/workflows/publish-docker.yml` - manual dispatch: `mvn -B package && docker build -t <registry>/<name>:<sha>`, logged in with the `DOCKER_USERNAME` / `DOCKER_PASSWORD` secrets. `dockerRegistry` defaults to `docker.io`.\n- Flyway wiring when `useFlyway` (default `true`): `flyway-core` (versionless, so it matches what Boot's Flyway auto-configuration expects), `flyway-maven-plugin` pinned for the Java line, and `src/main/resources/db/migration/V1__init.sql`.\n- `.github/workflows/deploy-cdk.yml` (the `CdkDeployHook`, generated by default) - manual dispatch with an environment selector; each job sends a `workflow_dispatch` to `deploy.yml` in the companion `cdkDeployTargetRepo` (a `CdkInfraProject`/`CdkAppProject` repo). With no `cdkDeployTargetRepo` set, the workflow is still generated but each job's only step fails with instructions - it is dispatch-only, so that lands on whoever tries to deploy rather than on every PR. Turn the workflow off entirely with `cdkDeployHook: false`. `environments` defaults to `['prod']`.\n\n### JavaAppProject\n\nA GUI/TUI/CLI Java application published to GitHub Packages only - no Maven Central, no Docker, no CDK deploy hook.\n\nScaffold it with the `java_app` type:\n\n```bash\nnpx projen new --from @xpertss/projen-types java_app --name studio-cli --group-id org.xpertss --artifact-id studio-cli\n```\n\n```typescript\n// .projenrc.ts\nimport { JavaAppProject } from '@xpertss/projen-types';\n\nconst project = new JavaAppProject({\n name: 'studio-cli',\n groupId: 'org.xpertss',\n artifactId: 'studio-cli',\n ghPackagesRegistry: 'https://maven.pkg.github.com/xpertss/studio-cli',\n});\n\nproject.synth();\n```\n\nYou get everything from [`JavaMavenProject`](#javamavenproject) (modules included), 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.\n\n### GitHubActionProject\n\nA reusable GitHub Action or Workflow. This example scaffolds an action that stages a folder and, only if it changed, commits and pushes it.\n\nScaffold it with the `git_hub_action` type:\n\n```bash\nnpx projen new --from @xpertss/projen-types git_hub_action --name auto-commit --sonar-host-url https://sonarcloud.io\n```\n\n```typescript\n// .projenrc.ts\nimport { GitHubActionProject } from '@xpertss/projen-types';\n\nconst project = new GitHubActionProject({\n name: 'auto-commit',\n description: 'Stage a folder and, only if it changed, commit and push it',\n sonarHostUrl: 'https://sonarcloud.io', // required, no default - your SonarCloud URL\n dogfood: {\n // Two scenario steps: the \"changed\" path and the \"no-op\" path are both\n // load-bearing behavior for this action (a double-commit or a\n // push-when-empty bug is the failure mode a hand-rolled inline-shell\n // alternative is most likely to introduce).\n scenario: [\n {\n name: 'Changed path',\n fixtureSteps: [\n 'echo \"$(date -u +%Y%m%dT%H%M%SZ)\" >> test/fixtures/dogfood-state.txt',\n ],\n inputs: {\n commit_message: 'test: dogfood',\n branches: 'test/dogfood',\n },\n assertions: [\n // step id defaults to a slug of `name` - here \"changed-path-0\"\n '[ \"${{ steps.changed-path-0.outputs.committed }}\" = \"true\" ]',\n ],\n },\n {\n // No fixture change this time - nothing new to commit.\n name: 'No-op path',\n id: 'no-op-check', // pin an explicit id instead of relying on the default slug\n inputs: {\n commit_message: 'test: dogfood',\n branches: 'test/dogfood',\n },\n assertions: [\n '[ \"${{ steps.no-op-check.outputs.committed }}\" = \"false\" ]',\n ],\n },\n ],\n cleanup: [\n 'git push origin --delete test/dogfood || true',\n ],\n },\n});\n\nproject.synth();\n```\n\nYou get:\n\n- `action.yml` and `auto-commit.sh` are hand-written - this type only lints their content via `build.yml`'s shellcheck/yamllint/actionlint checks.\n- `.github/workflows/build.yml` - lint gate: `apt`-installed shellcheck/yamllint plus a pinned, SHA-256-verified `actionlint` release binary. Gates `main` alongside `sonar.yml`.\n- `.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. Omit `dogfood` and the workflow still exists, with one step that fails on every PR until you declare a scenario - AD-001 allows a dogfood to be missing loudly, never silently. A *partial* `dogfood` (a scenario with no cleanup) is a synth error.\n- `.github/workflows/sonar.yml` - SonarCloud scan via the Scanner CLI (the quality gate blocks the PR), scanning `action.yml`/`.github/workflows/**`/`**/*.sh` explicitly.\n- `.github/workflows/release.yml` - `feat:`/`fix:` commits on `main` bump the version, tag `vX.Y.Z`, and create a GitHub Release.\n- `.github/workflows/projen-drift-check.yml` and `workflow-change-notice.yml` - drift detection and a change notice, always included.\n- `package.json` (**private**, version source only), `.yamllint`, `LICENSE` (MIT by default), and a `README.md` template - all regenerated by `npx projen`.\n\nNeeds 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 by running the `projen new` command above first (see [Getting started](#getting-started)), then replace the generated `.projenrc.ts` with the one above and run `npx projen`, then hand-write `action.yml`/`auto-commit.sh`/`test/fixtures/`. If you wrote the `.projenrc.ts` before running `projen new`, see [Starting from an existing `.projenrc.ts`](#starting-from-an-existing-projenrcts).\n\n## Java version support\n\n`javaVersion` picks the Java line a Java project targets. It defaults to `21`; the supported lines are `1.8` (alias `8`), `17`, `21` and `25`, and any other value fails the synth with that list. **Nothing in the generated build is hard-coded to one Java line.** Everything that depends on it comes from one table in this package, grouped by line:\n\n| | `1.8` | `17` | `21` | `25` |\n| --- | --- | --- | --- | --- |\n| Compiler level | `maven.compiler.source`/`target` = `1.8` (javac 8 has no `--release`) | `maven.compiler.release` = `17` | `release` = `21` | `release` = `25` |\n| Enforcer `requireJavaVersion` | `[1.8,)` | `[17,)` | `[21,)` | `[25,)` |\n| JUnit (`junit-bom`) | 5.14.4 (JUnit 6 needs Java 17) | 6.1.3 | 6.1.3 | 6.1.3 |\n| Default Spring Boot (`JavaSpringBootProject`) | 2.7.18 (Boot 3+ needs Java 17; a 3.x+ `springBootVersion` fails the synth) | 4.1.1 | 4.1.1 | 4.1.1 |\n| `flyway-maven-plugin` (`JavaServiceProject`) | 9.22.3 | 13.9.0 | 13.9.0 | 13.9.0 |\n| CI JDK (`actions/setup-java` `java-version`) | `8` | `17` | `21` | `25` |\n\nMaven plugins (the same on every line, because all of them run on JDK 8): `maven-compiler-plugin` 3.16.0, `maven-surefire-plugin`/`maven-failsafe-plugin` 3.6.0, `maven-jar-plugin` 3.5.1, `maven-enforcer-plugin` 3.6.3, `maven-source-plugin` 3.4.0 and `maven-javadoc-plugin` 3.12.0 (library only), `versions-maven-plugin` 2.22.0 (the `upgrade` report).\n\n**The enforcer.** `maven-enforcer-plugin` fails the build at the start when the JDK or Maven running it is older than the project needs. Without it you get confusing compiler errors later, or a jar built for the wrong runtime. Its Java rule always follows `javaVersion`. The Maven rule defaults to `[3.9,)`; change it with `minMavenVersion`, or drop the plugin entirely with `enforcer: false`. CI installs the matching JDK through `setup-java`, so the rule only fires on a developer machine with the wrong JDK. A Java 1.8 project builds on any newer JDK (the rule is a minimum), but the JDK 8 runtime API is guaranteed only when you build on JDK 8.\n\n**Overriding a version.** `pluginVersions` replaces any default in the table, keyed by `groupId/artifactId`, with an exact version:\n\n```typescript\nnew JavaMavenProject({\n name: 'svc',\n groupId: 'org.xpertss',\n artifactId: 'svc',\n pluginVersions: {\n 'org.apache.maven.plugins/maven-surefire-plugin': '3.5.6',\n 'org.junit/junit-bom': '5.14.4',\n },\n});\n```\n\n`project.pinnedVersion('org.apache.maven.plugins/maven-surefire-plugin')` returns the version in effect, for reuse in your own plugin config.\n\n**New Java lines** are one new row in this package's version table and a release. Until a line is listed, `javaVersion` rejects it rather than guessing.\n\n## Adding CI jobs to a Java project\n\n`build.yml` is exposed as `project.buildVerifyWorkflow`, so jobs are added through projen's `addJob` rather than `addOverride`. `project.ciSetupSteps` holds the steps every Maven job here needs: pinned Node, `npm ci`, and the project's JDK with a Maven cache. Every job in `build.yml` can then be made a required check on `main`.\n\n```typescript\nimport { github } from 'projen';\n\nproject.buildVerifyWorkflow.addJob('integration', {\n name: 'Container integration tests',\n runsOn: ['self-hosted', 'linux', 'fedora', 'podman'],\n permissions: { contents: github.workflows.JobPermission.READ },\n steps: [\n { name: 'Checkout', uses: 'actions/checkout@v7' },\n ...project.ciSetupSteps,\n { name: 'Integration tests', run: 'mvn -B verify -Pcontainer-its' },\n ],\n});\n```\n\n## Common options\n\nCDK project types (`CdkInfraProjectOptions` / `CdkAppProjectOptions`):\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `name` | - (required) | Project name; must match `package.json` |\n| `cdkVersion` | `2.189.1` | AWS CDK version |\n| `gheTokenSecret` | `PROJEN_GITHUB_TOKEN` | GitHub secret holding projen's PAT |\n| `environments` | - (no `deploy` workflow) | Deploy targets for the `deploy` workflow; strings or `EnvironmentOptions` |\n| `ecrEcs` | - | `EcrEcsOptions` - `enabled`, `externalImageSource` (default `true`) |\n| `edgeResources` | - | Subset of `cloudfront`, `route53`, `apigateway`, `cognito`, `sqs` |\n| `database` | - (app only) | `DatabaseOptions` - `engine` (`postgres`/`mysql`/`dynamodb`, default `postgres`), `migrationTool` |\n| `appEntryPoint` | `src/app.ts` (app only) | Path of the generated application entrypoint |\n\nJava project types (`JavaMavenProjectOptions` and everything built on it - `JavaLibraryProjectOptions`, `JavaAppProjectOptions`, `JavaSpringBootProjectOptions`, `JavaServiceProjectOptions`):\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `name` | - (required) | Project name |\n| `groupId` | - (required) | Maven group id |\n| `artifactId` | - (required) | Maven artifact id (of the reactor parent, in a multi-module project) |\n| `version` | `0.1.0` | Maven version; must be exact |\n| `description` / `url` | - | Written to the root pom |\n| `javaVersion` | `21` | Java line: `1.8`, `17`, `21`, `25` - see [Java version support](#java-version-support) |\n| `javaDistribution` | `temurin` | `actions/setup-java` distribution for CI |\n| `packaging` | `jar` | Root packaging while the project has no modules; a project with modules is always `pom` |\n| `sample` | `false` | Starter `Main` + test under the `groupId` package (single-module only) |\n| `enforcer` | `true` | `maven-enforcer-plugin` with Maven and Java version rules |\n| `minMavenVersion` | `3.9` | The enforcer's `requireMavenVersion` minimum |\n| `pluginVersions` | - | Exact-version overrides for this package's defaults, keyed by `groupId/artifactId` |\n| `licensed` | `true` | Write a `LICENSE` |\n| `license` | `MIT` | SPDX identifier for the `LICENSE` |\n| `copyrightOwner` / `copyrightPeriod` | `xpertss` / current year | Named in the `LICENSE` |\n| `editorconfig` | `true` | Write a projen-managed `.editorconfig` (also on the CDK and action types) |\n| `upgradeWorkflow` | `true` | Generate the nightly update report (`upgrade.yml`) |\n| `sonarProjectKey` | - | SonarQube project key; the sonar step is skipped when unset |\n| `gheTokenSecret` | `PROJEN_GITHUB_TOKEN` | GitHub secret holding projen's PAT |\n| `springBootVersion` | newest Boot for `javaVersion` (Spring Boot types only) | Exact Spring Boot version: the BOM and `spring-boot-maven-plugin` |\n| `cdkDeployTargetRepo` | - (service only; `deploy-cdk.yml` fails until set) | Companion CDK repo (`owner/repo`) whose `deploy.yml` the deploy hook dispatches |\n| `cdkDeployHook` | `true` (service only) | Whether to generate `deploy-cdk.yml` at all |\n| `dockerRegistry` | `docker.io` (service only) | Registry the Docker image is pushed to |\n| `useFlyway` | `true` (service only) | Flyway plugin/dependency + `V1__init.sql` |\n\nWith the default MIT license, the generated `LICENSE` looks like:\n\n```\nMIT License\n\nCopyright (c) 2024-2026 Xpert Software\n\nPermission is hereby granted, ...\n```\n\nThe header line (`MIT License`) is specific to the license type — an `Apache-2.0` project would instead show `Apache-2.0`.\n\nOverride the license type and copyright fields:\n\n```typescript\nnew JavaMavenProject({\n name: 'my-lib',\n groupId: 'org.xpertss',\n artifactId: 'my-lib',\n license: 'Apache-2.0', // any SPDX id projen ships a template for\n copyrightOwner: 'Xpert Software',\n copyrightPeriod: '2024-2026',\n});\n```\n\n`EnvironmentOptions` for deploy targets:\n\n```text\ninterface EnvironmentOptions {\n readonly name: string; // e.g. \"dev\", \"stage\", \"prod\"\n readonly accountId?: string; // AWS account id (CDK deploys)\n readonly region?: string; // AWS region (CDK deploys)\n readonly requiresApproval?: boolean; // GitHub Environment approval gate (default false)\n}\n```\n\nPlain strings (`'dev'`) are shorthand for `{ name: 'dev' }`.\n\n`GitHubActionProjectOptions`:\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `name` | - (required) | Project name |\n| `description` | - | One-line description; used in the default README template and recorded in the private `package.json` |\n| `sonarHostUrl` | - (required) | URL of your SonarCloud instance (e.g. `https://sonarcloud.io`); must be reachable from github.com-hosted runners |\n| `sonarTokenSecret` | `SONAR_TOKEN` | GitHub secret holding the Sonar token |\n| `sonarPullRequestGate` | `true` | Whether `sonar.yml` also runs on `pull_request` as a pass/fail gate |\n| `dogfood` | - (a `test-dogfood.yml` that fails until you declare one) | `ActionDogfoodOptions` - the scenario that exercises the action end-to-end via `uses: ./` |\n| `license` | `MIT` | SPDX identifier for the generated `LICENSE` |\n| `gheTokenSecret` | `PROJEN_GITHUB_TOKEN` | GitHub secret holding projen's PAT |\n\n`ActionDogfoodOptions`/`ActionDogfoodStep` - the dogfood scenario (`test-dogfood.yml`):\n\n```text\ninterface ActionDogfoodOptions {\n readonly scenario: ActionDogfoodStep[]; // one or more, run in order - required\n readonly cleanup: string[]; // shared, run once at the end with `if: always()` - required\n}\n\ninterface ActionDogfoodStep {\n readonly name: string; // labels this step-group's generated workflow steps\n readonly id?: string; // step id for the `uses: ./` call; default: a slug of `name`\n readonly fixtureSteps?: string[]; // shell, before the invocation (default: none)\n readonly inputs?: Record<string, string>; // `with:` for this invocation (default: none)\n readonly assertions: string[]; // shell, after the invocation - required, job fails unless all exit 0\n}\n```\n\nMost 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`.\n\n## Required GitHub secrets\n\n| Secret | Used by | Notes |\n| --- | --- | --- |\n| `PROJEN_GITHUB_TOKEN` | all types | PAT for projen's self-mutation/automation; override via `gheTokenSecret` |\n| `SONAR_TOKEN` | Java types with `sonarProjectKey`; `GitHubActionProject` | SonarQube scan step in `build.yml` / `sonar.yml`; override via `sonarTokenSecret` on `GitHubActionProject` |\n| `DOCKER_USERNAME` / `DOCKER_PASSWORD` | `JavaServiceProject` | Docker image push |\n| `MAVEN_GPG_PRIVATE_KEY`, `MAVEN_GPG_PASSPHRASE`, `MAVEN_CENTRAL_USERNAME`, `MAVEN_CENTRAL_PASSWORD` | `JavaLibraryProject` without `mavenCentralOidc` | Not needed with OIDC trusted publishing |\n\n## Customizing `.gitignore`\n\nEvery project type already ignores JetBrains IDE state (`/.idea/*`) and the `/spec/` directory with all of its subdirectories (local plans and specs, never committed). The Java types also ignore Maven `target/` output and Eclipse files. To ignore more, call the inherited `addGitIgnore()` method after constructing the project in your `.projenrc.ts`:\n\n```typescript\n// .projenrc.ts\nimport { CdkInfraProject } from '@xpertss/projen-types';\n\nconst project = new CdkInfraProject({\n name: 'my-infra',\n});\n\nproject.addGitIgnore('*.log');\nproject.addGitIgnore('.env.*');\nproject.addGitIgnore('/build/');\n\nproject.synth();\n```\n\nThe same works for every type - just swap the class (e.g. `JavaServiceProject`, `GitHubActionProject`). Each call takes one standard gitignore glob pattern. There is no `gitignore` constructor option: the project types' option interfaces do not expose one, so patterns go through `addGitIgnore()` instead.\n\nRe-run `npx projen` after editing - `.gitignore` is a generated file, so hand-editing it is caught by the drift check.\n\n## Troubleshooting\n\n**`Unable to find projen project. Use \"projen new\" to create a new project.`**\nIf the directory already has a `.projenrc.ts`, this error means the rc has\nnever been synthesized (there's no `.projen/tasks.json`), not that you need a\nnew project. See [Starting from an existing `.projenrc.ts`](#starting-from-an-existing-projenrcts).\n\n## Going further\n\nThe project types are composed from smaller components you can also attach to your own projects:\n\n| Component | Applies to | Purpose |\n| --- | --- | --- |\n| `AppRuntimeScaffold` | `NodeProject` | App source skeleton (`app.ts` + handlers) |\n| `DatabaseComponent` | `NodeProject` | Database construct stub + migration tool wiring |\n| `EcrEcsConstructs` | `Project` | ECR + Fargate ECS construct helper |\n| `EdgeNetworkingConstructs` | `Project` | Per-resource edge networking construct helpers |\n| `MavenPom` | `Project` | A `pom.xml` with modules, BOM imports, dependency/plugin management, and exact versions only |\n| `MavenModule` | `JavaMavenProject` | One module of a reactor (created by `addModule()`) |\n| `MavenUpgradeReport` | `GitHubProject` | Nightly report-only `upgrade.yml` |\n| `MavenCentralPublish` | `JavaMavenProject` | Manual-dispatch Maven Central publish workflow |\n| `DockerPublish` | `JavaMavenProject` | Manual-dispatch Docker build+push workflow |\n| `GitHubPackagesPublish` | `JavaMavenProject` | Manual-dispatch GitHub Packages publish workflow |\n| `FlywayMigration` | `JavaSpringBootProject` | Flyway plugin/dependency + migrations directory |\n| `CdkDeployHook` | `JavaMavenProject` | Manual-dispatch workflow that triggers `deploy.yml` in a companion CDK repo |\n| `CodeIndexWorkflow` | `JavaMavenProject` | Code index generation on push to `main` |\n| `ActionBuildWorkflow` | `GitHubProject` | The `lint` task (shellcheck/yamllint/pinned actionlint) + `build.yml` |\n| `ActionDogfoodWorkflow` | `GitHubProject` | `test-dogfood.yml` from an `ActionDogfoodOptions` scenario |\n| `ActionSonarWorkflow` | `GitHubProject` | `sonar.yml` (SonarCloud scan via the Scanner CLI) |\n\nExample - adding a Docker publish to a `JavaMavenProject` (`JavaServiceProject` is the packaged version of this, with Spring Boot):\n\n```typescript\nimport { DockerPublish, JavaMavenProject } from '@xpertss/projen-types';\n\nconst project = new JavaMavenProject({\n name: 'my-service',\n groupId: 'org.xpertss',\n artifactId: 'my-service',\n});\n\nnew DockerPublish(project, { dockerRegistry: 'ghcr.io' });\n\nproject.synth();\n```\n\nThe full API reference, including every option and property, is in [API.md](./API.md).\n"
|
|
109
|
+
"markdown": "# @xpertss/projen-types\n\nProjen project types for CDK/TypeScript and Java/Maven projects.\n\nInstead of hand-maintaining `pom.xml`, `cdk.json`, and GitHub workflows, you declare a project type in a `.projenrc.ts` 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.\n\n## Project types at a glance\n\n| Type | What it is | Publishes to | Generated workflows |\n| --- | --- | --- | --- |\n| `CdkInfraProject` | Pure-infrastructure CDK stacks (CloudFront, Route53, SQS, API Gateway, Cognito, ECR/ECS for externally-built images) | - | `build` (PR checks), `deploy` (manual dispatch) |\n| `CdkAppProject` | Full TypeScript service behind API Gateway: infra + app source + database | - | `build`, `deploy`, `app-build` (PR checks) |\n| `JavaMavenProject` | Plain Maven project, single- or multi-module, no framework | - | `build`, `upgrade` (nightly report) |\n| `JavaLibraryProject` | Reusable Java library | Maven Central | `build`, `upgrade` (nightly report), `publish-maven-central`, `codeindex` |\n| `JavaAppProject` | GUI/TUI/CLI Java application | GitHub Packages | `build`, `upgrade` (nightly report), `publish-ghpackages` |\n| `JavaSpringBootProject` | Spring Boot on Maven, single- or multi-module, **no Docker** | - | `build`, `upgrade` (nightly report) |\n| `JavaServiceProject` | Spring Boot service deployed as a container | Docker Hub | `build`, `upgrade` (nightly report), `publish-docker`, `deploy-cdk` |\n| `GitHubActionProject` | Reusable GitHub Action or Workflow | GitHub Releases | `build`, `test-dogfood`, `sonar`, `release` |\n\nThe Java types are layered, so pick the lowest layer that does what you need:\n\n```text\nJavaMavenProject java_maven Maven only; single- or multi-module; any supported Java line\n├── JavaLibraryProject java_library + Maven Central publish, source/javadoc jars, code index\n├── JavaAppProject java_app + GitHub Packages publish\n└── JavaSpringBootProject java_spring_boot + Spring Boot BOM and executable-jar repackaging; no Docker/Flyway/CDK\n └── JavaServiceProject java_service + Docker publish, Flyway, CDK deploy hook (single-module)\n```\n\nEvery Java type targets a configurable Java line (`javaVersion`: `1.8`, `17`, `21` or `25`; see [Java version support](#java-version-support)), and every one except `JavaServiceProject` can be a multi-module Maven reactor (see [JavaMavenProject](#javamavenproject)).\n\nOne foundation class is also exported for advanced use: `CdkTypescriptProject` (shared CDK + TypeScript base for the CDK types).\n\nAll project types:\n\n- run a **drift check** in PR builds - a job that re-runs projen and fails if generated files were hand-edited. Edit `.projenrc.ts`, then run `npx projen`; never edit generated files directly.\n- use the GitHub secret `PROJEN_GITHUB_TOKEN` (a fine-grained PAT) for projen's automation. Override with `gheTokenSecret`.\n- make all publishing/deploying **manual** (workflow_dispatch) rather than on every merge.\n\n## Getting started\n\nHow you start depends on what is already in the directory:\n\n| Starting point | Do this |\n| --- | --- |\n| Empty directory | `projen new --from` (below) |\n| Existing repo, no `.projenrc.ts` | `projen new --from ... --no-git` (below) |\n| A `.projenrc.ts` but no `.projen/` directory - copied from another repo, or one of the [examples](#examples) pasted into a fresh repo | [Starting from an existing `.projenrc.ts`](#starting-from-an-existing-projenrcts) |\n\nScaffold the repo with projen's own bootstrap, pointed at this package:\n\n```bash\nmkdir my-project && cd my-project\ngit init\nnpx projen new --from @xpertss/projen-types cdk_infra --name my-project\n```\n\nThat writes a starter `.projenrc.ts`, synthesizes the whole scaffold and\ninstalls dependencies. The type names `projen new` accepts are `cdk_infra`,\n`cdk_app`, `java_maven`, `java_library`, `java_app`, `java_spring_boot`,\n`java_service` and `git_hub_action`; pass a bogus one to have it list them.\nRequired options become flags: `--name` for every type, plus\n`--group-id`/`--artifact-id` (Java) and `--sonar-host-url`\n(`git_hub_action`). Any other plainly-typed option can be passed the same\nway - `--java-version 1.8`, `--cdk-deploy-target-repo owner/repo`,\n`--docker-registry ghcr.io`, `--no-use-flyway`, and so on. Modules can't be\npassed on the command line; add them to `.projenrc.ts` afterwards (see\n[JavaMavenProject](#javamavenproject)).\n\n**Adding projen to a repo that already has content.** `projen new` runs\n`git init` and commits the scaffold by default. In a repo with existing work,\npass `--no-git` so it writes the files and leaves committing to you:\n\n```bash\ncd existing-repo\nnpx projen new --from @xpertss/projen-types java_spring_boot --name obeya --group-id org.xpertss.obeya --artifact-id obeya-parent --no-git\n```\n\n**Commit a lockfile.** The generated `build.yml` and drift check install the\ntoolchain with `npm ci`, which needs a committed `package-lock.json`, and\n`projen new` doesn't always leave one behind. Run `npm install` once and\ncommit `package-lock.json` along with the scaffold. Without it those\nworkflows fail with an `::error::` that says exactly this. For the Java\ntypes, `package.json` is generated, and it pins `projen` and\n`@xpertss/projen-types` to **exact** versions (no `^`), so every machine and\nCI run uses the same generator. A floating range would make the drift check\nreport the differences between generator versions as drift.\n\nCommit the result. From then on, every change to the scaffold goes through\n`.projenrc.ts` followed by `npx projen`:\n\n```bash\nnpx projen\n```\n\nEvery type scaffolds from that one command; no option is *required* that\n`projen new` cannot pass. The structured options - `environments` and\n`GitHubActionProject`'s `dogfood` - are ones projen's CLI cannot render\ninto a projenrc, so they are added afterwards by editing `.projenrc.ts` and\nre-running `npx projen`. Leaving `environments` out simply generates no\ndeploy workflow; leaving `dogfood` out (or a service's\n`cdkDeployTargetRepo`) still generates the workflow, with one step that\nfails and tells you what to add - a gate this package considers load-bearing\nis allowed to be missing loudly, never silently.\n\nThe `name` option must match the `name` field in the project's `package.json` (for the CDK types). For the Java types it becomes the root pom's `<name>` and the generated `package.json` name.\n\n> **Never write projen's generated-file marker text literally in `.projenrc.ts`.** projen deletes, as an orphaned generated file, any file containing the marker line (`~~ Generated by projen. To modify, ...`), and that includes `.projenrc.ts` itself. When you generate a file yourself (for example with `TextFile`), insert the marker through the file's `marker` property: ``file.addLine(`# ${file.marker}`)``.\n\n## Starting from an existing `.projenrc.ts`\n\nA directory that has a `.projenrc.ts` but no `.projen/` directory has never\nbeen synthesized. This happens when you copy the rc from another repo, or paste\none of the [examples](#examples) into a fresh repo. In that state `npx projen`\nfails with:\n\n```\n👾 Unable to find projen project. Use \"projen new\" to create a new project.\n```\n\n`npx projen` doesn't run `.projenrc.ts` itself. It runs the `default` task\nlisted in `.projen/tasks.json`, and that file is written by the first synth.\nDo the first synth one of these two ways. After that, `npx projen` works as\nusual.\n\n**Option 1 (recommended): run `projen new` over the existing rc.** `projen\nnew` leaves an existing `.projenrc.ts` untouched and writes the rest of the\nscaffold, `.projen/` included. Pass the type and its required flags as you\nwould for a new repo. Their values don't have to match your rc, because the\n`npx projen` that follows re-synthesizes everything from the rc:\n\n```bash\nnpx projen new --from @xpertss/projen-types git_hub_action --name pull-request --sonar-host-url https://sonarcloud.io --no-git\nnpx projen\n```\n\nThe first command's output reflects only the flags. For example, a\n`GitHubActionProject`'s `test-dogfood.yml` is still the failing placeholder.\nThe second command applies everything in the rc (`dogfood`, `environments`,\nmodules, and so on).\n\n**Option 2 (Java types and `GitHubActionProject`): run the rc directly,\nonce.** The CDK types run their rc differently, so for those use option 1.\nInstall what the rc imports, give\nts-node a placeholder `tsconfig.projen.json` (the synth overwrites it with the\ngenerated one), and run the same command the generated `default` task runs:\n\n```bash\nnpm i -D projen @xpertss/projen-types constructs\necho '{}' > tsconfig.projen.json\nnpx -y -p ts-node@10.9.2 -p typescript@6.0.3 ts-node --project tsconfig.projen.json .projenrc.ts\nnpx projen\n```\n\nThe `echo` line works in bash and PowerShell. Don't drop `--project`: without\na tsconfig, ts-node fails on Node 22+ with `Unknown file extension \".ts\"`.\n\nEither way, commit `.projen/` along with the rest of the scaffold. A fresh\nclone then has its `tasks.json`, and `npx projen` works there straight away.\n\n## Updating an existing project when this package changes\n\nYour generated scaffold reflects the *installed* version of `@xpertss/projen-types` - `npx projen` reads your project type from the package in `node_modules`, not from this repository. So when this package ships a change (a bug fix, a new generated file, or altered workflow behavior), an existing project picks it up by bumping the dependency and re-synthesizing. A stale `node_modules` silently regenerates with the old behavior, so the bump is the load-bearing step.\n\nUsing the [`auto-commit` action](#githubactionproject) as a running example, say a new release adds the `# Purpose:` workflow header and SonarCloud wording. In the `auto-commit` repo:\n\n```bash\nnpm view @xpertss/projen-types version # what's the newest release?\nnpm i -D @xpertss/projen-types@latest # bump the installed project type\nnpx projen # re-synthesize every generated file\ngit diff # review before committing\n```\n\nThe diff here is the workflows gaining a `# Purpose:` comment and `sonar.yml` reflecting the SonarCloud wording. Commit the result with a normal `chore:` or `fix:` message - you never hand-edit the generated files themselves.\n\n## Examples\n\nEach example shows the `projen new` command first, then a fuller\n`.projenrc.ts`. Run the command first, then replace the generated\n`.projenrc.ts` with the example (or merge it in) and run `npx projen`. If you\npasted the example into a fresh repo first instead, see\n[Starting from an existing `.projenrc.ts`](#starting-from-an-existing-projenrcts).\n\n### CdkInfraProject\n\nPure infrastructure stacks with optional ECR/ECS and edge-networking constructs.\n\nScaffold it with the `cdk_infra` type:\n\n```bash\nnpx projen new --from @xpertss/projen-types cdk_infra --name media-edge-infra\n```\n\n```typescript\n// .projenrc.ts\nimport { CdkInfraProject } from '@xpertss/projen-types';\n\nconst project = new CdkInfraProject({\n name: 'media-edge-infra',\n environments: [\n 'dev',\n { name: 'stage', accountId: '111111111111', region: 'eu-central-1' },\n { name: 'prod', accountId: '222222222222', region: 'eu-central-1', requiresApproval: true },\n ],\n edgeResources: ['cloudfront', 'route53', 'sqs'],\n ecrEcs: { enabled: true, externalImageSource: true },\n});\n\nproject.synth();\n```\n\nYou get:\n\n- `cdk.json`, `cdk synth` / `cdk diff` / `cdk deploy` tasks, and the standard `AwsCdkTypeScriptApp` layout (CDK 2.189.1 by default).\n- `.github/workflows/build.yml` - PR build that hard-fails on projen drift.\n- `.github/workflows/deploy.yml` - manual dispatch with one `deploy-<env>` job per environment (runs `cdk deploy --all` with `--context environment=<env>`); `requiresApproval` environments get a GitHub Environment approval gate.\n- `LICENSE` (MIT by default), `.editorconfig`, and the projen drift check.\n- `src/constructs/edge-networking.ts` - helper constructs only for the requested `edgeResources` (`cloudfront`, `route53`, `apigateway`, `cognito`, `sqs`).\n- `src/constructs/ecr-ecs.ts` when `ecrEcs.enabled` - ECR repo + Fargate service; `externalImageSource: true` (default) means the service pulls an image built outside this repo.\n\n### CdkAppProject\n\n`CdkInfraProject` plus application source, a database construct, and an app-level build workflow.\n\nScaffold it with the `cdk_app` type:\n\n```bash\nnpx projen new --from @xpertss/projen-types cdk_app --name video-api\n```\n\n```typescript\n// .projenrc.ts\nimport { CdkAppProject } from '@xpertss/projen-types';\n\nconst project = new CdkAppProject({\n name: 'video-api',\n environments: ['dev', 'prod'],\n edgeResources: ['apigateway'],\n database: { engine: 'postgres', migrationTool: 'flyway' },\n appEntryPoint: 'src/app.ts',\n});\n\nproject.synth();\n```\n\nEverything from `CdkInfraProject`, plus:\n\n- `src/app.ts` - application entrypoint stub (`export function handler()`).\n- `src/handlers/example.ts` - API Gateway proxy handler stub, with `@types/aws-lambda` added as a dev dependency.\n- `src/constructs/database.ts` - a `Database` construct stub for the chosen engine (`postgres`/`mysql` -> RDS, `dynamodb` -> DynamoDB). `migrationTool` (no default, intentionally) is added as a dev dependency and referenced in the stub - wiring it up is left to you.\n- `.github/workflows/app-build.yml` - runs the project's test task on every PR, then checks for projen drift.\n\n### JavaMavenProject\n\nA plain Maven build with no framework and no publish target. It's the base of every other Java type, and it's usable on its own. It's single-module until you add a module, then it's a multi-module reactor.\n\nScaffold it with the `java_maven` type:\n\n```bash\nnpx projen new --from @xpertss/projen-types java_maven --name legacy-tools --group-id org.xpertss --artifact-id legacy-tools --java-version 1.8\n```\n\n**Single module:**\n\n```typescript\n// .projenrc.ts\nimport { JavaMavenProject } from '@xpertss/projen-types';\n\nconst project = new JavaMavenProject({\n name: 'legacy-tools',\n groupId: 'org.xpertss',\n artifactId: 'legacy-tools',\n javaVersion: '1.8',\n});\n\nproject.addDependency('commons-io/commons-io@2.20.0'); // exact version\nproject.addTestDependency('org.assertj/assertj-core@3.27.3');\n\nproject.synth();\n```\n\n**Multi-module:** each `addModule()` call adds a module directory with its own generated `pom.xml`. The root pom becomes the `pom`-packaged reactor parent. Everything stays one projen project, with one `.projen/`, one `.gitignore` and one `tasks.json`.\n\n```typescript\n// .projenrc.ts\nimport { JavaMavenProject } from '@xpertss/projen-types';\n\nconst project = new JavaMavenProject({\n name: 'toolkit',\n groupId: 'org.xpertss.toolkit',\n artifactId: 'toolkit-parent',\n version: '0.1.0-SNAPSHOT',\n javaVersion: '17',\n});\n\nconst model = project.addModule({ dir: 'toolkit-model', artifactId: 'toolkit-model', description: 'Domain model' });\nconst stub = project.addModule({ dir: 'tools/stub-model', artifactId: 'toolkit-stub-model' }); // nested dirs are fine\nconst cli = project.addModule({ dir: 'toolkit-cli', artifactId: 'toolkit-cli' });\n\nstub.addModuleDependency(model); // sibling module: versionless\ncli.addModuleDependency(model);\ncli.addDependency('info.picocli/picocli@4.7.7'); // pinned: the version moves to the parent\ncli.addDependency('org.yaml/snakeyaml'); // versionless: managed below\nproject.addManagedDependency('org.yaml/snakeyaml@2.4');\nproject.addBom('org.testcontainers/testcontainers-bom@1.21.3');\n\nproject.synth();\n```\n\nWhat the reactor looks like:\n\n- **Root `pom.xml`:**\n - `<packaging>pom</packaging>`, with `<modules>` in `addModule` order.\n - `<dependencyManagement>` holds the BOM imports first (`type=pom`, `scope=import`), then every module at `${project.version}`, then every pinned version.\n - `<pluginManagement>` holds the plugin versions, and versionless `<plugins>` are inherited by every module: compiler, surefire, failsafe, jar, and enforcer.\n - `junit-jupiter` is a test dependency every module inherits. Its version comes from `junit-bom`, or from the Spring Boot BOM in the Spring Boot types.\n- **Module `pom.xml`:** `<parent>` with the right `relativePath` (`tools/stub-model` → `../../pom.xml`), then `artifactId`, `name`, `description`, and versionless `<dependencies>`. Nothing else, unless the module adds plugins.\n- A version given to `module.addDependency`/`addTestDependency`/`addPlugin` is moved into the parent's `<dependencyManagement>`/`<pluginManagement>`, so every module that uses an artifact gets the same version. Pinning one artifact at two different versions fails the synth.\n- The synth fails with a clear message on:\n - two modules with the same `artifactId`\n - two modules with the same `dir`, or one `dir` nested inside another\n - a `dir` outside the repo\n - a module depending on itself\n - `packaging` set to anything but `pom` on a project with modules\n\nYou get:\n\n- the root `pom.xml` (and one per module), written by this package:\n - **exact versions only**: a range such as `^1`, `~1.2` or `[1,2)` fails the synth\n - the compiler level, enforcer rule and JUnit line all follow `javaVersion`\n- one Maven run per build. `npx projen build` synthesizes, then runs `mvn -B verify`: compile, unit tests (surefire), package, and `*IT` integration tests (failsafe). There is no `mvn deploy` and no `dist/`.\n- `.github/workflows/build.yml`: a PR build that installs the pinned Node toolchain (`npm ci`) and the project's JDK (`actions/setup-java`, Maven cache), then runs `npx projen build`, plus a SonarQube step when `sonarProjectKey` is set. See [Adding CI jobs](#adding-ci-jobs-to-a-java-project).\n- `.github/workflows/upgrade.yml`: a nightly (03:00 UTC) **report** of available dependency and plugin updates in the job summary. It changes nothing, because every version comes from `.projenrc.ts`; apply an update there. Turn it off with `upgradeWorkflow: false`. The same report runs locally with `npx projen upgrade`.\n- the projen drift check, `LICENSE` (MIT by default), `.editorconfig`, and a generated `package.json` that pins the projen toolchain exactly.\n- no sample code, unless `sample: true` on a single-module project.\n\n### JavaLibraryProject\n\nA reusable Java library published to Maven Central.\n\nScaffold it with the `java_library` type:\n\n```bash\nnpx projen new --from @xpertss/projen-types java_library --name common-utils --group-id org.xpertss --artifact-id common-utils\n```\n\n```typescript\n// .projenrc.ts\nimport { JavaLibraryProject } from '@xpertss/projen-types';\n\nconst project = new JavaLibraryProject({\n name: 'common-utils',\n groupId: 'org.xpertss',\n artifactId: 'common-utils',\n version: '1.0.0',\n sonarProjectKey: 'org.xpertss:common-utils',\n mavenCentralOidc: true,\n});\n\nproject.synth();\n```\n\nYou get everything from [`JavaMavenProject`](#javamavenproject), so modules work here too, plus:\n\n- `maven-source-plugin` and `maven-javadoc-plugin`, attaching the `-sources`/`-javadoc` jars Maven Central requires. In a multi-module library every module attaches them.\n- `.github/workflows/publish-maven-central.yml` - manual dispatch running `mvn -B deploy -P release`. With `mavenCentralOidc: true` it uses Maven Central's OIDC trusted publishing (no GPG secrets needed); otherwise it expects the secrets `MAVEN_GPG_PRIVATE_KEY`, `MAVEN_GPG_PASSPHRASE`, `MAVEN_CENTRAL_USERNAME`, `MAVEN_CENTRAL_PASSWORD`.\n- `.github/workflows/codeindex.yml` - on push to `main`, generates a Java source index under `.cai/` covering every module (disable with `publishCodeIndex: false`).\n\n### JavaSpringBootProject\n\nSpring Boot on Maven, single- or multi-module, **without** Docker, Flyway or a deploy hook. It's [`JavaMavenProject`](#javamavenproject) plus Spring Boot dependency management. Use it for a Spring Boot repo that ships something other than this package's container image, such as a multi-module control plane, or for a Boot app you deploy your own way.\n\nScaffold it with the `java_spring_boot` type:\n\n```bash\nnpx projen new --from @xpertss/projen-types java_spring_boot --name obeya --group-id org.xpertss.obeya --artifact-id obeya-parent\n```\n\n```typescript\n// .projenrc.ts\nimport { JavaSpringBootProject } from '@xpertss/projen-types';\n\nconst project = new JavaSpringBootProject({\n name: 'obeya',\n groupId: 'org.xpertss.obeya',\n artifactId: 'obeya-parent',\n version: '0.1.0-SNAPSHOT',\n javaVersion: '21',\n copyrightOwner: 'Xpert Software',\n});\n\n// plain jar modules: shared libraries, clients, tools\nconst model = project.addModule({ dir: 'obeya-model', artifactId: 'obeya-model' });\nconst client = project.addModule({ dir: 'obeya-api-client', artifactId: 'obeya-api-client' });\nclient.addModuleDependency(model);\n\n// a Spring Boot application module, repackaged into an executable jar\nconst server = project.addSpringBootModule({ dir: 'obeya-server', artifactId: 'obeya-server' });\nserver.addModuleDependency(model);\nserver.addDependency('org.springframework.boot/spring-boot-starter-web'); // versionless: Boot's BOM manages it\nserver.addTestDependency('org.springframework.boot/spring-boot-starter-test');\n\nproject.addBom('org.testcontainers/testcontainers-bom@1.21.3');\n\nproject.synth();\n```\n\nYou get everything from [`JavaMavenProject`](#javamavenproject), plus:\n\n- `spring-boot-dependencies` imported as the **first** BOM, so starters and every library Boot manages (JUnit included) are added without a version. `springBootVersion` sets it; the default is the newest release of the line that supports `javaVersion` (see [Java version support](#java-version-support)).\n- `spring-boot-maven-plugin`, versioned in `<pluginManagement>`:\n - In a **single-module** project the root jar is repackaged into an executable jar.\n - In a **multi-module** project only modules added with `addSpringBootModule()` are repackaged; `addModule()` modules stay plain jars.\n - A repackaged module needs its `@SpringBootApplication` class before `mvn verify` passes, because `repackage` fails with `Unable to find main class` until one exists. Add a module as a plain `addModule()` while it's still empty.\n- failsafe configured to run integration tests against the compiled classes rather than the repackaged jar (as `spring-boot-starter-parent` does).\n- no starters, no Docker, no Flyway, no CDK. Add the starters you need with `addDependency`.\n\n### JavaServiceProject\n\nA Spring Boot service that publishes a Docker image and can trigger deploys in a companion CDK repo. It is [`JavaSpringBootProject`](#javaspringbootproject) plus Docker, Flyway and a deploy hook. It is **single-module**, because the Docker build, the migrations and the deploy hook all assume one deployable at the repo root; `addModule()` fails and points you to `JavaSpringBootProject`.\n\nScaffold it with the `java_service` type:\n\n```bash\nnpx projen new --from @xpertss/projen-types java_service --name stream-processor --group-id org.xpertss --artifact-id stream-processor\n```\n\n```typescript\n// .projenrc.ts\nimport { JavaServiceProject } from '@xpertss/projen-types';\n\nconst project = new JavaServiceProject({\n name: 'stream-processor',\n groupId: 'org.xpertss',\n artifactId: 'stream-processor',\n dockerRegistry: 'docker.io/xpertss',\n cdkDeployTargetRepo: 'xpertss/stream-infra',\n environments: ['dev', { name: 'prod', requiresApproval: true }],\n});\n\nproject.synth();\n```\n\nYou get everything from [`JavaSpringBootProject`](#javaspringbootproject) (and so from `JavaMavenProject`), plus:\n\n- `spring-boot-starter-web` added to the pom (versionless; Boot's BOM manages it).\n- `.github/workflows/publish-docker.yml` - manual dispatch: `mvn -B package && docker build -t <registry>/<name>:<sha>`, logged in with the `DOCKER_USERNAME` / `DOCKER_PASSWORD` secrets. `dockerRegistry` defaults to `docker.io`.\n- Flyway wiring when `useFlyway` (default `true`): `flyway-core` (versionless, so it matches what Boot's Flyway auto-configuration expects), `flyway-maven-plugin` pinned for the Java line, and `src/main/resources/db/migration/V1__init.sql`.\n- `.github/workflows/deploy-cdk.yml` (the `CdkDeployHook`, generated by default) - manual dispatch with an environment selector; each job sends a `workflow_dispatch` to `deploy.yml` in the companion `cdkDeployTargetRepo` (a `CdkInfraProject`/`CdkAppProject` repo). With no `cdkDeployTargetRepo` set, the workflow is still generated but each job's only step fails with instructions - it is dispatch-only, so that lands on whoever tries to deploy rather than on every PR. Turn the workflow off entirely with `cdkDeployHook: false`. `environments` defaults to `['prod']`.\n\n### JavaAppProject\n\nA GUI/TUI/CLI Java application published to GitHub Packages only - no Maven Central, no Docker, no CDK deploy hook.\n\nScaffold it with the `java_app` type:\n\n```bash\nnpx projen new --from @xpertss/projen-types java_app --name studio-cli --group-id org.xpertss --artifact-id studio-cli\n```\n\n```typescript\n// .projenrc.ts\nimport { JavaAppProject } from '@xpertss/projen-types';\n\nconst project = new JavaAppProject({\n name: 'studio-cli',\n groupId: 'org.xpertss',\n artifactId: 'studio-cli',\n ghPackagesRegistry: 'https://maven.pkg.github.com/xpertss/studio-cli',\n});\n\nproject.synth();\n```\n\nYou get everything from [`JavaMavenProject`](#javamavenproject) (modules included), 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.\n\n### GitHubActionProject\n\nA reusable GitHub Action or Workflow. This example scaffolds an action that stages a folder and, only if it changed, commits and pushes it.\n\nScaffold it with the `git_hub_action` type:\n\n```bash\nnpx projen new --from @xpertss/projen-types git_hub_action --name auto-commit --sonar-host-url https://sonarcloud.io\n```\n\n```typescript\n// .projenrc.ts\nimport { GitHubActionProject } from '@xpertss/projen-types';\n\nconst project = new GitHubActionProject({\n name: 'auto-commit',\n description: 'Stage a folder and, only if it changed, commit and push it',\n sonarHostUrl: 'https://sonarcloud.io', // required, no default - your SonarCloud URL\n sonarOrganization: 'xpertss', // default - your SonarCloud org key\n dogfood: {\n // Two scenario steps: the \"changed\" path and the \"no-op\" path are both\n // load-bearing behavior for this action (a double-commit or a\n // push-when-empty bug is the failure mode a hand-rolled inline-shell\n // alternative is most likely to introduce).\n scenario: [\n {\n name: 'Changed path',\n fixtureSteps: [\n 'echo \"$(date -u +%Y%m%dT%H%M%SZ)\" >> test/fixtures/dogfood-state.txt',\n ],\n inputs: {\n commit_message: 'test: dogfood',\n branches: 'test/dogfood',\n },\n assertions: [\n // step id defaults to a slug of `name` - here \"changed-path-0\"\n '[ \"${{ steps.changed-path-0.outputs.committed }}\" = \"true\" ]',\n ],\n },\n {\n // No fixture change this time - nothing new to commit.\n name: 'No-op path',\n id: 'no-op-check', // pin an explicit id instead of relying on the default slug\n inputs: {\n commit_message: 'test: dogfood',\n branches: 'test/dogfood',\n },\n assertions: [\n '[ \"${{ steps.no-op-check.outputs.committed }}\" = \"false\" ]',\n ],\n },\n ],\n cleanup: [\n 'git push origin --delete test/dogfood || true',\n ],\n },\n});\n\nproject.synth();\n```\n\nYou get:\n\n- `action.yml` and `auto-commit.sh` are hand-written - this type only lints their content via `build.yml`'s shellcheck/yamllint/actionlint checks.\n- `.github/workflows/build.yml` - lint gate: `apt`-installed shellcheck/yamllint plus a pinned, SHA-256-verified `actionlint` release binary. Gates `main` alongside `sonar.yml`.\n- `.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. Omit `dogfood` and the workflow still exists, with one step that fails on every PR until you declare a scenario - AD-001 allows a dogfood to be missing loudly, never silently. A *partial* `dogfood` (a scenario with no cleanup) is a synth error.\n- `.github/workflows/sonar.yml` - SonarCloud scan via the Scanner CLI (the quality gate blocks the PR), scanning `action.yml`/`.github/workflows/**`/`**/*.sh` explicitly.\n- `.github/workflows/release.yml` - `feat:`/`fix:` commits on `main` bump the version, tag `vX.Y.Z`, and create a GitHub Release.\n- `.github/workflows/projen-drift-check.yml` and `workflow-change-notice.yml` - drift detection and a change notice, always included.\n- `package.json` (**private**, version source only), `.yamllint`, `LICENSE` (MIT by default), and a `README.md` template - all regenerated by `npx projen`.\n\nNeeds 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 by running the `projen new` command above first (see [Getting started](#getting-started)), then replace the generated `.projenrc.ts` with the one above and run `npx projen`, then hand-write `action.yml`/`auto-commit.sh`/`test/fixtures/`. If you wrote the `.projenrc.ts` before running `projen new`, see [Starting from an existing `.projenrc.ts`](#starting-from-an-existing-projenrcts).\n\n## Java version support\n\n`javaVersion` picks the Java line a Java project targets. It defaults to `21`; the supported lines are `1.8` (alias `8`), `17`, `21` and `25`, and any other value fails the synth with that list. **Nothing in the generated build is hard-coded to one Java line.** Everything that depends on it comes from one table in this package, grouped by line:\n\n| | `1.8` | `17` | `21` | `25` |\n| --- | --- | --- | --- | --- |\n| Compiler level | `maven.compiler.source`/`target` = `1.8` (javac 8 has no `--release`) | `maven.compiler.release` = `17` | `release` = `21` | `release` = `25` |\n| Enforcer `requireJavaVersion` | `[1.8,)` | `[17,)` | `[21,)` | `[25,)` |\n| JUnit (`junit-bom`) | 5.14.4 (JUnit 6 needs Java 17) | 6.1.3 | 6.1.3 | 6.1.3 |\n| Default Spring Boot (`JavaSpringBootProject`) | 2.7.18 (Boot 3+ needs Java 17; a 3.x+ `springBootVersion` fails the synth) | 4.1.1 | 4.1.1 | 4.1.1 |\n| `flyway-maven-plugin` (`JavaServiceProject`) | 9.22.3 | 13.9.0 | 13.9.0 | 13.9.0 |\n| CI JDK (`actions/setup-java` `java-version`) | `8` | `17` | `21` | `25` |\n\nMaven plugins (the same on every line, because all of them run on JDK 8): `maven-compiler-plugin` 3.16.0, `maven-surefire-plugin`/`maven-failsafe-plugin` 3.6.0, `maven-jar-plugin` 3.5.1, `maven-enforcer-plugin` 3.6.3, `maven-source-plugin` 3.4.0 and `maven-javadoc-plugin` 3.12.0 (library only), `versions-maven-plugin` 2.22.0 (the `upgrade` report).\n\n**The enforcer.** `maven-enforcer-plugin` fails the build at the start when the JDK or Maven running it is older than the project needs. Without it you get confusing compiler errors later, or a jar built for the wrong runtime. Its Java rule always follows `javaVersion`. The Maven rule defaults to `[3.9,)`; change it with `minMavenVersion`, or drop the plugin entirely with `enforcer: false`. CI installs the matching JDK through `setup-java`, so the rule only fires on a developer machine with the wrong JDK. A Java 1.8 project builds on any newer JDK (the rule is a minimum), but the JDK 8 runtime API is guaranteed only when you build on JDK 8.\n\n**Overriding a version.** `pluginVersions` replaces any default in the table, keyed by `groupId/artifactId`, with an exact version:\n\n```typescript\nnew JavaMavenProject({\n name: 'svc',\n groupId: 'org.xpertss',\n artifactId: 'svc',\n pluginVersions: {\n 'org.apache.maven.plugins/maven-surefire-plugin': '3.5.6',\n 'org.junit/junit-bom': '5.14.4',\n },\n});\n```\n\n`project.pinnedVersion('org.apache.maven.plugins/maven-surefire-plugin')` returns the version in effect, for reuse in your own plugin config.\n\n**New Java lines** are one new row in this package's version table and a release. Until a line is listed, `javaVersion` rejects it rather than guessing.\n\n## Adding CI jobs to a Java project\n\n`build.yml` is exposed as `project.buildVerifyWorkflow`, so jobs are added through projen's `addJob` rather than `addOverride`. `project.ciSetupSteps` holds the steps every Maven job here needs: pinned Node, `npm ci`, and the project's JDK with a Maven cache. Every job in `build.yml` can then be made a required check on `main`.\n\n```typescript\nimport { github } from 'projen';\n\nproject.buildVerifyWorkflow.addJob('integration', {\n name: 'Container integration tests',\n runsOn: ['self-hosted', 'linux', 'fedora', 'podman'],\n permissions: { contents: github.workflows.JobPermission.READ },\n steps: [\n { name: 'Checkout', uses: 'actions/checkout@v7' },\n ...project.ciSetupSteps,\n { name: 'Integration tests', run: 'mvn -B verify -Pcontainer-its' },\n ],\n});\n```\n\n## Common options\n\nCDK project types (`CdkInfraProjectOptions` / `CdkAppProjectOptions`):\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `name` | - (required) | Project name; must match `package.json` |\n| `cdkVersion` | `2.189.1` | AWS CDK version |\n| `gheTokenSecret` | `PROJEN_GITHUB_TOKEN` | GitHub secret holding projen's PAT |\n| `licensed` | `true` | Write a `LICENSE` |\n| `license` | `MIT` | SPDX identifier for the `LICENSE` |\n| `copyrightOwner` / `copyrightPeriod` | `Xpert Software` / current year | Named in the `LICENSE` |\n| `environments` | - (no `deploy` workflow) | Deploy targets for the `deploy` workflow; strings or `EnvironmentOptions` |\n| `ecrEcs` | - | `EcrEcsOptions` - `enabled`, `externalImageSource` (default `true`) |\n| `edgeResources` | - | Subset of `cloudfront`, `route53`, `apigateway`, `cognito`, `sqs` |\n| `database` | - (app only) | `DatabaseOptions` - `engine` (`postgres`/`mysql`/`dynamodb`, default `postgres`), `migrationTool` |\n| `appEntryPoint` | `src/app.ts` (app only) | Path of the generated application entrypoint |\n\nJava project types (`JavaMavenProjectOptions` and everything built on it - `JavaLibraryProjectOptions`, `JavaAppProjectOptions`, `JavaSpringBootProjectOptions`, `JavaServiceProjectOptions`):\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `name` | - (required) | Project name |\n| `groupId` | - (required) | Maven group id |\n| `artifactId` | - (required) | Maven artifact id (of the reactor parent, in a multi-module project) |\n| `version` | `0.1.0` | Maven version; must be exact |\n| `description` / `url` | - | Written to the root pom |\n| `javaVersion` | `21` | Java line: `1.8`, `17`, `21`, `25` - see [Java version support](#java-version-support) |\n| `javaDistribution` | `temurin` | `actions/setup-java` distribution for CI |\n| `packaging` | `jar` | Root packaging while the project has no modules; a project with modules is always `pom` |\n| `sample` | `false` | Starter `Main` + test under the `groupId` package (single-module only) |\n| `enforcer` | `true` | `maven-enforcer-plugin` with Maven and Java version rules |\n| `minMavenVersion` | `3.9` | The enforcer's `requireMavenVersion` minimum |\n| `pluginVersions` | - | Exact-version overrides for this package's defaults, keyed by `groupId/artifactId` |\n| `licensed` | `true` | Write a `LICENSE` |\n| `license` | `MIT` | SPDX identifier for the `LICENSE` |\n| `copyrightOwner` / `copyrightPeriod` | `Xpert Software` / current year | Named in the `LICENSE` |\n| `editorconfig` | `true` | Write a projen-managed `.editorconfig` (also on the CDK and action types) |\n| `upgradeWorkflow` | `true` | Generate the nightly update report (`upgrade.yml`) |\n| `sonarProjectKey` | - | SonarQube project key; the sonar step is skipped when unset |\n| `gheTokenSecret` | `PROJEN_GITHUB_TOKEN` | GitHub secret holding projen's PAT |\n| `springBootVersion` | newest Boot for `javaVersion` (Spring Boot types only) | Exact Spring Boot version: the BOM and `spring-boot-maven-plugin` |\n| `cdkDeployTargetRepo` | - (service only; `deploy-cdk.yml` fails until set) | Companion CDK repo (`owner/repo`) whose `deploy.yml` the deploy hook dispatches |\n| `cdkDeployHook` | `true` (service only) | Whether to generate `deploy-cdk.yml` at all |\n| `dockerRegistry` | `docker.io` (service only) | Registry the Docker image is pushed to |\n| `useFlyway` | `true` (service only) | Flyway plugin/dependency + `V1__init.sql` |\n\nWith the default MIT license, the generated `LICENSE` looks like:\n\n```\nMIT License\n\nCopyright (c) 2024-2026 Xpert Software\n\nPermission is hereby granted, ...\n```\n\nThe header line (`MIT License`) is specific to the license type — an `Apache-2.0` project would instead show `Apache-2.0`.\n\nOverride the license type and copyright fields:\n\n```typescript\nnew JavaMavenProject({\n name: 'my-lib',\n groupId: 'org.xpertss',\n artifactId: 'my-lib',\n license: 'Apache-2.0', // any SPDX id projen ships a template for\n copyrightOwner: 'Xpert Software',\n copyrightPeriod: '2024-2026',\n});\n```\n\n`EnvironmentOptions` for deploy targets:\n\n```text\ninterface EnvironmentOptions {\n readonly name: string; // e.g. \"dev\", \"stage\", \"prod\"\n readonly accountId?: string; // AWS account id (CDK deploys)\n readonly region?: string; // AWS region (CDK deploys)\n readonly requiresApproval?: boolean; // GitHub Environment approval gate (default false)\n}\n```\n\nPlain strings (`'dev'`) are shorthand for `{ name: 'dev' }`.\n\n`GitHubActionProjectOptions`:\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `name` | - (required) | Project name |\n| `description` | - | One-line description; used in the default README template and recorded in the private `package.json` |\n| `sonarHostUrl` | - (required) | URL of your SonarCloud instance (e.g. `https://sonarcloud.io`); must be reachable from github.com-hosted runners |\n| `sonarOrganization` | `xpertss` | SonarCloud org key (`sonar.organization`); required by the Scanner CLI, not derived from the token |\n| `sonarTokenSecret` | `SONAR_TOKEN` | GitHub secret holding the Sonar token |\n| `sonarPullRequestGate` | `true` | Whether `sonar.yml` also runs on `pull_request` as a pass/fail gate |\n| `dogfood` | - (a `test-dogfood.yml` that fails until you declare one) | `ActionDogfoodOptions` - the scenario that exercises the action end-to-end via `uses: ./` |\n| `license` | `MIT` | SPDX identifier for the generated `LICENSE` |\n| `copyrightOwner` / `copyrightPeriod` | `Xpert Software` / current year | Named in the `LICENSE` |\n| `gheTokenSecret` | `PROJEN_GITHUB_TOKEN` | GitHub secret holding projen's PAT (drift-check PR comments); a dogfood that passes a `token` input must reference this secret in the step's `inputs` |\n\n`ActionDogfoodOptions`/`ActionDogfoodStep` - the dogfood scenario (`test-dogfood.yml`):\n\n```text\ninterface ActionDogfoodOptions {\n readonly scenario: ActionDogfoodStep[]; // one or more, run in order - required\n readonly cleanup: string[]; // shared, run once at the end with `if: always()` - required\n}\n\ninterface ActionDogfoodStep {\n readonly name: string; // labels this step-group's generated workflow steps\n readonly id?: string; // step id for the `uses: ./` call; default: a slug of `name`\n readonly fixtureSteps?: string[]; // shell, before the invocation (default: none)\n readonly inputs?: Record<string, string>; // `with:` for this invocation (default: none)\n readonly assertions: string[]; // shell, after the invocation - required; the step runs under set -euo pipefail so any failing line fails the job\n}\n```\n\nMost 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`.\n\n## Required GitHub secrets\n\n| Secret | Used by | Notes |\n| --- | --- | --- |\n| `PROJEN_GITHUB_TOKEN` | all types | PAT for projen's self-mutation/automation; override via `gheTokenSecret` |\n| `SONAR_TOKEN` | Java types with `sonarProjectKey`; `GitHubActionProject` | SonarQube scan step in `build.yml` / `sonar.yml`; override via `sonarTokenSecret` on `GitHubActionProject` |\n| `DOCKER_USERNAME` / `DOCKER_PASSWORD` | `JavaServiceProject` | Docker image push |\n| `MAVEN_GPG_PRIVATE_KEY`, `MAVEN_GPG_PASSPHRASE`, `MAVEN_CENTRAL_USERNAME`, `MAVEN_CENTRAL_PASSWORD` | `JavaLibraryProject` without `mavenCentralOidc` | Not needed with OIDC trusted publishing |\n\n## Customizing `.gitignore`\n\nEvery project type already ignores JetBrains IDE state (`/.idea/*`) and the `/spec/` directory with all of its subdirectories (local plans and specs, never committed). The Java types also ignore Maven `target/` output and Eclipse files. To ignore more, call the inherited `addGitIgnore()` method after constructing the project in your `.projenrc.ts`:\n\n```typescript\n// .projenrc.ts\nimport { CdkInfraProject } from '@xpertss/projen-types';\n\nconst project = new CdkInfraProject({\n name: 'my-infra',\n});\n\nproject.addGitIgnore('*.log');\nproject.addGitIgnore('.env.*');\nproject.addGitIgnore('/build/');\n\nproject.synth();\n```\n\nThe same works for every type - just swap the class (e.g. `JavaServiceProject`, `GitHubActionProject`). Each call takes one standard gitignore glob pattern. There is no `gitignore` constructor option: the project types' option interfaces do not expose one, so patterns go through `addGitIgnore()` instead.\n\nRe-run `npx projen` after editing - `.gitignore` is a generated file, so hand-editing it is caught by the drift check.\n\n## Troubleshooting\n\n**`Unable to find projen project. Use \"projen new\" to create a new project.`**\nIf the directory already has a `.projenrc.ts`, this error means the rc has\nnever been synthesized (there's no `.projen/tasks.json`), not that you need a\nnew project. See [Starting from an existing `.projenrc.ts`](#starting-from-an-existing-projenrcts).\n\n## Going further\n\nThe project types are composed from smaller components you can also attach to your own projects:\n\n| Component | Applies to | Purpose |\n| --- | --- | --- |\n| `AppRuntimeScaffold` | `NodeProject` | App source skeleton (`app.ts` + handlers) |\n| `DatabaseComponent` | `NodeProject` | Database construct stub + migration tool wiring |\n| `EcrEcsConstructs` | `Project` | ECR + Fargate ECS construct helper |\n| `EdgeNetworkingConstructs` | `Project` | Per-resource edge networking construct helpers |\n| `MavenPom` | `Project` | A `pom.xml` with modules, BOM imports, dependency/plugin management, and exact versions only |\n| `MavenModule` | `JavaMavenProject` | One module of a reactor (created by `addModule()`) |\n| `MavenUpgradeReport` | `GitHubProject` | Nightly report-only `upgrade.yml` |\n| `MavenCentralPublish` | `JavaMavenProject` | Manual-dispatch Maven Central publish workflow |\n| `DockerPublish` | `JavaMavenProject` | Manual-dispatch Docker build+push workflow |\n| `GitHubPackagesPublish` | `JavaMavenProject` | Manual-dispatch GitHub Packages publish workflow |\n| `FlywayMigration` | `JavaSpringBootProject` | Flyway plugin/dependency + migrations directory |\n| `CdkDeployHook` | `JavaMavenProject` | Manual-dispatch workflow that triggers `deploy.yml` in a companion CDK repo |\n| `CodeIndexWorkflow` | `JavaMavenProject` | Code index generation on push to `main` |\n| `ActionBuildWorkflow` | `GitHubProject` | The `lint` task (shellcheck/yamllint/pinned actionlint) + `build.yml` |\n| `ActionDogfoodWorkflow` | `GitHubProject` | `test-dogfood.yml` from an `ActionDogfoodOptions` scenario |\n| `ActionSonarWorkflow` | `GitHubProject` | `sonar.yml` (SonarCloud scan via the Scanner CLI) |\n\nExample - adding a Docker publish to a `JavaMavenProject` (`JavaServiceProject` is the packaged version of this, with Spring Boot):\n\n```typescript\nimport { DockerPublish, JavaMavenProject } from '@xpertss/projen-types';\n\nconst project = new JavaMavenProject({\n name: 'my-service',\n groupId: 'org.xpertss',\n artifactId: 'my-service',\n});\n\nnew DockerPublish(project, { dockerRegistry: 'ghcr.io' });\n\nproject.synth();\n```\n\nThe full API reference, including every option and property, is in [API.md](./API.md).\n"
|
|
110
110
|
},
|
|
111
111
|
"repository": {
|
|
112
112
|
"type": "git",
|
|
@@ -193,20 +193,21 @@
|
|
|
193
193
|
"kind": "interface",
|
|
194
194
|
"locationInModule": {
|
|
195
195
|
"filename": "src/actions/action-dogfood-workflow.ts",
|
|
196
|
-
"line":
|
|
196
|
+
"line": 61
|
|
197
197
|
},
|
|
198
198
|
"name": "ActionDogfoodOptions",
|
|
199
199
|
"properties": [
|
|
200
200
|
{
|
|
201
201
|
"abstract": true,
|
|
202
202
|
"docs": {
|
|
203
|
+
"remarks": "Intentionally **best-effort**: unlike the assert step it does\n*not* run under `set -e`, so a failing line (e.g. deleting an already\ndeleted ref) does not fail the job.",
|
|
203
204
|
"stability": "experimental",
|
|
204
|
-
"summary": "Shell cleanup, run once at the end with `if: always()
|
|
205
|
+
"summary": "Shell cleanup, run once at the end with `if: always()` so repeated runs start clean."
|
|
205
206
|
},
|
|
206
207
|
"immutable": true,
|
|
207
208
|
"locationInModule": {
|
|
208
209
|
"filename": "src/actions/action-dogfood-workflow.ts",
|
|
209
|
-
"line":
|
|
210
|
+
"line": 71
|
|
210
211
|
},
|
|
211
212
|
"name": "cleanup",
|
|
212
213
|
"type": {
|
|
@@ -227,7 +228,7 @@
|
|
|
227
228
|
"immutable": true,
|
|
228
229
|
"locationInModule": {
|
|
229
230
|
"filename": "src/actions/action-dogfood-workflow.ts",
|
|
230
|
-
"line":
|
|
231
|
+
"line": 63
|
|
231
232
|
},
|
|
232
233
|
"name": "scenario",
|
|
233
234
|
"type": {
|
|
@@ -260,13 +261,14 @@
|
|
|
260
261
|
{
|
|
261
262
|
"abstract": true,
|
|
262
263
|
"docs": {
|
|
264
|
+
"remarks": "The generated step runs under `set -euo pipefail`, so a failing\nassertion fails the step immediately rather than being masked by a later,\npassing one.",
|
|
263
265
|
"stability": "experimental",
|
|
264
266
|
"summary": "Shell assertions after this invocation - the job fails unless every one exits 0."
|
|
265
267
|
},
|
|
266
268
|
"immutable": true,
|
|
267
269
|
"locationInModule": {
|
|
268
270
|
"filename": "src/actions/action-dogfood-workflow.ts",
|
|
269
|
-
"line":
|
|
271
|
+
"line": 47
|
|
270
272
|
},
|
|
271
273
|
"name": "assertions",
|
|
272
274
|
"type": {
|
|
@@ -376,7 +378,7 @@
|
|
|
376
378
|
},
|
|
377
379
|
"locationInModule": {
|
|
378
380
|
"filename": "src/actions/action-dogfood-workflow.ts",
|
|
379
|
-
"line":
|
|
381
|
+
"line": 99
|
|
380
382
|
},
|
|
381
383
|
"parameters": [
|
|
382
384
|
{
|
|
@@ -397,7 +399,7 @@
|
|
|
397
399
|
"kind": "class",
|
|
398
400
|
"locationInModule": {
|
|
399
401
|
"filename": "src/actions/action-dogfood-workflow.ts",
|
|
400
|
-
"line":
|
|
402
|
+
"line": 96
|
|
401
403
|
},
|
|
402
404
|
"name": "ActionDogfoodWorkflow",
|
|
403
405
|
"properties": [
|
|
@@ -408,7 +410,7 @@
|
|
|
408
410
|
"immutable": true,
|
|
409
411
|
"locationInModule": {
|
|
410
412
|
"filename": "src/actions/action-dogfood-workflow.ts",
|
|
411
|
-
"line":
|
|
413
|
+
"line": 97
|
|
412
414
|
},
|
|
413
415
|
"name": "workflow",
|
|
414
416
|
"type": {
|
|
@@ -433,7 +435,7 @@
|
|
|
433
435
|
},
|
|
434
436
|
"locationInModule": {
|
|
435
437
|
"filename": "src/actions/action-sonar-workflow.ts",
|
|
436
|
-
"line":
|
|
438
|
+
"line": 44
|
|
437
439
|
},
|
|
438
440
|
"parameters": [
|
|
439
441
|
{
|
|
@@ -453,7 +455,7 @@
|
|
|
453
455
|
"kind": "class",
|
|
454
456
|
"locationInModule": {
|
|
455
457
|
"filename": "src/actions/action-sonar-workflow.ts",
|
|
456
|
-
"line":
|
|
458
|
+
"line": 41
|
|
457
459
|
},
|
|
458
460
|
"name": "ActionSonarWorkflow",
|
|
459
461
|
"properties": [
|
|
@@ -464,7 +466,7 @@
|
|
|
464
466
|
"immutable": true,
|
|
465
467
|
"locationInModule": {
|
|
466
468
|
"filename": "src/actions/action-sonar-workflow.ts",
|
|
467
|
-
"line":
|
|
469
|
+
"line": 42
|
|
468
470
|
},
|
|
469
471
|
"name": "workflow",
|
|
470
472
|
"type": {
|
|
@@ -504,6 +506,24 @@
|
|
|
504
506
|
"primitive": "string"
|
|
505
507
|
}
|
|
506
508
|
},
|
|
509
|
+
{
|
|
510
|
+
"abstract": true,
|
|
511
|
+
"docs": {
|
|
512
|
+
"default": "\"xpertss\"",
|
|
513
|
+
"stability": "experimental",
|
|
514
|
+
"summary": "SonarCloud organization key (`sonar.organization`). Mandatory for the Scanner CLI on SonarCloud - it is not derived from the token, so a scan without it always fails."
|
|
515
|
+
},
|
|
516
|
+
"immutable": true,
|
|
517
|
+
"locationInModule": {
|
|
518
|
+
"filename": "src/actions/action-sonar-workflow.ts",
|
|
519
|
+
"line": 23
|
|
520
|
+
},
|
|
521
|
+
"name": "sonarOrganization",
|
|
522
|
+
"optional": true,
|
|
523
|
+
"type": {
|
|
524
|
+
"primitive": "string"
|
|
525
|
+
}
|
|
526
|
+
},
|
|
507
527
|
{
|
|
508
528
|
"abstract": true,
|
|
509
529
|
"docs": {
|
|
@@ -514,7 +534,7 @@
|
|
|
514
534
|
"immutable": true,
|
|
515
535
|
"locationInModule": {
|
|
516
536
|
"filename": "src/actions/action-sonar-workflow.ts",
|
|
517
|
-
"line":
|
|
537
|
+
"line": 32
|
|
518
538
|
},
|
|
519
539
|
"name": "sonarPullRequestGate",
|
|
520
540
|
"optional": true,
|
|
@@ -531,7 +551,7 @@
|
|
|
531
551
|
"immutable": true,
|
|
532
552
|
"locationInModule": {
|
|
533
553
|
"filename": "src/actions/action-sonar-workflow.ts",
|
|
534
|
-
"line":
|
|
554
|
+
"line": 26
|
|
535
555
|
},
|
|
536
556
|
"name": "sonarTokenSecret",
|
|
537
557
|
"optional": true,
|
|
@@ -628,7 +648,7 @@
|
|
|
628
648
|
"kind": "interface",
|
|
629
649
|
"locationInModule": {
|
|
630
650
|
"filename": "src/cdk/options.ts",
|
|
631
|
-
"line":
|
|
651
|
+
"line": 92
|
|
632
652
|
},
|
|
633
653
|
"name": "CdkAppProjectOptions",
|
|
634
654
|
"properties": [
|
|
@@ -641,7 +661,7 @@
|
|
|
641
661
|
"immutable": true,
|
|
642
662
|
"locationInModule": {
|
|
643
663
|
"filename": "src/cdk/options.ts",
|
|
644
|
-
"line":
|
|
664
|
+
"line": 96
|
|
645
665
|
},
|
|
646
666
|
"name": "appEntryPoint",
|
|
647
667
|
"optional": true,
|
|
@@ -657,7 +677,7 @@
|
|
|
657
677
|
"immutable": true,
|
|
658
678
|
"locationInModule": {
|
|
659
679
|
"filename": "src/cdk/options.ts",
|
|
660
|
-
"line":
|
|
680
|
+
"line": 93
|
|
661
681
|
},
|
|
662
682
|
"name": "database",
|
|
663
683
|
"optional": true,
|
|
@@ -811,7 +831,7 @@
|
|
|
811
831
|
"kind": "interface",
|
|
812
832
|
"locationInModule": {
|
|
813
833
|
"filename": "src/cdk/options.ts",
|
|
814
|
-
"line":
|
|
834
|
+
"line": 63
|
|
815
835
|
},
|
|
816
836
|
"name": "CdkInfraProjectOptions",
|
|
817
837
|
"properties": [
|
|
@@ -823,7 +843,7 @@
|
|
|
823
843
|
"immutable": true,
|
|
824
844
|
"locationInModule": {
|
|
825
845
|
"filename": "src/cdk/options.ts",
|
|
826
|
-
"line":
|
|
846
|
+
"line": 79
|
|
827
847
|
},
|
|
828
848
|
"name": "ecrEcs",
|
|
829
849
|
"optional": true,
|
|
@@ -839,7 +859,7 @@
|
|
|
839
859
|
"immutable": true,
|
|
840
860
|
"locationInModule": {
|
|
841
861
|
"filename": "src/cdk/options.ts",
|
|
842
|
-
"line":
|
|
862
|
+
"line": 81
|
|
843
863
|
},
|
|
844
864
|
"name": "edgeResources",
|
|
845
865
|
"optional": true,
|
|
@@ -863,7 +883,7 @@
|
|
|
863
883
|
"immutable": true,
|
|
864
884
|
"locationInModule": {
|
|
865
885
|
"filename": "src/cdk/options.ts",
|
|
866
|
-
"line":
|
|
886
|
+
"line": 77
|
|
867
887
|
},
|
|
868
888
|
"name": "environments",
|
|
869
889
|
"optional": true,
|
|
@@ -902,7 +922,7 @@
|
|
|
902
922
|
},
|
|
903
923
|
"locationInModule": {
|
|
904
924
|
"filename": "src/cdk/cdk-typescript-base.ts",
|
|
905
|
-
"line":
|
|
925
|
+
"line": 31
|
|
906
926
|
},
|
|
907
927
|
"parameters": [
|
|
908
928
|
{
|
|
@@ -916,7 +936,7 @@
|
|
|
916
936
|
"kind": "class",
|
|
917
937
|
"locationInModule": {
|
|
918
938
|
"filename": "src/cdk/cdk-typescript-base.ts",
|
|
919
|
-
"line":
|
|
939
|
+
"line": 30
|
|
920
940
|
},
|
|
921
941
|
"name": "CdkTypescriptProject",
|
|
922
942
|
"symbolId": "src/cdk/cdk-typescript-base:CdkTypescriptProject"
|
|
@@ -934,7 +954,7 @@
|
|
|
934
954
|
"kind": "interface",
|
|
935
955
|
"locationInModule": {
|
|
936
956
|
"filename": "src/cdk/cdk-typescript-base.ts",
|
|
937
|
-
"line":
|
|
957
|
+
"line": 19
|
|
938
958
|
},
|
|
939
959
|
"name": "CdkTypescriptProjectOptions",
|
|
940
960
|
"properties": [
|
|
@@ -946,7 +966,7 @@
|
|
|
946
966
|
"immutable": true,
|
|
947
967
|
"locationInModule": {
|
|
948
968
|
"filename": "src/cdk/cdk-typescript-base.ts",
|
|
949
|
-
"line":
|
|
969
|
+
"line": 20
|
|
950
970
|
},
|
|
951
971
|
"name": "environments",
|
|
952
972
|
"optional": true,
|
|
@@ -1050,6 +1070,42 @@
|
|
|
1050
1070
|
"primitive": "string"
|
|
1051
1071
|
}
|
|
1052
1072
|
},
|
|
1073
|
+
{
|
|
1074
|
+
"abstract": true,
|
|
1075
|
+
"docs": {
|
|
1076
|
+
"default": "\"Xpert Software\"",
|
|
1077
|
+
"stability": "experimental",
|
|
1078
|
+
"summary": "Copyright owner named in the `LICENSE`."
|
|
1079
|
+
},
|
|
1080
|
+
"immutable": true,
|
|
1081
|
+
"locationInModule": {
|
|
1082
|
+
"filename": "src/cdk/options.ts",
|
|
1083
|
+
"line": 48
|
|
1084
|
+
},
|
|
1085
|
+
"name": "copyrightOwner",
|
|
1086
|
+
"optional": true,
|
|
1087
|
+
"type": {
|
|
1088
|
+
"primitive": "string"
|
|
1089
|
+
}
|
|
1090
|
+
},
|
|
1091
|
+
{
|
|
1092
|
+
"abstract": true,
|
|
1093
|
+
"docs": {
|
|
1094
|
+
"default": "- the current year",
|
|
1095
|
+
"stability": "experimental",
|
|
1096
|
+
"summary": "Copyright period named in the `LICENSE`."
|
|
1097
|
+
},
|
|
1098
|
+
"immutable": true,
|
|
1099
|
+
"locationInModule": {
|
|
1100
|
+
"filename": "src/cdk/options.ts",
|
|
1101
|
+
"line": 54
|
|
1102
|
+
},
|
|
1103
|
+
"name": "copyrightPeriod",
|
|
1104
|
+
"optional": true,
|
|
1105
|
+
"type": {
|
|
1106
|
+
"primitive": "string"
|
|
1107
|
+
}
|
|
1108
|
+
},
|
|
1053
1109
|
{
|
|
1054
1110
|
"abstract": true,
|
|
1055
1111
|
"docs": {
|
|
@@ -1060,7 +1116,7 @@
|
|
|
1060
1116
|
"immutable": true,
|
|
1061
1117
|
"locationInModule": {
|
|
1062
1118
|
"filename": "src/cdk/options.ts",
|
|
1063
|
-
"line":
|
|
1119
|
+
"line": 60
|
|
1064
1120
|
},
|
|
1065
1121
|
"name": "editorconfig",
|
|
1066
1122
|
"optional": true,
|
|
@@ -1084,6 +1140,42 @@
|
|
|
1084
1140
|
"type": {
|
|
1085
1141
|
"primitive": "string"
|
|
1086
1142
|
}
|
|
1143
|
+
},
|
|
1144
|
+
{
|
|
1145
|
+
"abstract": true,
|
|
1146
|
+
"docs": {
|
|
1147
|
+
"default": "\"MIT\"",
|
|
1148
|
+
"stability": "experimental",
|
|
1149
|
+
"summary": "SPDX identifier for the generated `LICENSE`."
|
|
1150
|
+
},
|
|
1151
|
+
"immutable": true,
|
|
1152
|
+
"locationInModule": {
|
|
1153
|
+
"filename": "src/cdk/options.ts",
|
|
1154
|
+
"line": 42
|
|
1155
|
+
},
|
|
1156
|
+
"name": "license",
|
|
1157
|
+
"optional": true,
|
|
1158
|
+
"type": {
|
|
1159
|
+
"primitive": "string"
|
|
1160
|
+
}
|
|
1161
|
+
},
|
|
1162
|
+
{
|
|
1163
|
+
"abstract": true,
|
|
1164
|
+
"docs": {
|
|
1165
|
+
"default": "true",
|
|
1166
|
+
"stability": "experimental",
|
|
1167
|
+
"summary": "Write a `LICENSE`."
|
|
1168
|
+
},
|
|
1169
|
+
"immutable": true,
|
|
1170
|
+
"locationInModule": {
|
|
1171
|
+
"filename": "src/cdk/options.ts",
|
|
1172
|
+
"line": 36
|
|
1173
|
+
},
|
|
1174
|
+
"name": "licensed",
|
|
1175
|
+
"optional": true,
|
|
1176
|
+
"type": {
|
|
1177
|
+
"primitive": "boolean"
|
|
1178
|
+
}
|
|
1087
1179
|
}
|
|
1088
1180
|
],
|
|
1089
1181
|
"symbolId": "src/cdk/options:CommonCdkOptions"
|
|
@@ -1150,7 +1242,7 @@
|
|
|
1150
1242
|
{
|
|
1151
1243
|
"abstract": true,
|
|
1152
1244
|
"docs": {
|
|
1153
|
-
"default": "\"
|
|
1245
|
+
"default": "\"Xpert Software\"",
|
|
1154
1246
|
"stability": "experimental",
|
|
1155
1247
|
"summary": "Copyright owner named in the `LICENSE`."
|
|
1156
1248
|
},
|
|
@@ -1533,7 +1625,7 @@
|
|
|
1533
1625
|
"kind": "interface",
|
|
1534
1626
|
"locationInModule": {
|
|
1535
1627
|
"filename": "src/cdk/options.ts",
|
|
1536
|
-
"line":
|
|
1628
|
+
"line": 84
|
|
1537
1629
|
},
|
|
1538
1630
|
"name": "DatabaseOptions",
|
|
1539
1631
|
"properties": [
|
|
@@ -1546,7 +1638,7 @@
|
|
|
1546
1638
|
"immutable": true,
|
|
1547
1639
|
"locationInModule": {
|
|
1548
1640
|
"filename": "src/cdk/options.ts",
|
|
1549
|
-
"line":
|
|
1641
|
+
"line": 86
|
|
1550
1642
|
},
|
|
1551
1643
|
"name": "engine",
|
|
1552
1644
|
"optional": true,
|
|
@@ -1563,7 +1655,7 @@
|
|
|
1563
1655
|
"immutable": true,
|
|
1564
1656
|
"locationInModule": {
|
|
1565
1657
|
"filename": "src/cdk/options.ts",
|
|
1566
|
-
"line":
|
|
1658
|
+
"line": 89
|
|
1567
1659
|
},
|
|
1568
1660
|
"name": "migrationTool",
|
|
1569
1661
|
"optional": true,
|
|
@@ -1919,7 +2011,7 @@
|
|
|
1919
2011
|
},
|
|
1920
2012
|
"locationInModule": {
|
|
1921
2013
|
"filename": "src/actions/github-action-project.ts",
|
|
1922
|
-
"line":
|
|
2014
|
+
"line": 161
|
|
1923
2015
|
},
|
|
1924
2016
|
"parameters": [
|
|
1925
2017
|
{
|
|
@@ -1933,7 +2025,7 @@
|
|
|
1933
2025
|
"kind": "class",
|
|
1934
2026
|
"locationInModule": {
|
|
1935
2027
|
"filename": "src/actions/github-action-project.ts",
|
|
1936
|
-
"line":
|
|
2028
|
+
"line": 155
|
|
1937
2029
|
},
|
|
1938
2030
|
"name": "GitHubActionProject",
|
|
1939
2031
|
"properties": [
|
|
@@ -1944,7 +2036,7 @@
|
|
|
1944
2036
|
"immutable": true,
|
|
1945
2037
|
"locationInModule": {
|
|
1946
2038
|
"filename": "src/actions/github-action-project.ts",
|
|
1947
|
-
"line":
|
|
2039
|
+
"line": 156
|
|
1948
2040
|
},
|
|
1949
2041
|
"name": "buildWorkflow",
|
|
1950
2042
|
"type": {
|
|
@@ -1958,7 +2050,7 @@
|
|
|
1958
2050
|
"immutable": true,
|
|
1959
2051
|
"locationInModule": {
|
|
1960
2052
|
"filename": "src/actions/github-action-project.ts",
|
|
1961
|
-
"line":
|
|
2053
|
+
"line": 157
|
|
1962
2054
|
},
|
|
1963
2055
|
"name": "dogfoodWorkflow",
|
|
1964
2056
|
"type": {
|
|
@@ -1972,7 +2064,7 @@
|
|
|
1972
2064
|
"immutable": true,
|
|
1973
2065
|
"locationInModule": {
|
|
1974
2066
|
"filename": "src/actions/github-action-project.ts",
|
|
1975
|
-
"line":
|
|
2067
|
+
"line": 159
|
|
1976
2068
|
},
|
|
1977
2069
|
"name": "release",
|
|
1978
2070
|
"type": {
|
|
@@ -1986,7 +2078,7 @@
|
|
|
1986
2078
|
"immutable": true,
|
|
1987
2079
|
"locationInModule": {
|
|
1988
2080
|
"filename": "src/actions/github-action-project.ts",
|
|
1989
|
-
"line":
|
|
2081
|
+
"line": 158
|
|
1990
2082
|
},
|
|
1991
2083
|
"name": "sonarWorkflow",
|
|
1992
2084
|
"type": {
|
|
@@ -2022,13 +2114,49 @@
|
|
|
2022
2114
|
"immutable": true,
|
|
2023
2115
|
"locationInModule": {
|
|
2024
2116
|
"filename": "src/actions/github-action-project.ts",
|
|
2025
|
-
"line":
|
|
2117
|
+
"line": 59
|
|
2026
2118
|
},
|
|
2027
2119
|
"name": "sonarHostUrl",
|
|
2028
2120
|
"type": {
|
|
2029
2121
|
"primitive": "string"
|
|
2030
2122
|
}
|
|
2031
2123
|
},
|
|
2124
|
+
{
|
|
2125
|
+
"abstract": true,
|
|
2126
|
+
"docs": {
|
|
2127
|
+
"default": "\"Xpert Software\"",
|
|
2128
|
+
"stability": "experimental",
|
|
2129
|
+
"summary": "Copyright owner named in the `LICENSE`."
|
|
2130
|
+
},
|
|
2131
|
+
"immutable": true,
|
|
2132
|
+
"locationInModule": {
|
|
2133
|
+
"filename": "src/actions/github-action-project.ts",
|
|
2134
|
+
"line": 104
|
|
2135
|
+
},
|
|
2136
|
+
"name": "copyrightOwner",
|
|
2137
|
+
"optional": true,
|
|
2138
|
+
"type": {
|
|
2139
|
+
"primitive": "string"
|
|
2140
|
+
}
|
|
2141
|
+
},
|
|
2142
|
+
{
|
|
2143
|
+
"abstract": true,
|
|
2144
|
+
"docs": {
|
|
2145
|
+
"default": "- the current year",
|
|
2146
|
+
"stability": "experimental",
|
|
2147
|
+
"summary": "Copyright period named in the `LICENSE`."
|
|
2148
|
+
},
|
|
2149
|
+
"immutable": true,
|
|
2150
|
+
"locationInModule": {
|
|
2151
|
+
"filename": "src/actions/github-action-project.ts",
|
|
2152
|
+
"line": 110
|
|
2153
|
+
},
|
|
2154
|
+
"name": "copyrightPeriod",
|
|
2155
|
+
"optional": true,
|
|
2156
|
+
"type": {
|
|
2157
|
+
"primitive": "string"
|
|
2158
|
+
}
|
|
2159
|
+
},
|
|
2032
2160
|
{
|
|
2033
2161
|
"abstract": true,
|
|
2034
2162
|
"docs": {
|
|
@@ -2058,7 +2186,7 @@
|
|
|
2058
2186
|
"immutable": true,
|
|
2059
2187
|
"locationInModule": {
|
|
2060
2188
|
"filename": "src/actions/github-action-project.ts",
|
|
2061
|
-
"line":
|
|
2189
|
+
"line": 92
|
|
2062
2190
|
},
|
|
2063
2191
|
"name": "dogfood",
|
|
2064
2192
|
"optional": true,
|
|
@@ -2076,7 +2204,7 @@
|
|
|
2076
2204
|
"immutable": true,
|
|
2077
2205
|
"locationInModule": {
|
|
2078
2206
|
"filename": "src/actions/github-action-project.ts",
|
|
2079
|
-
"line":
|
|
2207
|
+
"line": 116
|
|
2080
2208
|
},
|
|
2081
2209
|
"name": "editorconfig",
|
|
2082
2210
|
"optional": true,
|
|
@@ -2088,13 +2216,14 @@
|
|
|
2088
2216
|
"abstract": true,
|
|
2089
2217
|
"docs": {
|
|
2090
2218
|
"default": "\"PROJEN_GITHUB_TOKEN\"",
|
|
2219
|
+
"remarks": "It is **not** wired into the dogfood automatically: a dogfood that invokes\nan action with a `token` input must reference this secret in the step's\n`inputs` (e.g. `token: '${{ secrets.PROJEN_GITHUB_TOKEN }}'`).",
|
|
2091
2220
|
"stability": "experimental",
|
|
2092
|
-
"summary": "Name of the GitHub Actions secret holding the PAT used for projen-automation PR comments (F003) and
|
|
2221
|
+
"summary": "Name of the GitHub Actions secret holding the PAT used for projen-automation PR comments (F003) and the drift-check's PR comments."
|
|
2093
2222
|
},
|
|
2094
2223
|
"immutable": true,
|
|
2095
2224
|
"locationInModule": {
|
|
2096
2225
|
"filename": "src/actions/github-action-project.ts",
|
|
2097
|
-
"line":
|
|
2226
|
+
"line": 52
|
|
2098
2227
|
},
|
|
2099
2228
|
"name": "gheTokenSecret",
|
|
2100
2229
|
"optional": true,
|
|
@@ -2112,7 +2241,7 @@
|
|
|
2112
2241
|
"immutable": true,
|
|
2113
2242
|
"locationInModule": {
|
|
2114
2243
|
"filename": "src/actions/github-action-project.ts",
|
|
2115
|
-
"line":
|
|
2244
|
+
"line": 98
|
|
2116
2245
|
},
|
|
2117
2246
|
"name": "license",
|
|
2118
2247
|
"optional": true,
|
|
@@ -2120,6 +2249,24 @@
|
|
|
2120
2249
|
"primitive": "string"
|
|
2121
2250
|
}
|
|
2122
2251
|
},
|
|
2252
|
+
{
|
|
2253
|
+
"abstract": true,
|
|
2254
|
+
"docs": {
|
|
2255
|
+
"default": "\"xpertss\"",
|
|
2256
|
+
"stability": "experimental",
|
|
2257
|
+
"summary": "SonarCloud organization key (`sonar.organization`), required by the Scanner CLI on SonarCloud."
|
|
2258
|
+
},
|
|
2259
|
+
"immutable": true,
|
|
2260
|
+
"locationInModule": {
|
|
2261
|
+
"filename": "src/actions/github-action-project.ts",
|
|
2262
|
+
"line": 66
|
|
2263
|
+
},
|
|
2264
|
+
"name": "sonarOrganization",
|
|
2265
|
+
"optional": true,
|
|
2266
|
+
"type": {
|
|
2267
|
+
"primitive": "string"
|
|
2268
|
+
}
|
|
2269
|
+
},
|
|
2123
2270
|
{
|
|
2124
2271
|
"abstract": true,
|
|
2125
2272
|
"docs": {
|
|
@@ -2130,7 +2277,7 @@
|
|
|
2130
2277
|
"immutable": true,
|
|
2131
2278
|
"locationInModule": {
|
|
2132
2279
|
"filename": "src/actions/github-action-project.ts",
|
|
2133
|
-
"line":
|
|
2280
|
+
"line": 75
|
|
2134
2281
|
},
|
|
2135
2282
|
"name": "sonarPullRequestGate",
|
|
2136
2283
|
"optional": true,
|
|
@@ -2147,7 +2294,7 @@
|
|
|
2147
2294
|
"immutable": true,
|
|
2148
2295
|
"locationInModule": {
|
|
2149
2296
|
"filename": "src/actions/github-action-project.ts",
|
|
2150
|
-
"line":
|
|
2297
|
+
"line": 69
|
|
2151
2298
|
},
|
|
2152
2299
|
"name": "sonarTokenSecret",
|
|
2153
2300
|
"optional": true,
|
|
@@ -4483,6 +4630,6 @@
|
|
|
4483
4630
|
"symbolId": "src/common/workflow-change-notice-workflow:WorkflowChangeNoticeWorkflowOptions"
|
|
4484
4631
|
}
|
|
4485
4632
|
},
|
|
4486
|
-
"version": "0.0.
|
|
4487
|
-
"fingerprint": "
|
|
4633
|
+
"version": "0.0.21",
|
|
4634
|
+
"fingerprint": "Lpw7m6GjVomXI8FrDCx1XCdRdN23DRQOtGauO0smzeY="
|
|
4488
4635
|
}
|