diff --git a/packages/workspace/src/generators/ci-workflow/ci-workflow.spec.ts b/packages/workspace/src/generators/ci-workflow/ci-workflow.spec.ts index fb2989d4b0..94aef2977b 100644 --- a/packages/workspace/src/generators/ci-workflow/ci-workflow.spec.ts +++ b/packages/workspace/src/generators/ci-workflow/ci-workflow.spec.ts @@ -78,8 +78,10 @@ describe('CI Workflow generator', () => { const nxJson = readNxJson(tree); delete nxJson.nxCloudAccessToken; updateNxJson(tree, nxJson); - } else { + } else if (nxCloudAccessToken) { process.env.NX_CLOUD_ACCESS_TOKEN = nxCloudAccessToken; + } else { + delete process.env.NX_CLOUD_ACCESS_TOKEN; } }); @@ -275,4 +277,281 @@ describe('CI Workflow generator', () => { 'sharedGlobals', ]); }); + + describe('TS solution setup', () => { + let nxCloudAccessToken: string; + + beforeEach(() => { + tree = createTreeWithEmptyWorkspace(); + updateJson(tree, 'package.json', (json) => { + json.workspaces = ['packages/*']; + return json; + }); + writeJson(tree, 'tsconfig.base.json', { + compilerOptions: { + composite: true, + declaration: true, + }, + }); + writeJson(tree, 'tsconfig.json', { + extends: './tsconfig.base.json', + files: [], + references: [], + }); + + nxCloudAccessToken = process.env.NX_CLOUD_ACCESS_TOKEN; + delete process.env.NX_CLOUD_ACCESS_TOKEN; + }); + + afterEach(() => { + if (nxCloudAccessToken) { + process.env.NX_CLOUD_ACCESS_TOKEN = nxCloudAccessToken; + } else { + delete process.env.NX_CLOUD_ACCESS_TOKEN; + } + }); + + it('should generate github config with typecheck task', async () => { + await ciWorkflowGenerator(tree, { ci: 'github', name: 'CI' }); + + expect(tree.read('.github/workflows/ci.yml', 'utf-8')) + .toMatchInlineSnapshot(` + "name: CI + + on: + push: + branches: + - main + pull_request: + + permissions: + actions: read + contents: read + + jobs: + main: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # This enables task distribution via Nx Cloud + # Run this command as early as possible, before dependencies are installed + # Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun + # Connect your workspace by running "nx connect" and uncomment this line to enable task distribution + # - run: npx nx-cloud start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="build" + + # Cache node_modules + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' + + - run: npm ci --legacy-peer-deps + - uses: nrwl/nx-set-shas@v4 + + # Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud + # - run: npx nx-cloud record -- echo Hello World + # Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected + - run: npx nx affected -t lint test build typecheck + " + `); + }); + + it('should generate circleci config with typecheck task', async () => { + await ciWorkflowGenerator(tree, { ci: 'circleci', name: 'CI' }); + + expect(tree.read('.circleci/config.yml', 'utf-8')).toMatchInlineSnapshot(` + "version: 2.1 + + orbs: + nx: nrwl/nx@1.6.2 + + jobs: + main: + docker: + - image: cimg/node:lts-browsers + steps: + - checkout + + # This enables task distribution via Nx Cloud + # Run this command as early as possible, before dependencies are installed + # Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun + # Connect your workspace by running "nx connect" and uncomment this line to enable task distribution + # - run: npx nx-cloud start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="build" + + - run: npm ci --legacy-peer-deps + - nx/set-shas: + main-branch-name: 'main' + + # Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud + # - run: npx nx-cloud record -- echo Hello World + # Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected + - run: npx nx affected -t lint test build typecheck + + workflows: + version: 2 + + ci: + jobs: + - main + " + `); + }); + + it('should generate azure config with typecheck task', async () => { + await ciWorkflowGenerator(tree, { ci: 'azure', name: 'CI' }); + + expect(tree.read('azure-pipelines.yml', 'utf-8')).toMatchInlineSnapshot(` + "name: CI + + trigger: + - main + pr: + - main + + variables: + CI: 'true' + \${{ if eq(variables['Build.Reason'], 'PullRequest') }}: + NX_BRANCH: $(System.PullRequest.PullRequestNumber) + TARGET_BRANCH: $[replace(variables['System.PullRequest.TargetBranch'],'refs/heads/','origin/')] + BASE_SHA: $(git merge-base $(TARGET_BRANCH) HEAD) + \${{ if ne(variables['Build.Reason'], 'PullRequest') }}: + NX_BRANCH: $(Build.SourceBranchName) + BASE_SHA: $(git rev-parse HEAD~1) + HEAD_SHA: $(git rev-parse HEAD) + + jobs: + - job: main + pool: + vmImage: 'ubuntu-latest' + steps: + - checkout: self + fetchDepth: 0 + # Set Azure Devops CLI default settings + - bash: az devops configure --defaults organization=$(System.TeamFoundationCollectionUri) project=$(System.TeamProject) + displayName: 'Set default Azure DevOps organization and project' + # Get last successfull commit from Azure Devops CLI + - bash: | + LAST_SHA=$(az pipelines build list --branch $(Build.SourceBranchName) --definition-ids $(System.DefinitionId) --result succeeded --top 1 --query "[0].triggerInfo.\\"ci.sourceSha\\"") + if [ -z "$LAST_SHA" ] + then + echo "Last successful commit not found. Using fallback 'HEAD~1': $BASE_SHA" + else + echo "Last successful commit SHA: $LAST_SHA" + echo "##vso[task.setvariable variable=BASE_SHA]$LAST_SHA" + fi + displayName: 'Get last successful commit SHA' + condition: ne(variables['Build.Reason'], 'PullRequest') + env: + AZURE_DEVOPS_EXT_PAT: $(System.AccessToken) + + # This enables task distribution via Nx Cloud + # Run this command as early as possible, before dependencies are installed + # Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun + # Connect your workspace by running "nx connect" and uncomment this line to enable task distribution + # - script: npx nx-cloud start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="build" + + - script: npm ci --legacy-peer-deps + - script: git branch --track main origin/main + condition: eq(variables['Build.Reason'], 'PullRequest') + + # Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud + # - script: npx nx-cloud record -- echo Hello World + # Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected + - script: npx nx affected --base=$(BASE_SHA) --head=$(HEAD_SHA) lint test build typecheck + " + `); + }); + + it('should generate bitbucket config with typecheck task', async () => { + await ciWorkflowGenerator(tree, { + ci: 'bitbucket-pipelines', + name: 'CI', + }); + + expect(tree.read('bitbucket-pipelines.yml', 'utf-8')) + .toMatchInlineSnapshot(` + "image: node:20 + + clone: + depth: full + + pipelines: + pull-requests: + '**': + - step: + name: 'Build and test affected apps on Pull Requests' + script: + - export NX_BRANCH=$BITBUCKET_PR_ID + + # This enables task distribution via Nx Cloud + # Run this command as early as possible, before dependencies are installed + # Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun + # Connect your workspace by running "nx connect" and uncomment this line to enable task distribution + # - npx nx-cloud start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="build" + + - npm ci --legacy-peer-deps + + # Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud + # npx nx-cloud record -- echo Hello World + # Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected + - npx nx affected --base=origin/main -t lint test build typecheck + + branches: + main: + - step: + name: 'Build and test affected apps on "main" branch changes' + script: + - export NX_BRANCH=$BITBUCKET_BRANCH + # This enables task distribution via Nx Cloud + # Run this command as early as possible, before dependencies are installed + # Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun + # Connect your workspace by running "nx connect" and uncomment this + # - npx nx-cloud start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="build" + + - npm ci --legacy-peer-deps + + # Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud + # - npx nx-cloud record -- echo Hello World + # Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected + - npx nx affected -t lint test build typecheck --base=HEAD~1 + " + `); + }); + + it('should generate gitlab config with typecheck task', async () => { + await ciWorkflowGenerator(tree, { ci: 'gitlab', name: 'CI' }); + + expect(tree.read('.gitlab-ci.yml', 'utf-8')).toMatchInlineSnapshot(` + "image: node:20 + variables: + CI: 'true' + + # Main job + CI: + interruptible: true + only: + - main + - merge_requests + script: + # This enables task distribution via Nx Cloud + # Run this command as early as possible, before dependencies are installed + # Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun + # Connect your workspace by running "nx connect" and uncomment this line to enable task distribution + # - npx nx-cloud start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="build" + + - npm ci --legacy-peer-deps + - NX_HEAD=$CI_COMMIT_SHA + - NX_BASE=\${CI_MERGE_REQUEST_DIFF_BASE_SHA:-$CI_COMMIT_BEFORE_SHA} + + # Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud + # - npx nx-cloud record -- echo Hello World + # Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected + - npx nx affected -t lint test build typecheck + " + `); + }); + }); }); diff --git a/packages/workspace/src/generators/ci-workflow/ci-workflow.ts b/packages/workspace/src/generators/ci-workflow/ci-workflow.ts index c2676a7a18..7403816899 100644 --- a/packages/workspace/src/generators/ci-workflow/ci-workflow.ts +++ b/packages/workspace/src/generators/ci-workflow/ci-workflow.ts @@ -12,6 +12,7 @@ import { import { deduceDefaultBase } from '../../utilities/default-base'; import { join } from 'path'; import { getNxCloudUrl, isNxCloudUsed } from 'nx/src/utils/nx-cloud-utils'; +import { isUsingTsSolutionSetup } from '../../utilities/typescript/ts-solution-setup'; export interface Schema { name: string; @@ -47,6 +48,7 @@ interface Substitutes { nxCloudHost: string; hasCypress: boolean; hasE2E: boolean; + hasTypecheck: boolean; hasPlaywright: boolean; tmpl: ''; connectedToCloud: boolean; @@ -78,6 +80,7 @@ function normalizeOptions(options: Schema, tree: Tree): Substitutes { const hasCypress = allDependencies['@nx/cypress']; const hasPlaywright = allDependencies['@nx/playwright']; const hasE2E = hasCypress || hasPlaywright; + const hasTypecheck = isUsingTsSolutionSetup(tree); const connectedToCloud = isNxCloudUsed(readJson(tree, 'nx.json')); @@ -92,6 +95,7 @@ function normalizeOptions(options: Schema, tree: Tree): Substitutes { hasCypress, hasE2E, hasPlaywright, + hasTypecheck, nxCloudHost, tmpl: '', connectedToCloud, diff --git a/packages/workspace/src/generators/ci-workflow/files/azure/azure-pipelines.yml__tmpl__ b/packages/workspace/src/generators/ci-workflow/files/azure/azure-pipelines.yml__tmpl__ index 51e0610f67..cb4076372f 100644 --- a/packages/workspace/src/generators/ci-workflow/files/azure/azure-pipelines.yml__tmpl__ +++ b/packages/workspace/src/generators/ci-workflow/files/azure/azure-pipelines.yml__tmpl__ @@ -68,4 +68,4 @@ jobs: # - script: <%= packageManagerPrefix %> nx-cloud record -- echo Hello World # Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected<% if(hasE2E){ %> # When you enable task distribution, run the e2e-ci task instead of e2e<% } %> - - script: <%= packageManagerPrefix %> nx affected --base=$(BASE_SHA) --head=$(HEAD_SHA) lint test build<% if(hasE2E){ %> e2e<% } %> + - script: <%= packageManagerPrefix %> nx affected --base=$(BASE_SHA) --head=$(HEAD_SHA) lint test build<% if(hasTypecheck){ %> typecheck<% } %><% if(hasE2E){ %> e2e<% } %> diff --git a/packages/workspace/src/generators/ci-workflow/files/bitbucket-pipelines/bitbucket-pipelines.yml__tmpl__ b/packages/workspace/src/generators/ci-workflow/files/bitbucket-pipelines/bitbucket-pipelines.yml__tmpl__ index f1ae9804f3..775a449c6e 100644 --- a/packages/workspace/src/generators/ci-workflow/files/bitbucket-pipelines/bitbucket-pipelines.yml__tmpl__ +++ b/packages/workspace/src/generators/ci-workflow/files/bitbucket-pipelines/bitbucket-pipelines.yml__tmpl__ @@ -33,7 +33,7 @@ pipelines: # <%= packageManagerPrefix %> nx-cloud record -- echo Hello World # Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected<% if(hasE2E){ %> # When you enable task distribution, run the e2e-ci task instead of e2e<% } %> - - <%= packageManagerPrefix %> nx affected --base=origin/<%= mainBranch %> -t lint test build<% if(hasE2E){ %> e2e<% } %> + - <%= packageManagerPrefix %> nx affected --base=origin/<%= mainBranch %> -t lint test build<% if(hasTypecheck){ %> typecheck<% } %><% if(hasE2E){ %> e2e<% } %> branches: main: @@ -59,4 +59,4 @@ pipelines: # Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud # - <%= packageManagerPrefix %> nx-cloud record -- echo Hello World # Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected - - <%= packageManagerPrefix %> nx affected -t lint test build<% if(hasE2E){ %> e2e-ci<% } %> --base=HEAD~1 + - <%= packageManagerPrefix %> nx affected -t lint test build<% if(hasTypecheck){ %> typecheck<% } %><% if(hasE2E){ %> e2e-ci<% } %> --base=HEAD~1 diff --git a/packages/workspace/src/generators/ci-workflow/files/circleci/.circleci/config.yml__tmpl__ b/packages/workspace/src/generators/ci-workflow/files/circleci/.circleci/config.yml__tmpl__ index 89a844a9a0..7ed8056a1f 100644 --- a/packages/workspace/src/generators/ci-workflow/files/circleci/.circleci/config.yml__tmpl__ +++ b/packages/workspace/src/generators/ci-workflow/files/circleci/.circleci/config.yml__tmpl__ @@ -37,7 +37,7 @@ jobs: # - run: <%= packageManagerPrefix %> nx-cloud record -- echo Hello World # Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected<% if(hasE2E){ %> # When you enable task distribution, run the e2e-ci task instead of e2e<% } %> - - run: <%= packageManagerPrefix %> nx affected -t lint test build<% if(hasE2E){ %> e2e<% } %> + - run: <%= packageManagerPrefix %> nx affected -t lint test build<% if(hasTypecheck){ %> typecheck<% } %><% if(hasE2E){ %> e2e<% } %> workflows: version: 2 diff --git a/packages/workspace/src/generators/ci-workflow/files/github/.github/workflows/__workflowFileName__.yml__tmpl__ b/packages/workspace/src/generators/ci-workflow/files/github/.github/workflows/__workflowFileName__.yml__tmpl__ index 8df87b8e64..da09f64d5b 100644 --- a/packages/workspace/src/generators/ci-workflow/files/github/.github/workflows/__workflowFileName__.yml__tmpl__ +++ b/packages/workspace/src/generators/ci-workflow/files/github/.github/workflows/__workflowFileName__.yml__tmpl__ @@ -50,4 +50,4 @@ jobs: # - run: <%= packageManagerPrefix %> nx-cloud record -- echo Hello World # Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected<% if(hasE2E){ %> # When you enable task distribution, run the e2e-ci task instead of e2e<% } %> - - run: <%= packageManagerPrefix %> nx affected -t lint test build<% if(hasE2E){ %> e2e<% } %> + - run: <%= packageManagerPrefix %> nx affected -t lint test build<% if(hasTypecheck){ %> typecheck<% } %><% if(hasE2E){ %> e2e<% } %> diff --git a/packages/workspace/src/generators/ci-workflow/files/gitlab/.gitlab-ci.yml__tmpl__ b/packages/workspace/src/generators/ci-workflow/files/gitlab/.gitlab-ci.yml__tmpl__ index 857ecc3eb1..276cf6fbb0 100644 --- a/packages/workspace/src/generators/ci-workflow/files/gitlab/.gitlab-ci.yml__tmpl__ +++ b/packages/workspace/src/generators/ci-workflow/files/gitlab/.gitlab-ci.yml__tmpl__ @@ -31,4 +31,4 @@ variables: # - <%= packageManagerPrefix %> nx-cloud record -- echo Hello World # Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected<% if(hasE2E){ %> # When you enable task distribution, run the e2e-ci task instead of e2e<% } %> - - <%= packageManagerPrefix %> nx affected -t lint test build<% if(hasE2E){ %> e2e<% } %> + - <%= packageManagerPrefix %> nx affected -t lint test build<% if(hasTypecheck){ %> typecheck<% } %><% if(hasE2E){ %> e2e<% } %>