diff --git a/README.md b/README.md index 0617a05..51eb26e 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ This project defines the following templates: | Collection name | Description | | --------------- | ------------------------------------- | | `application` | Generates a new NestJS project. | +| `azure` | Generate Azure Pipelines definitions. | | `docker` | Generates Docker configuration files. | # How to use @@ -37,6 +38,14 @@ Run the following command to generate a new project in a subfolder: nest new -c @tseisel/nestjs-schematics ``` +## azure + +Generates configuration files to run a pull request check pipeline on an Azure DevOps build Agent. + +```sh +nest g -c @tseisel/nestjs-schematics azure +``` + ## docker Generates configuration files that are required for development and deployment with Docker. This schematic can be applied on an existing project. diff --git a/src/application/files/package.json b/src/application/files/package.json index 0c4e4dc..deee19a 100644 --- a/src/application/files/package.json +++ b/src/application/files/package.json @@ -29,6 +29,7 @@ "@nestjs/cli": "^10.3.0", "@nestjs/schematics": "^10.1.0", "@nestjs/testing": "^10.3.0", + "@tseisel/nestjs-schematics": "*", "@types/express": "^4.17.21", "@types/jest": "^29.5.0", "@types/node": "^20.12.0", diff --git a/src/azure/files/.azure-pipelines/pull-request.pipeline.yml b/src/azure/files/.azure-pipelines/pull-request.pipeline.yml new file mode 100644 index 0000000..466ecc7 --- /dev/null +++ b/src/azure/files/.azure-pipelines/pull-request.pipeline.yml @@ -0,0 +1,86 @@ +name: Pull-Request check for $(Build.SourceBranch) +trigger: none # Only triggered as part of a Branch Policy. +variables: + npm_config_cache: $(Pipeline.Workspace)/.npm + TargetBranch: origin/$(System.PullRequest.TargetBranchName) + +jobs: + - job: Test + steps: + - checkout: self + fetchDepth: 0 + + - task: UseNode@1 + displayName: Install Node.js + inputs: + version: 20.x + + - task: Cache@2 + displayName: Cache npm + inputs: + key: 'npm | "$(Agent.OS)" | package-lock.json' + restoreKeys: | + npm | "$(Agent.OS)" + path: $(npm_config_cache) + + - task: Npm@1 + displayName: Install node_modules + inputs: + customCommand: clean-install --ignore-scripts --no-audit --prefer-offline + + - script: npm audit --audit-level=high + displayName: Check npm dependency vulnerabilities + continueOnError: true + + - script: npx tsc -noEmit + displayName: Type-check code + + - script: npx prettier --check . + displayName: Check code formatting with Prettier + + - script: npm run lint + displayName: Analyze code with ESLint + + - script: npm run build + displayName: Build application + env: + NODE_ENV: production + + - script: npx jest --ci --coverage --selectProjects unit --changedSince=$(TargetBranch) + displayName: Run unit tests with coverage + env: + # Required for resolving ES modules in tests + NODE_OPTIONS: --experimental-vm-modules + # Configure jest-junit report + JEST_SUITE_NAME: unit tests + JEST_JUNIT_OUTPUT_NAME: unit.xml + + - task: PublishTestResults@2 + displayName: Publish unit test results + condition: succeededOrFailed() + inputs: + testRunTitle: Unit tests + testResultsFormat: JUnit + testResultsFiles: "reports/unit.xml" + + - task: PublishCodeCoverageResults@2 + displayName: Publish coverage results + inputs: + summaryFileLocation: "reports/cobertura-coverage.xml" + + - script: npx jest --ci --selectProjects e2e + displayName: Run end-to-end tests + env: + # Required for resolving ES modules in tests + NODE_OPTIONS: --experimental-vm-modules + # Configure jest-junit report + JEST_SUITE_NAME: end-to-end tests + JEST_JUNIT_OUTPUT_NAME: e2e.xml + + - task: PublishTestResults@2 + displayName: Publish end-to-end test results + condition: succeededOrFailed() + inputs: + testRunTitle: End-to-end tests + testResultsFormat: JUnit + testResultsFiles: "reports/e2e.xml" diff --git a/src/azure/index.spec.ts b/src/azure/index.spec.ts new file mode 100644 index 0000000..c25dc0f --- /dev/null +++ b/src/azure/index.spec.ts @@ -0,0 +1,22 @@ +import { Tree } from "@angular-devkit/schematics" +import { + SchematicTestRunner, + UnitTestTree, +} from "@angular-devkit/schematics/testing" + +const collectionPath = require.resolve("../collection.json") + +describe("azure", () => { + let tree: UnitTestTree + + beforeAll(async () => { + const runner = new SchematicTestRunner("schematics", collectionPath) + tree = await runner.runSchematic("azure", {}, Tree.empty()) + }) + + it("generates .azure-pipelines/pull-request.pipeline.yml", () => { + expect( + tree.get(".azure-pipelines/pull-request.pipeline.yml"), + ).not.toBeNull() + }) +}) diff --git a/src/azure/index.ts b/src/azure/index.ts new file mode 100644 index 0000000..be2073d --- /dev/null +++ b/src/azure/index.ts @@ -0,0 +1,11 @@ +import { + MergeStrategy, + Rule, + apply, + mergeWith, + url, +} from "@angular-devkit/schematics" + +export default function (): Rule { + return mergeWith(apply(url("./files"), []), MergeStrategy.Overwrite) +} diff --git a/src/collection.json b/src/collection.json index d76b58c..12855d7 100644 --- a/src/collection.json +++ b/src/collection.json @@ -6,6 +6,10 @@ "factory": "./application", "schema": "./application/schema.json" }, + "azure": { + "description": "Configures Azure Pipelines on an existing NestJS project.", + "factory": "./azure" + }, "docker": { "description": "Configures Docker on an existing NestJS project.", "factory": "./docker"