Compare commits

..

3 Commits

Author SHA1 Message Date
Victor Savkin 5023a8bf59 Release 10.4.3 2020-11-18 10:06:01 -05:00
Victor Savkin cbd404ccd1 fix(core): add explicit dep on cli if missing 2020-11-18 10:03:26 -05:00
Victor Savkin 95889a2447 fix(core): migration should fetch packages using cwd instead of prefix 2020-11-18 10:03:24 -05:00
12652 changed files with 400159 additions and 1617831 deletions
-12
View File
@@ -1,12 +0,0 @@
[build]
target-dir = 'dist/target'
[target.x86_64-unknown-linux-musl]
rustflags = [
"-C",
"target-feature=-crt-static",
]
[target.aarch64-unknown-linux-musl]
linker = "aarch64-linux-musl-gcc"
rustflags = ["-C", "target-feature=-crt-static"]
+186 -28
View File
@@ -1,37 +1,195 @@
# Javascript Node CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-javascript/ for more details
#
version: 2.1
# -------------------------
# EXECUTORS
# -------------------------
defaults: &defaults
working_directory: ~/repo
executors:
linux:
<<: *defaults
default:
working_directory: ~/repo
environment:
# install Cypress in Linux-like cache folder
CYPRESS_CACHE_FOLDER: '~/.cache/Cypress'
docker:
- image: cimg/rust:1.84.0-browsers
resource_class: small
- image: circleci/node:12-browsers
# -------------------------
# JOBS
# -------------------------
jobs:
# -------------------------
# JOBS: Main Linux
# -------------------------
main-linux:
executor: linux
commands:
install_rsync:
description: 'Install Rsync'
steps:
- run: echo "We are in the process of transitioning from Circle CI to GitHub Actions. For details about your build results, consult github actions build logs."
- run: sudo apt install rsync
yarn_install:
description: 'Install Dependencies'
steps:
- run: yarn install --frozen-lockfile --non-interactive
- run: ./node_modules/.bin/cypress verify
- save_cache:
key: nrwl-nx-node12-yarn-key-{{ checksum "yarn.lock" }}
paths:
- ~/.cache/yarn
- save_cache:
key: nrwl-nx-node12-cypress-{{ checksum "yarn.lock" }}
paths:
- ~/.cache/Cypress
restore_cypress_cache:
description: 'Restore Cypress Cache'
steps:
- restore_cache:
keys:
- nrwl-nx-node12-cypress-{{ checksum "yarn.lock" }}
# fallback to using the latest cache if no exact match is found
- nrwl-nx-node12-cypress-
restore_yarn_cache:
description: 'Restore Cached Dependencies'
steps:
- restore_cache:
keys:
- nrwl-nx-node12-yarn-key-{{ checksum "yarn.lock" }}
# fallback to using the latest cache if no exact match is found
- nrwl-nx-node12-yarn-key-
setup:
description: 'Setup Executor'
steps:
- checkout
- install_rsync
- attach_workspace:
# Must be absolute path or relative path from working_directory
at: ..
# -------------------------
# WORKFLOWS(JOBS)
# -------------------------
jobs:
install:
executor: default
steps:
- checkout
- restore_yarn_cache
- restore_cypress_cache
- yarn_install
- persist_to_workspace:
# Must be an absolute path, or relative path from working_directory. This is a directory on the container which is
# taken to be the root directory of the workspace.
root: ..
# Must be relative path from root
paths:
- repo/node_modules
- .cache/Cypress
checks-and-unit-tests:
executor: default
steps:
- setup
- run:
name: Run Unit Tests
command: yarn test
- run:
name: Check Documentation
command: yarn documentation
- run:
name: Check Imports
command: yarn check-imports
- run:
name: Check Formatting
command: yarn check-format
- run:
name: Run linting
command: yarn lint
- run:
name: Check Commit Message Format
command: yarn check-commit
- run:
name: Check Package dependencies
command: yarn depcheck
e2e-1:
executor: default
steps:
- setup
- run:
name: Tests Part 1
command: yarn e2e-ci 1
no_output_timeout: 30m
e2e-2:
executor: default
steps:
- setup
- run:
name: Tests Part 2
command: yarn e2e-ci 2
no_output_timeout: 30m
e2e-3:
executor: default
steps:
- setup
- run:
name: Tests Part 3
command: yarn e2e-ci 3
no_output_timeout: 30m
e2e-4:
executor: default
steps:
- setup
- run:
name: Tests Part 4
command: yarn e2e-ci 4
no_output_timeout: 30m
e2e-5:
executor: default
steps:
- setup
- run:
name: Tests Part 5
command: yarn e2e-ci 5
no_output_timeout: 30m
e2e-6:
executor: default
steps:
- setup
- run:
name: Tests Part 6
command: yarn e2e-ci 6
no_output_timeout: 30m
e2e-7:
executor: default
steps:
- setup
- run:
name: Tests Part 7
command: yarn e2e-ci 7
no_output_timeout: 30m
e2e-8:
executor: default
steps:
- setup
- run:
name: Tests Part 8
command: yarn e2e-ci 8
no_output_timeout: 30m
workflows:
version: 2
build:
version: 2.1
default_workflow:
jobs:
- main-linux
- install
- checks-and-unit-tests:
requires:
- install
- e2e-1:
requires:
- install
- e2e-2:
requires:
- install
- e2e-3:
requires:
- install
- e2e-4:
requires:
- install
- e2e-5:
requires:
- install
- e2e-6:
requires:
- install
- e2e-7:
requires:
- install
- e2e-8:
requires:
- install
-47
View File
@@ -1,47 +0,0 @@
# Commit Command
## Description
Create a git commit following Nx repository standards and validation requirements.
## Usage
```bash
/commit [message]
```
## What this command does:
1. **Pre-commit validation**: Runs the full validation suite (`pnpm nx prepush`) to ensure code quality
2. **Formatting**: Automatically formats changed files with Prettier
3. **Testing**: Runs tests on affected projects to validate changes
4. **Commit creation**: Creates a well-formed commit with proper message formatting (without co-author attribution)
5. **Status reporting**: Provides clear feedback on the commit process
## Workflow:
1. Format any modified files with Prettier
2. Run the prepush validation suite
3. If validation passes, stage relevant changes
4. Create commit with descriptive message
5. Provide summary of what was committed
## Commit Message Format:
- Use conventional commit format when appropriate
- Include scope (e.g., `feat(core):`, `fix(angular):`, `docs(nx):`)
- Keep first line under 72 characters
- Include detailed description if needed
## Examples:
- `/commit "feat(core): add new project graph visualization"`
- `/commit "fix(react): resolve build issues with webpack config"`
- `/commit "docs(nx): update getting started guide"`
## Validation Requirements:
- All tests must pass
- Code must be properly formatted
- No linting errors
- E2E tests for affected areas should pass
-155
View File
@@ -1,155 +0,0 @@
# GitHub Issue Planning and Resolution
This command provides guidance for both automated and manual GitHub issue workflows.
## Automated Workflow (GitHub Actions)
The automated workflow consists of two phases:
### Phase 1: Planning (`@claude plan` or `claude:plan` label)
- Claude analyzes the issue and creates a detailed implementation plan
- Plan is posted as a comment on the issue
- Issue is labeled with `claude:planned`
### Phase 2: Implementation (`@claude implement` or `claude:implement` label)
- Claude implements the solution based on the plan
- Runs validation tests and creates a feature branch
- Suggests opening a PR with proper formatting
## Planning Phase Template
When creating a plan (either automated or manual), include these sections:
### Problem Analysis
- Root cause identification
- Impact assessment
- Related components or systems affected
### Proposed Solution
- High-level approach
- Alternative solutions considered
- Trade-offs and rationale
### Implementation Details
- Files that need to be modified
- Key changes required
- Dependencies or prerequisites
### Testing Strategy
- Unit tests to add/modify
- Integration tests needed
- E2E test considerations
### Validation Steps
```bash
# Test specific affected projects
nx run-many -t test,build,lint -p PROJECT_NAME
# Test all affected projects
nx affected -t build,test,lint
# Run affected e2e tests
nx affected -t e2e-local
# Format code
npx nx prettier -- FILES
# Final validation
pnpm nx prepush
```
### Risks and Considerations
- Breaking changes
- Performance implications
- Migration requirements
## Manual Workflow
When working on a GitHub issue manually, follow this systematic approach:
## 1. Get Issue Details
```bash
# Get issue details using GitHub CLI (replace ISSUE_NUMBER with actual number)
gh issue view ISSUE_NUMBER
```
When cloning reproduction repos, please clone within `./tmp/claude/repro-ISSUE_NUMBER`
## 2. Analyze the Plan
- Look for a plan or implementation details in the issue description
- Check comments for additional context or clarification
- Identify affected projects and components
## 3. Implement the Solution
- Follow the plan outlined in the issue
- Make focused changes that address the specific problem
- Ensure code follows existing patterns and conventions
## 4. Run Full Validation
```bash
# Test specific affected projects first
nx run-many -t test,build,lint -p PROJECT_NAME
# Test all affected projects
nx affected -t build,test,lint
# Run affected e2e tests
nx affected -t e2e-local
# Final pre-push validation
pnpm nx prepush
```
## 5. Submit Pull Request
- Create a descriptive PR title that references the issue
- Include "Fixes #ISSUE_NUMBER" in the PR description
- Provide a clear summary of changes made
- Request appropriate reviewers
## Pull Request Template
When creating a pull request, follow the template found in `.github/PULL_REQUEST_TEMPLATE.md`. The template includes:
### Required Sections
1. **Current Behavior**: Describe the behavior we have today
2. **Expected Behavior**: Describe the behavior we should expect with the changes in this PR
3. **Related Issue(s)**: Link the issue being fixed so it gets closed when the PR is merged
### Template Format
```markdown
## Current Behavior
<!-- This is the behavior we have today -->
## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR -->
## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is merged. -->
Fixes #ISSUE_NUMBER
```
### Guidelines
- Ensure your commit message follows the conventional commit format (use `pnpm commit`)
- Read the submission guidelines in CONTRIBUTING.md before posting
- For complex changes, you can request a dedicated Nx release by mentioning the Nx team
- Always link the related issue using "Fixes #ISSUE_NUMBER" to automatically close it when merged
-30
View File
@@ -1,30 +0,0 @@
# Claude Issue Workflow Usage Guide
## Quick Start
## Expected Outputs
### Planning Phase
- Detailed analysis comment posted to issue
- Implementation plan with steps and file changes
- Testing strategy and validation steps
- Risk assessment
### Implementation Phase
- Code changes made according to plan
- Tests run and validated
- Feature branch created: `fix/issue-{number}`
- PR suggestion with proper title format
## Manual Override
If you need to work on an issue manually, use the `/gh-issue-plan` command for structured guidance following the same workflow patterns.
## Troubleshooting
- Ensure you're on the authorized users list
- Check that the issue has sufficient detail for analysis
- For implementation, ensure a plan comment exists from the planning phase
- If workflows fail, check the Actions tab for detailed logs
-34
View File
@@ -1,34 +0,0 @@
{
"permissions": {
"allow": [
"Bash(find:*)",
"Bash(ls:*)",
"Bash(mkdir:*)",
"WebFetch(domain:github.com)",
"WebFetch(domain:www.typescriptlang.org)",
"Bash(git log:*)",
"Bash(gh issue list:*)",
"Bash(gh issue view:*)",
"Bash(npx prettier:*)",
"Bash(nx prepush:*)",
"Bash(pnpm commit:*)",
"Bash(rg:*)",
"mcp__nx__nx_docs",
"mcp__nx__nx_workspace",
"mcp__nx__nx_project_details",
"Bash(nx show projects:*)",
"Bash(nx run-many:*)",
"Bash(nx run:*)",
"Bash(nx affected:*)",
"Bash(nx lint:*)",
"Bash(nx test:*)",
"Bash(nx build:*)",
"Bash(nx documentation:*)"
],
"deny": []
},
"enableAllProjectMcpServers": true,
"env": {
"BASH_MAX_TIMEOUT_MS": "1800000"
}
}
+83
View File
@@ -0,0 +1,83 @@
module.exports = {
types: [
{ value: 'feat', name: 'feat: A new feature' },
{ value: 'fix', name: 'fix: A bug fix' },
{ value: 'docs', name: 'docs: Documentation only changes' },
{
value: 'cleanup',
name:
'cleanup: A code change that neither fixes a bug nor adds a feature',
},
{
value: 'chore',
name: "chore: Other changes that don't modify src or test files",
},
],
scopes: [
{ name: 'angular', description: 'anything Angular specific' },
{ name: 'core', description: 'anything Nx core specific' },
{ name: 'docs', description: 'anything related to docs infrastructure' },
{ name: 'nextjs', description: 'anything Next specific' },
{ name: 'nest', description: 'anything Nest specific' },
{ name: 'node', description: 'anything Node specific' },
{ name: 'express', description: 'anything Express specific' },
{ name: 'nx-plugin', description: 'anything Nx Plugin specific' },
{ name: 'react', description: 'anything React specific' },
{ name: 'web', description: 'anything Web specific' },
{ name: 'linter', description: 'anything Linter specific' },
{ name: 'storybook', description: 'anything Storybook specific' },
{
name: 'testing',
description: 'anything testing specific (e.g., jest or cypress)',
},
{
name: 'repo',
description: 'anything related to managing the repo itself',
},
{ name: 'misc', description: 'misc stuff' },
],
allowTicketNumber: true,
isTicketNumberRequired: false,
ticketNumberPrefix: 'TICKET-',
ticketNumberRegExp: '\\d{1,5}',
// it needs to match the value for field type. Eg.: 'fix'
/*
scopeOverrides: {
fix: [
{name: 'merge'},
{name: 'style'},
{name: 'e2eTest'},
{name: 'unitTest'}
]
},
*/
// override the messages, defaults are as follows
messages: {
type: "Select the type of change that you're committing:",
scope: '\nDenote the SCOPE of this change (optional):',
// used if allowCustomScopes is true
customScope: 'Denote the SCOPE of this change:',
subject:
'Write a SHORT, IMPERATIVE (lowercase) description of the change:\n',
body:
'Provide a LONGER description of the change (optional). Use "|" to break new line:\n',
breaking: 'List any BREAKING CHANGES (optional):\n',
footer:
'List any ISSUES CLOSED by this change (optional). E.g.: #31, #34:\n',
confirmCommit: 'Are you sure you want to proceed with the commit above?',
},
allowCustomScopes: false,
allowBreakingChanges: ['feat', 'fix'],
// skip any questions you want
skipQuestions: ['ticketNumber'],
// limit subject length
subjectLimit: 100,
// breaklineChar: '|', // It is supported for fields body and footer.
// footerPrefix : 'ISSUES CLOSED:'
// askForBreakingChangeFirst : true, // default is false
};
-48
View File
@@ -1,48 +0,0 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node
{
"name": "NxDevContainer",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
// Starting from a base image that already contains GLIBC v2.33 or higher (required by Nx)
// Try a more recent distribution, if your are having build issues related to GLIBC version
// Here we use 'bookworm', which is based on `Debian-12`, which comes with `GLIBC v2.36`
// (Nx tools currenlty requires `GLIBC v2.33` or higher)
"image": "mcr.microsoft.com/devcontainers/typescript-node:20-bookworm",
"features": {
"ghcr.io/devcontainers/features/rust:1": {}
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// 4211 = nx graph port
// 4873 = verdaccio (local npm registry) port
"forwardPorts": [4211, 4873],
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "./.devcontainer/postCreateCommand.sh",
// Configure tool-specific properties.
"customizations": {
"vscode": {
"extensions": [
"nrwl.angular-console",
"firsttris.vscode-jest-runner",
"eamodio.gitlens",
"mhutchie.git-graph",
"mutantdino.resourcemonitor" // to monitor cpu, memory usage from the dev container
],
"settings": {
"debug.javascript.autoAttachFilter": "disabled" // workaround for that issue: https://github.com/microsoft/vscode-js-debug/issues/374#issuecomment-622239998
}
}
},
// To improve disk performances when installing node modules
// See https://code.visualstudio.com/remote/advancedcontainers/improve-performance
"mounts": [
"source=${localWorkspaceFolderBasename}-node_modules,target=${containerWorkspaceFolder}/node_modules,type=volume"
],
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
"remoteUser": "root"
}
-23
View File
@@ -1,23 +0,0 @@
#!/bin/sh
# Update the underlying (Debian) OS, to make sure we have the latest security patches and libraries like 'GLIBC'
echo "⚙️ Updating the underlying OS..."
sudo apt-get update && sudo apt-get -y upgrade
# Uninstall globally installed PNPM (required version will be reinstalled through corepack)
echo "❌ Uninstalling globally installed PNPM..."
npm uninstall -g pnpm
# Prevent corepack from prompting user before downloading PNPM
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
# Enable corepack
corepack enable
# Install the PNPM version defined in the root package.json
echo "⚙️ Installing required PNPM version..."
corepack prepare --activate
# Install NPM dependencies
echo "⚙️ Installing NPM dependencies..."
pnpm install --frozen-lockfile
-18
View File
@@ -1,18 +0,0 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
# 4 space indentation
[*.{js,ts,jsx,tsx}]
indent_style = space
indent_size = 2
[package.json]
indent_style = space
indent_size = 2
-1
View File
@@ -1 +0,0 @@
node_modules
+8 -92
View File
@@ -1,101 +1,17 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.*?.json"
},
"env": {
"node": true
},
"ignorePatterns": ["**/*.ts", "**/test-output"],
"plugins": ["@typescript-eslint", "@nx"],
"extends": ["plugin:storybook/recommended"],
"ignorePatterns": ["**/*.ts"],
"plugins": ["@typescript-eslint"],
"extends": [],
"rules": {
"@typescript-eslint/explicit-module-boundary-types": "off",
"no-restricted-imports": [
"error",
{
"paths": [
{
"name": "create-nx-workspace",
"message": "Please import utils from nx or @nx/devkit instead."
},
{
"name": "node-fetch",
"message": "Please default to native fetch instead of 'node-fetch'."
}
]
}
],
"@typescript-eslint/no-restricted-imports": [
"error",
{
"patterns": [
{
"group": ["nx/src/plugins/js*"],
"message": "Imports from 'nx/src/plugins/js' are not allowed. Use '@nx/js' instead"
},
{
"group": ["**/native-bindings", "**/native-bindings.js", ""],
"message": "Direct imports from native-bindings.js are not allowed. Import from index.js instead."
}
]
}
],
"storybook/no-uninstalled-addons": [
"error",
{
"ignore": ["@nx/react/plugins/storybook"],
"packageJsonLocation": "../../package.json"
}
]
"@typescript-eslint/explicit-module-boundary-types": "off"
},
"overrides": [
{
"files": ["*.json"],
"parser": "jsonc-eslint-parser",
"rules": {}
},
{
"files": ["**/executors/**/schema.json", "**/generators/**/schema.json"],
"rules": {
"@nx/workspace/valid-schema-description": "error"
}
},
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {
"@nx/enforce-module-boundaries": [
"error",
{
"enforceBuildableLibDependency": true,
"checkDynamicDependenciesExceptions": [".*"],
"allow": [],
"depConstraints": [
{
"sourceTag": "*",
"onlyDependOnLibsWithTags": ["*"]
}
]
}
],
"@nx/workspace/valid-command-object": "error"
}
},
{
"files": ["pnpm-lock.yaml"],
"parser": "./tools/eslint-rules/raw-file-parser.js",
"rules": {
"@nx/workspace/ensure-pnpm-lock-version": [
"error",
{
"version": "9.0"
}
]
}
},
{
"files": ["*.ts"],
"rules": {
"@angular-eslint/prefer-standalone": "off"
}
}
]
"overrides": []
}
-10
View File
@@ -1,10 +0,0 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# Linux start script should use lf
/gradlew text eol=lf
# These are Windows script files and should use crlf
*.bat text eol=crlf
# Exclude files from Graphite reviews
docs/generated/* linguist-generated=true
*.pdf,*.gif,*.mp4,*.webp,*.avif,*.png,*.jpeg,*.jpg,*.tiff filter=lfs diff=lfs merge=lfs -text
+33
View File
@@ -0,0 +1,33 @@
---
name: "🐞 Bug Report"
about: Report Current Behavior that is believed to be unintentional or unexpected.
labels: "type: bug"
---
<!-- Please do your best to fill out all of the sections below! -->
## Current Behavior
<!-- What is the behavior that currently you experience? -->
## Expected Behavior
<!-- What is the behavior that you expect to happen? -->
<!-- Is this a regression? .i.e Did this used to be the behavior at one point? -->
## Steps to Reproduce
<!-- Help us help you by making it easy for us to reproduce your issue! -->
<!-- Can you reproduce this on https://github.com/nrwl/nx-examples? -->
<!-- If so, open a PR with your changes and link it below. -->
<!-- If not, please provide a minimal Github repo -->
<!-- At the very least, provide as much detail as possible to help us reproduce the issue -->
<!-- Remove this line -->
This issue may not be prioritized if details are not provided to help us reproduce the issue.
### Failure Logs
<!-- Please include any relevant log snippets or files here. -->
### Environment
<!-- It's important for us to know the context in which you experience this behavior! -->
<!-- Please paste the result of `nx report` below! -->
-83
View File
@@ -1,83 +0,0 @@
name: 🐞 Bug Report
description: This form is to report unexpected behavior in Nx.
labels: ["type: bug"]
type: Bug
body:
- type: markdown
attributes:
value: |
Thank you for taking your precious time to file an issue! 🙏 We are sorry for the inconvenience this issue has caused you and want to resolve it as soon as possible.
Help us help you! We know that your time is precious and hate to ask for any more of it, but the first step in fixing this issue is to understand the issue. Taking some extra time to ensure that we are able to reproduce the issue will help us significantly in resolving the issue.
- type: textarea
id: current-behavior
attributes:
label: Current Behavior
description: What is the behavior that currently you experience?
validations:
required: true
- type: textarea
id: expected-behavior
attributes:
label: Expected Behavior
description: What is the behavior that you expect to happen?
validations:
required: true
- type: input
id: repo
attributes:
label: GitHub Repo
description: |
This is extremely important! If this issue is reproduce-able on https://github.com/nrwl/nx-examples, you may use that as the repo.
If not, please do take a few minutes of your time to create a repo to help us reproduce the issue.
This is the best way to help us reproduce the issue and fix it as soon as possible.
- type: textarea
id: reproduction
attributes:
label: Steps to Reproduce
description: Please provide some instructions to reproduce the issue in the repo provided above. Be as detailed as possible.
value: |
1.
validations:
required: true
- type: textarea
id: nx-report
attributes:
label: Nx Report
description: Please paste the contents shown by `nx report`. This will be automatically formatted into code, so no need for backticks.
render: shell
validations:
required: true
- type: textarea
id: logs
attributes:
label: Failure Logs
description: Please include any relevant log snippets or files here. This will be automatically formatted into code, so no need for backticks.
render: shell
- type: input
id: pm
attributes:
label: Package Manager Version
description: |
If `nx report` doesn't work, please provide the name and the version of your package manager.
You can get version information by running `PACKAGE_MANAGER --version`, where PACKAGE_MANAGER is any of `yarn`, `pnpm`, `bun` or `npm`, depending on the package manager used.
- type: checkboxes
id: os
attributes:
label: Operating System
description: What Operating System are you using?
options:
- label: macOS
- label: Linux
- label: Windows
- label: Other (Please specify)
- type: textarea
id: additional
attributes:
label: Additional Information
description: Is there any additional information that you can provide?
- type: markdown
id: disclaimer
attributes:
value: |
> If we are not able to reproduce the issue, we will likely prioritize fixing other issues we can reproduce. Please do your best to fill out all of the sections above.
-26
View File
@@ -1,26 +0,0 @@
---
name: "📖 Documentation issue"
about: Help improve our docs.
labels: "type: docs"
---
### Documentation issue
<!-- (Update "[ ]" to "[x]" to check a box) -->
- [ ] Reporting a typo
- [ ] Reporting a documentation bug
- [ ] Documentation improvement
- [ ] Documentation feedback
<!--
If your issue is not regarding the documentation, please choose an issue type:
https://github.com/nrwl/nx/issues/new/choose
-->
### Is there a specific documentation page you are reporting?
Enter the URL or documentation section here.
### Additional context or description
Provide any additional details here as needed.
+20
View File
@@ -0,0 +1,20 @@
---
name: "\U0001F680 Feature Request"
about: Request Behavior that does not currently exist in Nx
labels: "type: feature"
---
<!-- Please do your best to fill out all of the sections below! -->
## Description
<!-- What is the behavior that you would like to see introduced? -->
## Motivation
<!-- Why do you believe this behavior would be beneficial? -->
## Suggested Implementation
<!-- How do you imagine this might work? -->
## Alternate Implementations
<!-- How else do you imagine this might work? -->
+11
View File
@@ -0,0 +1,11 @@
---
name: "💡 Discussion"
about: "Start a thread to discuss an idea"
labels: "type: question / discussion"
---
<!-- Please do your best to fill out all of the sections below! -->
## Description
<!-- What would you like to discuss? -->
+7 -13
View File
@@ -1,17 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: "\U0001F680 Feature Request"
about: "Suggest a new feature to make Nx better"
url: https://github.com/nrwl/nx/discussions/new?category=feature-requests
- name: Start a Discussion
about: "Start a discussion to share your experience with Nx"
url: https://github.com/nrwl/nx/discussions/new/choose
- name: Join the Discord
url: https://go.nx.dev/community
about: "The Nx Official Discord Server is a great place for questions to be asked and answered. Please use the #forum if you need help with your workspace!"
- name: Are you looking for integration with a new tool?
url: https://nx.dev/community
about: "There are a lot of awesome Plugins for Nx provided by the community! Check here to see if there is a community plugin to integrate your tool."
- name: Read the community guidelines
- name: Read the Community Guidelines
about: "Please make sure you have read the submission guidelines before posting an issue"
url: https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-an-issue
- name: Have a question?
url: https://bit.ly/2ZApcSo
about: "The Community Slack is a great place for questions to be asked and answered. Please use the #support channel if you need help with your workspace!"
- name: Are you looking for integration with a new tool?
url: https://nx.dev/nx-community
about: "There are a lot of awesome Plugins for Nx provided by the community! Check here to see if there is a community plugin to integrate your tool."
-2
View File
@@ -4,8 +4,6 @@
<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->
<!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. -->
## Current Behavior
<!-- This is the behavior we have today -->
@@ -1,31 +1,9 @@
<!--
_[Please make sure you have read the submission guidelines before posting an PR](https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#submit-pr)_
# Community Plugin Submission
Thanks for submitting your Nx Plugin to our community plugins list. Make sure to follow these steps to ensure that your PR is approved in a timely manner.
## Plugin Requirements
Before you submit your plugin to be listed in our registry, it needs to meet the following requirements:
- Run some kind of automated e2e tests in your repository
- Include `@nx/devkit` as a `dependency` in the plugin's `package.json`
- List a `repository.url` in the plugin's `package.json`
i.e.
```
{
"repository": {
"type": "git",
"url": "https://github.com/nrwl/nx.git",
"directory": "packages/web"
}
}
```
Note: We reserve the right to remove unmaintained plugins from the registry. If the plugins become maintained again, they can be resubmitted to the registry.
## Steps to Submit Your Plugin
- Use the following commit message template: `chore(core): nx plugin submission [PLUGIN_NAME]`
- Update the `community/approved-plugins.json` file with a new entry for your plugin that includes `name`, `url`, `description`:
@@ -42,15 +20,4 @@ Example:
}]
```
Once merged, your plugin will be available when running the `nx list` command, and will also be available in the Plugin Registry on [nx.dev](https://nx.dev/plugin-registry)
-->
# Community Plugin Submission
## {replace with plugin's name}
<!--
Describe what your plugin is and what is its goal or issues it addresses. If you don't provide a description, we will not merge your PR.
Is it focused on a technology, tooling or behaviour? Does the plugin provide generators, executors or graph support?
Do you know who is already using the plugin? Mention who is the author of the plugin.
-->
Once merged, your will plugin will be available when running the `nx list` command, and will also be available in the Plugin browser on [nx.dev](https://nx.dev)
-297
View File
@@ -1,297 +0,0 @@
name: CI
on:
push:
branches:
- master
- '[0-9]+.[0-9]+.x'
pull_request:
branches:
- "**"
env:
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
PNPM_HOME: ~/.pnpm
jobs:
main-linux:
runs-on: ubuntu-latest
env:
NX_E2E_CI_CACHE_KEY: e2e-github-linux
NX_DAEMON: 'true'
NX_PERF_LOGGING: 'false'
NX_VERBOSE_LOGGING: 'false'
NX_NATIVE_LOGGING: 'false'
NX_E2E_RUN_E2E: 'true'
NX_CI_EXECUTION_ENV: 'linux'
NX_CLOUD_NO_TIMEOUTS: 'true'
NX_ALLOW_NON_CACHEABLE_DTE: 'true'
NX_CLOUD_USE_NEW_TASK_APIS: 'true'
NX_CLOUD_USE_NEW_STREAM_OUTPUT: 'true'
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 0
filter: tree:0
- name: Fetch Master
run: git fetch origin master:master
if: ${{ github.event_name == 'pull_request' }}
- name: Set SHAs
uses: nrwl/nx-set-shas@1859e66a83ac9be0dceecbd9a023702e27ac47f4 # v4.3.3
with:
main-branch-name: 'master'
- name: Start CI Run
run: npx nx-cloud@next start-ci-run --distribute-on="./.nx/workflows/dynamic-changesets.yaml" --stop-agents-after="e2e"
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y ca-certificates lsof libvips-dev libglib2.0-dev libgirepository1.0-dev
- name: Install Chrome
uses: browser-actions/setup-chrome@2dbff04819ebbfd5c974947148805a825b8a07fd # v2.1.0
- uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
name: Install pnpm
with:
version: 10.11.1
run_install: false
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
node-version: 20
cache: 'pnpm'
- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@ac90e63697ac2784f4ecfe2964e1a285c304003a # v1
with:
rustflags: ''
- name: Setup Java
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
with:
distribution: temurin
java-version: 17
- name: Setup Gradle
uses: gradle/actions/setup-gradle@48b5f213c81028ace310571dc5ec0fbbca0b2947 # v4.4.3
- name: Install project dependencies
run: |
pnpm install --frozen-lockfile
pnpm playwright install --with-deps
- name: Check Documentation
run: pnpm nx documentation
timeout-minutes: 20
- name: Run Checks/Lint/Test/Build
run: |
pids=()
pnpm nx-cloud record -- nx format:check &
pids+=($!)
pnpm nx-cloud record -- nx sync:check
pids+=($!)
pnpm nx-cloud record -- nx-cloud conformance:check
pids+=($!)
pnpm nx run-many -t check-imports check-commit check-lock-files check-codeowners --parallel=1 --no-dte &
pids+=($!)
pnpm nx affected --targets=lint,test,build,e2e,e2e-ci,format-native,lint-native &
pids+=($!)
for pid in "${pids[@]}"; do
wait "$pid"
done
timeout-minutes: 100
- name: Fix CI
run: pnpm nx-cloud fix-ci
if: failure()
main-macos:
runs-on: macos-latest
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}${{ contains(github.event_name, 'push') && format('-{0}', github.sha) || '' }}
cancel-in-progress: true
env:
NX_E2E_CI_CACHE_KEY: e2e-github-macos
NX_PERF_LOGGING: 'false'
NX_CI_EXECUTION_ENV: 'macos'
SELECTED_PM: 'npm'
steps:
- name: Log concurrency info
run: |
echo "Concurrency group: ${{ github.workflow }}-${{ github.ref }}${{ contains(github.event_name, 'push') && format('-{0}', github.sha) || '' }}"
echo "Concurrency cancel-in-progress: ${{ !contains(github.event_name, 'push') }}"
echo "Concurrency cancel-event-name: ${{ github.event_name }}"
if: always()
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 0
filter: tree:0
- name: Fetch Master
run: git fetch origin master:master
if: ${{ github.event_name == 'pull_request' }}
- name: Restore Homebrew packages
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: |
/opt/homebrew
~/Library/Caches/Homebrew
key: nrwl-nx-homebrew-packages
- name: Configure Detox Environment, Install applesimutils
run: |
# Ensure Xcode command line tools are installed and configured
xcode-select --print-path || sudo xcode-select --reset
sudo xcode-select -s /Applications/Xcode.app
# Install or update applesimutils with error handling
if ! brew list applesimutils &>/dev/null; then
echo "Installing applesimutils..."
HOMEBREW_NO_AUTO_UPDATE=1 brew tap wix/brew >/dev/null
HOMEBREW_NO_AUTO_UPDATE=1 brew install applesimutils >/dev/null || {
echo "Failed to install applesimutils, retrying with update..."
brew update
HOMEBREW_NO_AUTO_UPDATE=1 brew install applesimutils
}
else
echo "Updating applesimutils..."
HOMEBREW_NO_AUTO_UPDATE=1 brew upgrade applesimutils || true
fi
# Verify applesimutils installation
applesimutils --version || (echo "applesimutils installation failed" && exit 1)
# Configure environment for M-series Mac
echo "DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer" >> $GITHUB_ENV
echo "PLATFORM_NAME=iOS Simulator" >> $GITHUB_ENV
# Set additional environment variables for better debugging
echo "DETOX_DISABLE_TELEMETRY=1" >> $GITHUB_ENV
echo "DETOX_LOG_LEVEL=trace" >> $GITHUB_ENV
# Verify Xcode installation
xcodebuild -version
# List available simulators
xcrun simctl list devices available
timeout-minutes: 10
continue-on-error: false
- name: Reset iOS Simulators
id: reset-simulators
run: |
echo "Resetting iOS Simulators..."
# Kill simulator processes
sudo killall -9 com.apple.CoreSimulator.CoreSimulatorService 2>/dev/null || true
killall "Simulator" 2>/dev/null || true
killall "iOS Simulator" 2>/dev/null || true
# Wait for processes to terminate
sleep 3
# Shutdown and erase all simulators (ignore failures)
xcrun simctl shutdown all 2>/dev/null || true
sleep 5
xcrun simctl erase all 2>/dev/null || true
# If erase failed, try the nuclear option
if xcrun simctl list devices | grep -q "Booted" 2>/dev/null; then
echo "Standard reset failed, using nuclear option..."
rm -rf ~/Library/Developer/CoreSimulator/Devices/* 2>/dev/null || true
launchctl remove com.apple.CoreSimulator.CoreSimulatorService 2>/dev/null || true
sleep 3
fi
# Clean up additional directories
rm -rf ~/Library/Developer/CoreSimulator/Caches/* 2>/dev/null || true
rm -rf ~/Library/Logs/CoreSimulator/* 2>/dev/null || true
rm -rf ~/Library/Developer/Xcode/DerivedData/* 2>/dev/null || true
echo "Simulator reset completed"
timeout-minutes: 5
continue-on-error: true
- name: Verify Simulator Reset
if: ${{ steps.reset-simulators.outcome == 'success' }}
run: |
# Verify CoreSimulator service restarted
pgrep -fl "CoreSimulator" || (echo "CoreSimulator service not running" && exit 1)
# Check simulator list is clean
xcrun simctl list devices
# Verify simulator runtime paths exist and are writable
test -d ~/Library/Developer/CoreSimulator/Devices || (echo "Simulator devices directory missing" && exit 1)
touch ~/Library/Developer/CoreSimulator/Devices/test || (echo "Simulator devices directory not writable" && exit 1)
rm ~/Library/Developer/CoreSimulator/Devices/test
timeout-minutes: 5
- name: Diagnose Simulator Reset Failure
if: ${{ steps.reset-simulators.outcome == 'failure' }}
run: |
echo "Simulator reset failed. Collecting diagnostic information..."
xcrun simctl list
echo "Checking simulator logs..."
ls -la ~/Library/Logs/CoreSimulator/ || echo "No simulator logs found"
- name: Save Homebrew Cache
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: |
/opt/homebrew
~/Library/Caches/Homebrew
key: nrwl-nx-homebrew-packages
- uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
name: Install pnpm
with:
version: 10.11.1
run_install: false
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
node-version: 20
cache: 'pnpm'
- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@ac90e63697ac2784f4ecfe2964e1a285c304003a # v1
with:
rustflags: ''
- name: Install project dependencies
run: |
pnpm install --frozen-lockfile
pnpm playwright install --with-deps
- name: Set SHAs
uses: nrwl/nx-set-shas@1859e66a83ac9be0dceecbd9a023702e27ac47f4 # v4.3.3
with:
main-branch-name: 'master'
- name: Run E2E Tests for macOS
run: |
HAS_CHANGED=$(node ./scripts/check-react-native-changes.js $NX_BASE $NX_HEAD);
if $HAS_CHANGED; then
pnpm nx affected -t e2e-macos-local --parallel=1 --base=$NX_BASE --head=$NX_HEAD
else
echo "Skip E2E tests for macOS as there are no changes in React Native projects."
fi
-104
View File
@@ -1,104 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ "master" ]
schedule:
- cron: '20 14 * * 6'
jobs:
analyze:
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
packages: read
# only required for workflows in private repositories
actions: read
contents: read
strategy:
fail-fast: false
matrix:
include:
- language: actions
build-mode: none
# We would like to test our Java / Kotlin... but its currently failing. We can follow up.
# - language: java-kotlin
# build-mode: autobuild
- language: javascript-typescript
build-mode: none
- language: rust
build-mode: none
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
# Add any setup steps before running the `github/codeql-action/init` action.
# This includes steps like installing compilers or runtimes (`actions/setup-node`
# or others). This is typically only required for manual builds.
# - name: Setup runtime (example)
# uses: actions/setup-example@v1
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@15403aac29bd91419968e066cded66bde56b0283 # v3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@15403aac29bd91419968e066cded66bde56b0283 # v3
with:
category: "/language:${{matrix.language}}"
-101
View File
@@ -1,101 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
pull_request:
branches: [ "**" ]
jobs:
analyze:
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
# required to fetch internal or private CodeQL packs
packages: read
# only required for workflows in private repositories
actions: read
contents: read
strategy:
fail-fast: false
matrix:
include:
- language: actions
build-mode: none
# See comment in @./codeql-master.yml about Java / Kotlin
# - language: java-kotlin
# build-mode: autobuild
- language: javascript-typescript
build-mode: none
- language: rust
build-mode: none
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
# Add any setup steps before running the `github/codeql-action/init` action.
# This includes steps like installing compilers or runtimes (`actions/setup-node`
# or others). This is typically only required for manual builds.
# - name: Setup runtime (example)
# uses: actions/setup-example@v1
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@15403aac29bd91419968e066cded66bde56b0283 # v3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@15403aac29bd91419968e066cded66bde56b0283 # v3
with:
category: "/language:${{matrix.language}}"
upload: 'never'
upload-database: false
-21
View File
@@ -1,21 +0,0 @@
name: Unmergeable Labels Check
on:
pull_request:
types: [synchronize, opened, reopened, labeled, unlabeled]
jobs:
do-not-merge:
if: ${{ github.repository_owner == 'nrwl' }}
name: Prevent Merging
runs-on: ubuntu-latest
steps:
- name: Check for label
run: |
echo "${{ toJSON(github.event.*.labels.*.name) }}"
node -e 'const forbidden = ["target: next major version", "pr status: needs tests", "pr status: in-progress", "blocked: needs rebase", "pr status: do not merge"];
const match = ${{ toJSON(github.event.*.labels.*.name) }}.find(l => forbidden.includes(l.toLowerCase()));
if (match) {
console.log("Cannot merge PRs that are labeled with " + match);
process.exit(1)
}'
-517
View File
@@ -1,517 +0,0 @@
name: E2E matrix
on:
schedule:
- cron: "0 5 * * *"
workflow_dispatch:
inputs:
debug_enabled:
type: boolean
description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
required: false
default: false
env:
CYPRESS_CACHE_FOLDER: ${{ github.workspace }}/.cypress
permissions: { }
jobs:
preinstall:
if: ${{ github.repository_owner == 'nrwl' }}
runs-on: ${{ matrix.os }}
timeout-minutes: 20
strategy:
matrix:
os:
- ubuntu-latest
- macos-latest
# - windows-latest Windows fails to build gradle wrapper which always runs when we build nx.
## https://staging.nx.app/runs/LgD4vxGn8w?utm_source=pull-request&utm_medium=comment
node_version:
- 20
- 22
# - 23
exclude:
# run just node v20 on macos and windows
- os: macos-latest
node_version: 22
# - os: macos-latest
# node_version: 23
# - os: windows-latest TODO (emily): Windows fails to build gradle wrapper which always runs when we build nx. Re-enable when we fix this.
# node_version: 22
# - os: windows-latest TODO (emily): Windows fails to build gradle wrapper which always runs when we build nx. Re-enable when we fix this.
# node_version: 23
name: Cache install (${{ matrix.os }}, node v${{ matrix.node_version }})
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 0
filter: tree:0
- uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
name: Install pnpm
with:
version: 10.11.1
run_install: false
- name: Set node
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
node-version: ${{ matrix.node_version }}
cache: 'pnpm'
- name: Get pnpm store directory
id: pnpm-cache
run: echo "path=$(pnpm store path)" >> $GITHUB_OUTPUT
- name: Cache pnpm store
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: ${{ steps.pnpm-cache.outputs.path }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Ensure Python setuptools Installed on Macos
if: ${{ matrix.os == 'macos-latest' }}
id: brew-install-python-setuptools
run: brew install python-setuptools
- name: Install packages
run: |
pnpm install --frozen-lockfile
pnpm playwright install --with-deps
- name: Homebrew cache directory path
if: ${{ matrix.os == 'macos-latest' }}
id: homebrew-cache-dir-path
run: echo "dir=$(brew --cache)" >> $GITHUB_OUTPUT
- name: Cache Homebrew
if: ${{ matrix.os == 'macos-latest' }}
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
lookup-only: true
path: ${{ steps.homebrew-cache-dir-path.outputs.dir }}
key: brew-${{ matrix.node_version }}
restore-keys: |
brew-
- name: Cache Cypress
id: cache-cypress
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
lookup-only: true
path: '${{ github.workspace }}/.cypress'
key: ${{ runner.os }}-cypress
- name: Install Cypress
if: steps.cache-cypress.outputs.cache-hit != 'true'
run: npx cypress install
prepare-matrix:
name: Prepare matrix combinations
if: ${{ github.repository_owner == 'nrwl' }}
timeout-minutes: 5
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.process-json.outputs.MATRIX }}
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 0
filter: tree:0
- name: Process matrix data
id: process-json
run:
echo "MATRIX=$(npx tsx .github/workflows/nightly/process-matrix.ts | jq -c .)" >> $GITHUB_OUTPUT
e2e:
if: ${{ github.repository_owner == 'nrwl' }}
needs:
- preinstall
- prepare-matrix
permissions:
contents: read
runs-on: ${{ matrix.os }}
timeout-minutes: 200 # <- cap each job to 200 minutes
strategy:
matrix: ${{fromJson(needs.prepare-matrix.outputs.matrix)}} # Load matrix from previous job
fail-fast: false
name: ${{ matrix.os_name }}/${{ matrix.package_manager }}/${{ matrix.node_version }} ${{ join(matrix.project) }}
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 0
filter: tree:0
- name: Prepare dir for output
run: mkdir -p outputs
- uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
name: Install pnpm
with:
version: 10.11.1
run_install: false
- name: Use Node.js ${{ matrix.node_version }}
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
node-version: ${{ matrix.node_version }}
cache: 'pnpm'
- name: Install Rust
if: ${{ matrix.os != 'windows-latest' }}
run: |
curl --proto '=https' --tlsv1.3 https://sh.rustup.rs -sSf | sh -s -- -y
source "$HOME/.cargo/env"
rustup toolchain install 1.70.0
- name: Load Cargo Env
if: ${{ matrix.os != 'windows-latest' }}
run: echo "PATH=$HOME/.cargo/bin:$PATH" >> $GITHUB_ENV
- name: Install bun
if: ${{ matrix.os != 'windows-latest' }}
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
with:
bun-version: latest
- name: Install packages
run: |
pnpm install --frozen-lockfile
pnpm playwright install --with-deps
- name: Cleanup
if: ${{ matrix.os == 'ubuntu-latest' }}
run: |
# Workaround to provide additional free space for testing.
# https://github.com/actions/virtual-environments/issues/2840
sudo rm -rf /usr/share/dotnet
sudo rm -rf /opt/ghc
sudo rm -rf "/usr/local/share/boost"
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
sudo apt-get install lsof
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
- name: Homebrew cache directory path
if: ${{ matrix.os == 'macos-latest' }}
id: homebrew-cache-dir-path
run: echo "dir=$(brew --cache)" >> $GITHUB_OUTPUT
- name: Cache Homebrew
if: ${{ matrix.os == 'macos-latest' }}
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: ${{ steps.homebrew-cache-dir-path.outputs.dir }}
key: brew-${{ matrix.node_version }}
restore-keys: |
brew-
- name: Cache Cypress
id: cache-cypress
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: '${{ github.workspace }}/.cypress'
key: ${{ runner.os }}-cypress
- name: Install Cypress
if: steps.cache-cypress.outputs.cache-hit != 'true'
run: npx cypress install
- name: Configure Detox Environment, Install applesimutils
if: ${{ matrix.os == 'macos-latest' }}
run: |
# Ensure Xcode command line tools are installed and configured
xcode-select --print-path || sudo xcode-select --reset
sudo xcode-select -s /Applications/Xcode.app
# Install or update applesimutils with error handling
if ! brew list applesimutils &>/dev/null; then
echo "Installing applesimutils..."
HOMEBREW_NO_AUTO_UPDATE=1 brew tap wix/brew >/dev/null
HOMEBREW_NO_AUTO_UPDATE=1 brew install applesimutils >/dev/null || {
echo "Failed to install applesimutils, retrying with update..."
brew update
HOMEBREW_NO_AUTO_UPDATE=1 brew install applesimutils
}
else
echo "Updating applesimutils..."
HOMEBREW_NO_AUTO_UPDATE=1 brew upgrade applesimutils || true
fi
# Verify applesimutils installation
applesimutils --version || (echo "applesimutils installation failed" && exit 1)
# Configure environment for M-series Mac
echo "DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer" >> $GITHUB_ENV
echo "PLATFORM_NAME=iOS Simulator" >> $GITHUB_ENV
# Set additional environment variables for better debugging
echo "DETOX_DISABLE_TELEMETRY=1" >> $GITHUB_ENV
echo "DETOX_LOG_LEVEL=trace" >> $GITHUB_ENV
# Verify Xcode installation
xcodebuild -version
timeout-minutes: 10
continue-on-error: false
- name: Reset iOS Simulators
if: ${{ matrix.os == 'macos-latest' }}
id: reset-simulators
run: |
echo "Resetting iOS Simulators..."
# Kill simulator processes
sudo killall -9 com.apple.CoreSimulator.CoreSimulatorService 2>/dev/null || true
killall "Simulator" 2>/dev/null || true
killall "iOS Simulator" 2>/dev/null || true
# Wait for processes to terminate
sleep 3
# Shutdown and erase all simulators (ignore failures)
xcrun simctl shutdown all 2>/dev/null || true
sleep 5
xcrun simctl erase all 2>/dev/null || true
# If erase failed, try the nuclear option
if xcrun simctl list devices | grep -q "Booted" 2>/dev/null; then
echo "Standard reset failed, using nuclear option..."
rm -rf ~/Library/Developer/CoreSimulator/Devices/* 2>/dev/null || true
launchctl remove com.apple.CoreSimulator.CoreSimulatorService 2>/dev/null || true
sleep 3
fi
# Clean up additional directories
rm -rf ~/Library/Developer/CoreSimulator/Caches/* 2>/dev/null || true
rm -rf ~/Library/Logs/CoreSimulator/* 2>/dev/null || true
rm -rf ~/Library/Developer/Xcode/DerivedData/* 2>/dev/null || true
echo "Simulator reset completed"
timeout-minutes: 5
continue-on-error: true
- name: Verify Simulator Reset
if: ${{ matrix.os == 'macos-latest' && steps.reset-simulators.outcome == 'success' }}
run: |
# Verify CoreSimulator service restarted
pgrep -fl "CoreSimulator" || (echo "CoreSimulator service not running" && exit 1)
# Verify simulator runtime paths exist and are writable
test -d ~/Library/Developer/CoreSimulator/Devices || (echo "Simulator devices directory missing" && exit 1)
touch ~/Library/Developer/CoreSimulator/Devices/test || (echo "Simulator devices directory not writable" && exit 1)
rm ~/Library/Developer/CoreSimulator/Devices/test
timeout-minutes: 5
- name: Diagnose Simulator Reset Failure
if: ${{ matrix.os == 'macos-latest' && steps.reset-simulators.outcome == 'failure' }}
run: |
echo "Simulator reset failed. Collecting diagnostic information..."
xcrun simctl list
echo "Checking simulator logs..."
ls -la ~/Library/Logs/CoreSimulator/ || echo "No simulator logs found"
- name: Configure git metadata (needed for lerna smoke tests)
if: ${{ (matrix.os != 'macos-latest') || (matrix.os == 'macos-latest' && steps.reset-simulators.outcome == 'success') }}
run: |
git config --global user.email test@test.com
git config --global user.name "Test Test"
- name: Set starting timestamp
if: ${{ (matrix.os != 'macos-latest') || (matrix.os == 'macos-latest' && steps.reset-simulators.outcome == 'success') }}
id: before-e2e
shell: bash
run: |
echo "timestamp=$(date +%s)" >> $GITHUB_OUTPUT
- name: Run e2e tests with pnpm (Linux/Windows)
id: e2e-run-pnpm
if: ${{ matrix.os != 'macos-latest' }}
run: pnpm nx run ${{ matrix.project }}:e2e-local
shell: bash
timeout-minutes: ${{ matrix.os_timeout }}
env:
NX_E2E_CI_CACHE_KEY: e2e-gha-${{ matrix.os }}-${{ matrix.node_version }}-${{ matrix.package_manager }}
NX_DAEMON: 'true'
NX_PERF_LOGGING: 'false'
NX_E2E_VERBOSE_LOGGING: 'true'
NX_NATIVE_LOGGING: 'false'
NX_E2E_RUN_E2E: 'true'
NX_CLOUD_NO_TIMEOUTS: 'true'
NX_E2E_SKIP_CLEANUP: 'true'
NODE_OPTIONS: --max_old_space_size=8192
SELECTED_PM: ${{ matrix.package_manager }}
npm_config_registry: http://localhost:4872
YARN_REGISTRY: http://localhost:4872
CI: true
- name: Run e2e tests with npm (macOS)
id: e2e-run-npm
if: ${{ matrix.os == 'macos-latest' && steps.reset-simulators.outcome == 'success' }}
run: |
# Run the tests
if [[ "${{ matrix.project }}" == "e2e-detox" ]] || [[ "${{ matrix.project }}" == "e2e-react-native" ]] || [[ "${{ matrix.project }}" == "e2e-expo" ]]; then
NX_E2E_VERBOSE_DEBUG=1 pnpm nx run ${{ matrix.project }}:e2e-macos-local
else
NX_E2E_VERBOSE_DEBUG=1 pnpm nx run ${{ matrix.project }}:e2e-local
fi
env:
NX_E2E_CI_CACHE_KEY: e2e-gha-${{ matrix.os }}-${{ matrix.node_version }}-${{ matrix.package_manager }}
NX_PERF_LOGGING: 'false'
NX_CI_EXECUTION_ENV: 'macos'
NX_E2E_VERBOSE_LOGGING: 'true'
NX_NATIVE_LOGGING: 'false'
NX_E2E_RUN_E2E: 'true'
NX_E2E_SKIP_CLEANUP: 'true'
NODE_OPTIONS: --max_old_space_size=8192
SELECTED_PM: 'npm'
npm_config_registry: http://localhost:4872
YARN_REGISTRY: http://localhost:4872
DEVELOPER_DIR: '/Applications/Xcode.app/Contents/Developer'
CI: true
- name: Save matrix config in file
if: ${{ always() }}
id: save-matrix
shell: bash
run: |
before=${{ steps.before-e2e.outputs.timestamp }}
now=$(date +%s)
delta=$(($now - $before))
# Determine the outcome based on which step ran
outcome="${{ matrix.os == 'macos-latest' && steps.e2e-run-npm.outcome || steps.e2e-run-pnpm.outcome }}"
matrix=$((
echo '${{ toJSON(matrix) }}'
) | jq --argjson delta $delta -c '. + { "status": "'"$outcome"'", "duration": $delta }')
echo "$matrix" > 'outputs/matrix.json'
- name: Upload matrix config
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: ${{ always() }}
with:
name: ${{ matrix.os_name}}-${{ matrix.node_version}}-${{ matrix.package_manager}}-${{ matrix.project }}
overwrite: true
if-no-files-found: 'ignore'
path: 'outputs/matrix.json'
- name: Setup tmate session
if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled && failure() }}
uses: mxschmitt/action-tmate@1fb8b1023602bf1fd0e2994d7f1e93015cb5bbec # v3.22
timeout-minutes: 15
with:
sudo: ${{ matrix.os != 'windows-latest' }} # disable sudo for windows debugging
process-result:
if: ${{ always() && github.repository_owner == 'nrwl' && github.event_name != 'workflow_dispatch' }}
runs-on: ubuntu-latest
needs: e2e
timeout-minutes: 10
outputs:
message: ${{ steps.process-json.outputs.slack_message }}
proj_duration: ${{ steps.process-json.outputs.slack_proj_duration }}
pm_duration: ${{ steps.process-json.outputs.slack_pm_duration }}
codeowners: ${{ steps.process-json.outputs.codeowners }}
has_golden_failures: ${{ steps.process-json.outputs.has_golden_failures }}
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 0
filter: tree:0
- name: Prepare dir for output
run: mkdir -p outputs
- name: Load outputs
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
path: outputs
- name: Join and stringify matrix configs
id: combine-json
run: |
combined=$(jq -sc . outputs/*/matrix.json)
echo "combined=$combined" >> $GITHUB_OUTPUT
- name: Process results with TypeScript script
id: process-json
run: |
echo '${{ steps.combine-json.outputs.combined }}' | npx tsx .github/workflows/nightly/process-result.ts
report-failure:
if: ${{ always() && needs.process-result.outputs.has_golden_failures == 'true' && github.repository_owner == 'nrwl' && github.event_name != 'workflow_dispatch' }}
needs: process-result
runs-on: ubuntu-latest
name: Report failure
timeout-minutes: 10
steps:
- name: Send notification
uses: ravsamhq/notify-slack-action@be814b201e233b2dc673608aa46e5447c8ab13f2 # v11
with:
status: 'failure'
message_format: '${{ needs.process-result.outputs.message }}'
notification_title: 'Golden Test Failure'
footer: '<{run_url}|View Run> / Last commit <{commit_url}|{commit_sha}>'
mention_groups: ${{ needs.process-result.outputs.codeowners }}
env:
SLACK_WEBHOOK_URL: ${{ secrets.ACTION_MONITORING_SLACK }}
report-success:
if: ${{ always() && needs.process-result.outputs.has_golden_failures == 'false' && github.repository_owner == 'nrwl' && github.event_name != 'workflow_dispatch' }}
needs: process-result
runs-on: ubuntu-latest
name: Report status
timeout-minutes: 10
steps:
- name: Send notification
uses: ravsamhq/notify-slack-action@be814b201e233b2dc673608aa46e5447c8ab13f2 # v11
with:
status: 'success'
message_format: '${{ needs.process-result.outputs.message }}'
notification_title: '✅ Golden Tests: All Passed!'
footer: '<{run_url}|View Run> / Last commit <{commit_url}|{commit_sha}>'
env:
SLACK_WEBHOOK_URL: ${{ secrets.ACTION_MONITORING_SLACK }}
report-pm-time:
if: ${{ always() && github.repository_owner == 'nrwl' && github.event_name != 'workflow_dispatch' }}
needs: process-result
runs-on: ubuntu-latest
timeout-minutes: 10
name: Report duration per package manager
steps:
- name: Send notification
uses: ravsamhq/notify-slack-action@be814b201e233b2dc673608aa46e5447c8ab13f2 # v11
with:
status: 'skipped'
message_format: '${{ needs.process-result.outputs.pm_duration }}'
notification_title: '⌛ Total duration per package manager (ubuntu only)'
env:
SLACK_WEBHOOK_URL: ${{ secrets.ACTION_MONITORING_SLACK }}
report-proj-time:
if: ${{ always() && github.repository_owner == 'nrwl' && github.event_name != 'workflow_dispatch' }}
needs: process-result
runs-on: ubuntu-latest
timeout-minutes: 10
name: Report duration per project
steps:
- name: Send notification
uses: ravsamhq/notify-slack-action@be814b201e233b2dc673608aa46e5447c8ab13f2 # v11
with:
status: 'skipped'
message_format: '${{ needs.process-result.outputs.proj_duration }}'
notification_title: '⌛ E2E Project duration stats'
env:
SLACK_WEBHOOK_URL: ${{ secrets.ACTION_MONITORING_SLACK }}
-53
View File
@@ -1,53 +0,0 @@
name: Generate embeddings
on:
schedule:
- cron: "0 5 * * 0,4" # sunday, thursday 5AM
workflow_dispatch:
jobs:
cache-and-install:
if: github.repository == 'nrwl/nx'
runs-on: ubuntu-latest
strategy:
matrix:
node-version: ['20.19.0']
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Install Node.js
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
node-version: '20.19.0'
- name: Install pnpm
uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
id: pnpm-install
with:
version: 10.11.1
run_install: false
- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- name: Setup pnpm cache
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install --no-frozen-lockfile
- name: Run embeddings script
run: pnpm exec nx run tools-documentation-create-embeddings:run-node
env:
NX_NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NX_NEXT_PUBLIC_SUPABASE_URL }}
NX_SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.NX_SUPABASE_SERVICE_ROLE_KEY }}
NX_OPENAI_KEY: ${{ secrets.NX_OPENAI_KEY }}
-70
View File
@@ -1,70 +0,0 @@
name: Issue Statistics
on:
schedule:
- cron: "0 0 * * 0"
workflow_dispatch:
permissions:
issues: read
pull-requests: read
jobs:
issues-report:
if: ${{ github.repository_owner == 'nrwl' }}
runs-on: ubuntu-latest
name: Report status
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
with:
version: 10.11.1
- name: Use Node.js ${{ matrix.node_version }}
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
node-version: '20.19.0'
cache: 'pnpm'
- name: Cache node_modules
id: cache-modules
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
lookup-only: true
path: '**/node_modules'
key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
- name: Install packages
run: pnpm install --frozen-lockfile
- name: Download artifact
id: download-artifact
uses: dawidd6/action-download-artifact@268677152d06ba59fcec7a7f0b5d961b6ccd7e1e # v2 # Needed since we are downloading artifact from a different workflow run, official actions/download-artifact doesn't support this.
with:
name: cached-issue-data
path: ${{ github.workspace }}/scripts/issues-scraper/cached
search_artifacts: true
allow_forks: false
continue-on-error: true
- name: Collect Issue Data
id: collect
run: npx tsx ./scripts/issues-scraper/index.ts
env:
GITHUB_TOKEN: ${{ github.token }}
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: cached-issue-data
path: ./scripts/issues-scraper/cached/data.json
- name: Send GitHub Action trigger data to Slack workflow
id: slack
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1
with:
payload: ${{ steps.collect.outputs.SLACK_MESSAGE }}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_ISSUES_REPORT_URL }}
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
-30
View File
@@ -1,30 +0,0 @@
name: "Lock Threads"
on:
schedule:
- cron: "0 0 * * *" # Once a day, at midnight UTC
workflow_dispatch:
permissions:
issues: write
pull-requests: write
concurrency:
group: lock
jobs:
action:
if: ${{ github.repository_owner == 'nrwl' }}
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@7de207be1d3ce97a9abe6ff1306222982d1ca9f9 # v5.0.1
id: lockthreads
with:
github-token: ${{ github.token }}
issue-inactive-days: "30" # Lock issues after 30 days of being closed
pr-inactive-days: "5" # Lock closed PRs after 5 days. This ensures that issues that stem from a PR are opened as issues, rather than comments on the recently merged PR.
add-issue-labels: "outdated"
issue-comment: >
This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.
pr-comment: >
This pull request has already been merged/closed. If you experience issues related to these changes, please open a new issue referencing this pull request.
-131
View File
@@ -1,131 +0,0 @@
type MatrixDataProject = {
name: string,
codeowners: string,
is_golden?: boolean, // true if this is a golden project, false otherwise
};
type MatrixDataOS = {
os: string, // GH runner machine name: e.g. ubuntu-latest
os_name: string, // short name that will be printed in the report and on the action
os_timeout: number, // 60
package_managers: string[], // package managers to run on this OS
node_versions: Array<number | string>, // node versions to run on this OS
excluded?: string[], // projects to exclude from running on this OS
};
type MatrixData = {
coreProjects: MatrixDataProject[],
projects: MatrixDataProject[],
nodeTLS: number,
setup: MatrixDataOS[],
}
export type MatrixItem = {
project: string,
codeowners: string,
node_version: number | string,
package_manager: string,
os: string,
os_name: string,
os_timeout: number,
is_golden?: boolean,
};
// TODO: Extract Slack groups into named groups for easier maintenance
const matrixData: MatrixData = {
coreProjects: [
{ name: 'e2e-lerna-smoke-tests', codeowners: 'S04TNCVEETS', is_golden: true },
{ name: 'e2e-js', codeowners: 'S04SJ6HHP0X', is_golden: true },
{ name: 'e2e-nx-init', codeowners: 'S04SYHYKGNP', is_golden: true },
{ name: 'e2e-nx', codeowners: 'S04SYHYKGNP' },
{ name: 'e2e-release', codeowners: 'S04SYHYKGNP' },
{ name: 'e2e-workspace-create', codeowners: 'S04SYHYKGNP' }
],
projects: [
{ name: 'e2e-cypress', codeowners: 'S04T16BTJJY', is_golden: true },
{ name: 'e2e-docker', codeowners: 'S04SJ6HHP0X', is_golden: true },
{ name: 'e2e-detox', codeowners: 'S04TNCNJG5N', is_golden: true },
{ name: 'e2e-esbuild', codeowners: 'S04SJ6HHP0X', is_golden: true },
{ name: 'e2e-gradle', codeowners: 'S04TNCNJG5N', is_golden: true },
{ name: 'e2e-eslint', codeowners: 'S04SYJGKSCT', is_golden: true },
{ name: 'e2e-node', codeowners: 'S04SJ6HHP0X', is_golden: true },
{ name: 'e2e-playwright', codeowners: 'S04SVQ8H0G5', is_golden: true },
{ name: 'e2e-remix', codeowners: 'S04SVQ8H0G5', is_golden: true },
{ name: 'e2e-rspack', codeowners: 'S04SJ6HHP0X', is_golden: true },
{ name: 'e2e-vite', codeowners: 'S04SJ6PL98X', is_golden: true },
{ name: 'e2e-vue', codeowners: 'S04SJ6PL98X', is_golden: true },
{ name: 'e2e-web', codeowners: 'S04SJ6PL98X', is_golden: true },
{ name: 'e2e-webpack', codeowners: 'S04SJ6PL98X', is_golden: true },
{ name: 'e2e-jest', codeowners: 'S04T16BTJJY', is_golden: true },
{ name: 'e2e-expo', codeowners: 'S04TNCNJG5N', is_golden: true },
{ name: 'e2e-react-native', codeowners: 'S04TNCNJG5N', is_golden: true },
{ name: 'e2e-angular', codeowners: 'S04SS457V38' },
{ name: 'e2e-next', codeowners: 'S04TNCNJG5N' },
{ name: 'e2e-plugin', codeowners: 'S04SYHYKGNP' },
{ name: 'e2e-react', codeowners: 'S04TNCNJG5N' },
{ name: 'e2e-rollup', codeowners: 'S04SJ6PL98X' },
{ name: 'e2e-storybook', codeowners: 'S04SVQ8H0G5' },
{ name: 'e2e-nuxt', codeowners: 'S04SJ6PL98X' }
],
nodeTLS: 20,
setup: [
{
os: 'ubuntu-latest',
os_name: 'Linux',
os_timeout: 60,
package_managers: ['npm', 'pnpm', 'yarn'],
node_versions: ['20.19.0', '22.12.0'],
excluded: ['e2e-detox', 'e2e-react-native', 'e2e-expo']
},
{ os: 'macos-latest', os_name: 'MacOS', os_timeout: 90, package_managers: ['npm'], node_versions: ['20.19.0'] }
// TODO (emily): Fix Windows support as gradle fails when running nx build https://staging.nx.app/runs/LgD4vxGn8w?utm_source=pull-request&utm_medium=comment
// { os: 'windows-latest', os_name: 'WinOS', os_timeout: 180, package_managers: ['npm'], node_versions: ['20.19.0'], excluded: ['e2e-detox', 'e2e-react-native', 'e2e-expo'] }
]
};
const matrix: Array<MatrixItem> = [];
function addMatrixCombo(project: MatrixDataProject, nodeVersion: number | string, pm: number, os: number) {
matrix.push({
project: project.name,
codeowners: project.codeowners,
node_version: nodeVersion,
package_manager: matrixData.setup[os].package_managers[pm],
os: matrixData.setup[os].os,
os_name: matrixData.setup[os].os_name,
os_timeout: matrixData.setup[os].os_timeout,
is_golden: !!project.is_golden // Mark golden projects as true, others as false
});
}
function processProject(project: MatrixDataProject, nodeVersion?: number) {
for (let os = 0; os < matrixData.setup.length; os++) {
for (let pm = 0; pm < matrixData.setup[os].package_managers.length; pm++) {
if (!matrixData.setup[os].excluded || !matrixData.setup[os].excluded?.includes(project.name)) {
if (nodeVersion) {
addMatrixCombo(project, nodeVersion, pm, os);
} else {
for (let n = 0; n < matrixData.setup[os].node_versions.length; n++) {
addMatrixCombo(project, matrixData.setup[os].node_versions[n], pm, os);
}
}
}
}
}
}
// process core projects
for (let p = 0; p < matrixData.coreProjects.length; p++) {
processProject(matrixData.coreProjects[p]);
}
// process other projects
for (let p = 0; p < matrixData.projects.length; p++) {
processProject(matrixData.projects[p], matrixData.nodeTLS);
}
if (matrix.length > 256) {
throw new Error('You have exceeded the size of the matrix. GitHub allows only 256 jobs in a matrix. Found ${matrix.length} jobs.');
}
// print result to stdout for pipeline to consume
process.stdout.write(JSON.stringify({ include: matrix }, null, 0));
-197
View File
@@ -1,197 +0,0 @@
import * as fs from 'fs';
import { MatrixItem } from './process-matrix';
interface MatrixResult extends MatrixItem {
status: 'success' | 'failure' | 'cancelled';
duration: number;
}
interface ProcessedResults {
codeowners: string;
slack_message: string;
slack_proj_duration: string;
slack_pm_duration: string;
has_golden_failures: string;
}
function trimSpace(res: string): string {
return res.split('\n').map((l) => l.trim()).join('\n');
}
function humanizeDuration(num: number): string {
let res = '';
const hours = Math.floor(num / 3600);
if (hours) res += `${hours}h `;
const mins = Math.floor((num % 3600) / 60);
if (mins) res += `${mins}m `;
const sec = num % 60;
if (sec) res += `${sec}s`;
return res;
}
function processResults(combined: MatrixResult[]): ProcessedResults {
const failedProjects = combined.filter(c => c.status === 'failure' || c.status === 'cancelled').sort((a, b) => a.project.localeCompare(b.project));
const failedGoldenProjects = failedProjects.filter(c => c.is_golden);
const hasGoldenFailures = failedGoldenProjects.length > 0;
const codeowners = new Set<string>();
failedGoldenProjects.forEach(c => codeowners.add(c.codeowners));
let result = '';
const allGoldenProjects = combined.filter(c => c.is_golden);
const uniqueGoldenProjects = new Set(allGoldenProjects.map(c => c.project));
const uniqueFailedGoldenProjects = new Set(failedGoldenProjects.map(c => c.project));
const goldenPassingCount = uniqueGoldenProjects.size - uniqueFailedGoldenProjects.size;
const goldenFailingCount = uniqueFailedGoldenProjects.size;
const allOtherProjects = combined.filter(c => !c.is_golden);
const uniqueOtherProjects = new Set(allOtherProjects.map(c => c.project));
const failedRegularProjects = failedProjects.filter(c => !c.is_golden);
const uniqueFailedOtherProjects = new Set(failedRegularProjects.map(c => c.project));
const otherPassingCount = uniqueOtherProjects.size - uniqueFailedOtherProjects.size;
const otherFailingCount = uniqueFailedOtherProjects.size;
result += `\n🌟 *Golden Projects*`;
result += `\n✅ Passing: ${goldenPassingCount}`;
result += `\n❌ Failing: ${goldenFailingCount}`;
if (failedGoldenProjects.length > 0) {
result += `\n\n🚨 *Failed Golden Projects*\n\`\`\``;
result += `\n| Failed project |`;
result += `\n|--------------------------------|`;
let lastProject: string | undefined;
failedGoldenProjects.forEach(matrix => {
const project = matrix.project !== lastProject ? matrix.project : '';
if (project) {
result += `\n| ${project.padEnd(30)} |`;
lastProject = matrix.project;
}
});
result += `\n\`\`\``;
}
result += `\n\n🔧 *Other Projects*`;
result += `\n✅ Passing: ${otherPassingCount}`;
result += `\n❌ Failing: ${otherFailingCount}`;
// Failed Other Projects Table (if any)
if (failedRegularProjects.length > 0) {
result += `\n\n⚠️ *Failed Other Projects*\n\`\`\``;
result += `\n| Failed project |`;
result += `\n|--------------------------------|`;
let lastProject: string | undefined;
failedRegularProjects.forEach(matrix => {
const project = matrix.project !== lastProject ? matrix.project : '';
if (project) {
result += `\n| ${project.padEnd(30)} |`;
lastProject = matrix.project;
}
});
result += `\n\`\`\``;
}
if (failedProjects.length === 0) {
result = '🎉 *No test failures detected!* All systems green! 🟢';
}
const timeReport: Record<string, { min: number; max: number; minEnv: string; maxEnv: string }> = {};
const pmReport = { npm: 0, yarn: 0, pnpm: 0 };
const macosProjects = ['e2e-detox', 'e2e-expo', 'e2e-react-native'];
combined.forEach(matrix => {
const nodeVersion = parseInt(matrix.node_version.toString());
if (matrix.os_name === 'Linux' && nodeVersion === 20 && matrix.package_manager in pmReport) {
pmReport[matrix.package_manager as keyof typeof pmReport] += matrix.duration;
}
if (matrix.os_name === 'Linux' || macosProjects.includes(matrix.project)) {
if (timeReport[matrix.project]) {
if (matrix.duration > timeReport[matrix.project].max) {
timeReport[matrix.project].max = matrix.duration;
timeReport[matrix.project].maxEnv = `${matrix.os_name}, ${matrix.package_manager}`;
}
if (matrix.duration < timeReport[matrix.project].min) {
timeReport[matrix.project].min = matrix.duration;
timeReport[matrix.project].minEnv = `${matrix.os_name}, ${matrix.package_manager}`;
}
} else {
timeReport[matrix.project] = {
min: matrix.duration,
max: matrix.duration,
minEnv: `${matrix.os_name}, ${matrix.package_manager}`,
maxEnv: `${matrix.os_name}, ${matrix.package_manager}`,
};
}
}
});
let resultPkg = `
\`\`\`
| Project | Time |
|--------------------------------|---------------------------|`;
function mapProjectTime(proj: string, section: 'min' | 'max'): string {
return `${humanizeDuration(timeReport[proj][section])} (${timeReport[proj][`${section}Env`]})`;
}
function durationIcon(proj: string, section: 'min' | 'max'): string {
const duration = timeReport[proj][section];
if (duration < 12 * 60) return `${section}`;
if (duration < 15 * 60) return `${section}`;
return `${section}`;
}
Object.keys(timeReport).forEach(proj => {
resultPkg += `\n| ${proj.padEnd(30)} | |`;
resultPkg += `\n| ${durationIcon(proj, 'min').padStart(29)} | ${mapProjectTime(proj, 'min').padEnd(25)} |`;
resultPkg += `\n| ${durationIcon(proj, 'max').padStart(29)} | ${mapProjectTime(proj, 'max').padEnd(25)} |`;
});
resultPkg += `\`\`\``;
let resultPm = `
\`\`\`
| PM | Total time |
|------|-------------|`;
Object.keys(pmReport).forEach(pm => {
resultPm += `\n| ${pm.padEnd(4)} | ${humanizeDuration(pmReport[pm as keyof typeof pmReport]).padEnd(11)} |`;
});
resultPm += `\`\`\``;
return {
codeowners: Array.from(codeowners).join(','),
slack_message: trimSpace(result),
slack_proj_duration: trimSpace(resultPkg),
slack_pm_duration: trimSpace(resultPm),
has_golden_failures: hasGoldenFailures.toString(),
};
}
function setOutput(key: string, value: string) {
const outputPath = process.env.GITHUB_OUTPUT;
if (!outputPath) {
console.warn(`GITHUB_OUTPUT not set. Skipping output for "${key}".`);
return;
}
if (value.includes('\n')) {
const delimiter = `EOF_${key}_${Date.now()}`;
fs.appendFileSync(outputPath, `${key}<<${delimiter}\n${value}\n${delimiter}\n`);
} else {
fs.appendFileSync(outputPath, `${key}=${value}\n`);
}
}
try {
const combinedInput = process.argv[2]
? process.argv[2]
: fs.readFileSync(0, 'utf-8').trim();
const combined: MatrixResult[] = JSON.parse(combinedInput);
const results = processResults(combined);
Object.entries(results).forEach(([key, value]) => {
setOutput(key, value);
});
} catch (error) {
console.error('Error processing results:', error);
process.exit(1);
}
-42
View File
@@ -1,42 +0,0 @@
name: NPM Audit
on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:
permissions: {}
jobs:
audit:
if: ${{ github.repository_owner == 'nrwl' }}
permissions:
contents: read # to fetch code (actions/checkout)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
with:
version: 10.11.1 # Aligned with root package.json (pnpm/action-setup will helpfully error if out of sync)
- name: Run a security audit
run: pnpm dlx audit-ci --critical --report-type summary
report:
if: ${{ always() && github.repository_owner == 'nrwl' && github.event_name != 'workflow_dispatch' }}
needs: audit
runs-on: ubuntu-latest
name: Report status
steps:
- name: Send notification
uses: ravsamhq/notify-slack-action@be814b201e233b2dc673608aa46e5447c8ab13f2 # v11
with:
status: ${{ needs.audit.result }}
message_format: '{emoji} Audit has {status_message}'
notification_title: '{workflow}'
footer: '<{run_url}|View Run> / Last commit <{commit_url}|{commit_sha}>'
mention_users: 'U01UELKLYF2,U9NPA6C90'
mention_users_when: 'failure,warnings'
env:
SLACK_WEBHOOK_URL: ${{ secrets.ACTION_MONITORING_SLACK }}
-30
View File
@@ -1,30 +0,0 @@
name: PR Title Validation
on:
pull_request:
types: [opened, edited, synchronize, reopened]
permissions: read-all
jobs:
validate-pr-title:
name: Validate PR Title
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
# Ensure's validate-pr-title.js is the copy from master
ref: master
- name: Setup Node.js
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
node-version: 20
package-manager-cache: false
- name: Validate PR title
env:
PR_TITLE: ${{ github.event.pull_request.title }}
PR_BODY: ${{ github.event.pull_request.body }}
run: node ./scripts/validate-pr-title.js
-480
View File
@@ -1,480 +0,0 @@
name: publish
on:
# Automated schedule - canary releases from master
schedule:
- cron: "0 20 * * 1-5" # Monday - Friday, at 20:00 UTC (8pm UTC)
release:
types: [ published ]
# Dynamically generate the display name for the GitHub UI based on the event type and inputs
run-name: ${{ github.event.inputs.pr && format('PR Release for {0}', github.event.inputs.pr) || github.event_name == 'schedule' && 'Canary Release' || github.event_name == 'workflow_dispatch' && !github.event.inputs.pr && 'Release Dry-Run' || github.ref_name }}
env:
DEBUG: napi:*
NX_RUN_GROUP: ${{ github.run_id }}-${{ github.run_attempt }}
CYPRESS_INSTALL_BINARY: 0
NODE_VERSION: 22.16.0
PNPM_VERSION: 10.11.1 # Aligned with root package.json (pnpm/action-setup will helpfully error if out of sync)
jobs:
# We first need to determine the version we are releasing, and if we need a custom repo or ref to use for the git checkout in subsequent steps.
# These values depend upon the event type that triggered the workflow:
#
# - schedule:
# - We are running a canary release which always comes from the master branch, we can use default ref resolution
# in actions/checkout. The exact version will be generated within scripts/nx-release.ts.
#
# - release:
# - We are running a full release which is based on the tag that triggered the release event, we can use default
# ref resolution in actions/checkout. The exact version will be generated within scripts/nx-release.ts.
resolve-required-data:
name: Resolve Required Data
if: ${{ github.repository_owner == 'nrwl' }}
runs-on: ubuntu-latest
outputs:
version: ${{ steps.script.outputs.version }}
dry_run_flag: ${{ steps.script.outputs.dry_run_flag }}
publish_branch: ${{ steps.script.outputs.publish_branch }}
steps:
# Default checkout on the triggering branch so that the latest publish-resolve-data.js script is available
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
with:
version: ${{ env.PNPM_VERSION }}
- name: Setup node
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
node-version: ${{ env.NODE_VERSION }}
registry-url: 'https://registry.npmjs.org'
check-latest: true
- name: Resolve and set checkout and version data to use for release
id: script
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env:
PR_NUMBER: ${{ github.event.inputs.pr }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const script = require('${{ github.workspace }}/scripts/publish-resolve-data.js');
await script({ github, context, core });
build:
needs: [ resolve-required-data ]
if: ${{ github.repository_owner == 'nrwl' }}
strategy:
fail-fast: false
matrix:
settings:
- host: macos-13
target: x86_64-apple-darwin
setup: |-
rustup target add aarch64-apple-darwin
build: |
pnpm nx run-many --target=build-native -- --target=x86_64-apple-darwin
- host: windows-latest
setup: |-
rustup target add aarch64-pc-windows-msvc
build: pnpm nx run-many --target=build-native -- --target=x86_64-pc-windows-msvc
target: x86_64-pc-windows-msvc
# Windows 32bit (not needed)
# - host: windows-latest
# build: |
# yarn nx -- run-many --target=build-native -- --target=i686-pc-windows-msvc
# target: i686-pc-windows-msvc
- host: ubuntu-latest
target: x86_64-unknown-linux-gnu
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian
build: |
set -e
apt-get update
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt-get install -y nodejs=22.16.0-1nodesource1
export PATH="/usr/local/bin:$PATH"
node --version
npm --version
npm i -g pnpm@${PNPM_VERSION} --force
pnpm --version
pnpm install --frozen-lockfile
rustup target add x86_64-unknown-linux-gnu
pnpm nx run-many --verbose --target=build-native -- --target=x86_64-unknown-linux-gnu
- host: ubuntu-latest
target: x86_64-unknown-linux-musl
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine
build: |
bash -c "
set -e
echo 'https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories
apk add --no-cache curl xz
curl -fsSL https://unofficial-builds.nodejs.org/download/release/v22.16.0/node-v22.16.0-linux-x64-musl.tar.xz -o node.tar.xz
tar -xJf node.tar.xz
mv node-v22.16.0-linux-x64-musl /usr/local/node
export PATH=\"/usr/local/node/bin:\$PATH\"
echo Node: \$(node -v)
echo NPM: \$(npm -v)
# Install PNPM
npm i -g pnpm@${PNPM_VERSION} --force
pnpm --version
# Install deps and run native build
pnpm install --frozen-lockfile
rustup target add x86_64-unknown-linux-musl
pnpm nx run-many --verbose --target=build-native -- --target=x86_64-unknown-linux-musl
"
- host: macos-13
target: aarch64-apple-darwin
setup: |-
rustup target add aarch64-apple-darwin
build: |
sudo rm -Rf /Library/Developer/CommandLineTools/SDKs/*;
export CC=$(xcrun -f clang);
export CXX=$(xcrun -f clang++);
SYSROOT=$(xcrun --sdk macosx --show-sdk-path);
export CFLAGS="-isysroot $SYSROOT -isystem $SYSROOT";
pnpm nx run-many --target=build-native -- --target=aarch64-apple-darwin
- host: ubuntu-latest
target: aarch64-unknown-linux-gnu
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian-aarch64
build: |
set -e
apt-get update
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt-get install -y nodejs=22.16.0-1nodesource1
export PATH="/usr/local/bin:$PATH"
node --version
npm --version
npm i -g pnpm@${PNPM_VERSION} --force
pnpm --version
pnpm install --frozen-lockfile
rustup target add aarch64-unknown-linux-gnu
pnpm nx run-many --verbose --target=build-native -- --target=aarch64-unknown-linux-gnu
- host: ubuntu-latest
target: armv7-unknown-linux-gnueabihf
setup: |
sudo apt-get update
sudo apt-get install gcc-arm-linux-gnueabihf -y
rustup target add armv7-unknown-linux-gnueabihf
build: |
CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER=/usr/bin/arm-linux-gnueabihf-gcc pnpm nx run-many --target=build-native -- --target=armv7-unknown-linux-gnueabihf
# Android (not needed)
# - host: ubuntu-latest
# target: aarch64-linux-android
# build: |
# pnpm nx run-many --target=build-native -- --target=aarch64-linux-android
# - host: ubuntu-latest
# target: armv7-linux-androideabi
# build: |
# pnpm nx run-many --target=build-native -- --target=armv7-linux-androideabi
- host: ubuntu-latest
target: aarch64-unknown-linux-musl
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine
build: |
bash -c "
set -e
echo 'https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories
apk add --no-cache curl xz
curl -fsSL https://unofficial-builds.nodejs.org/download/release/v22.16.0/node-v22.16.0-linux-x64-musl.tar.xz -o node.tar.xz
tar -xJf node.tar.xz
mv node-v22.16.0-linux-x64-musl /usr/local/node
export PATH=\"/usr/local/node/bin:\$PATH\"
echo Node: \$(node -v)
echo NPM: \$(npm -v)
# Install PNPM
npm i -g pnpm@${PNPM_VERSION} --force
pnpm --version
# Install deps and run native build
pnpm install --frozen-lockfile
rustup target add aarch64-unknown-linux-musl
pnpm nx run-many --verbose --target=build-native -- --target=aarch64-unknown-linux-musl
"
- host: windows-latest
target: aarch64-pc-windows-msvc
setup: |-
rustup target add aarch64-pc-windows-msvc
build: pnpm nx run-many --target=build-native -- --target=aarch64-pc-windows-msvc
name: stable - ${{ matrix.settings.target }} - node@22.16.0
runs-on: ${{ matrix.settings.host }}
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
with:
version: ${{ env.PNPM_VERSION }}
- name: Setup node
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
if: ${{ !matrix.settings.docker }}
with:
node-version: ${{ env.NODE_VERSION }}
check-latest: true
cache: 'pnpm'
- name: Install
uses: actions-rust-lang/setup-rust-toolchain@ac90e63697ac2784f4ecfe2964e1a285c304003a # v1
if: ${{ !matrix.settings.docker }}
with:
target: ${{ matrix.settings.target }}
rustflags: ''
- name: Cache cargo
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
.cargo-cache
target/
key: ${{ matrix.settings.target }}-cargo-registry
- uses: goto-bus-stop/setup-zig@abea47f85e598557f500fa1fd2ab7464fcb39406 # v2.2.1
if: ${{ matrix.settings.target == 'armv7-unknown-linux-gnueabihf' }}
with:
version: 0.10.0
- name: Setup toolchain
run: ${{ matrix.settings.setup }}
if: ${{ matrix.settings.setup }}
shell: bash
- name: Setup node x86
if: matrix.settings.target == 'i686-pc-windows-msvc'
run: yarn config set supportedArchitectures.cpu "ia32"
shell: bash
- name: Install dependencies
if: ${{ !matrix.settings.docker }}
run: pnpm install --frozen-lockfile
timeout-minutes: 30
- name: Setup node x86
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
if: matrix.settings.target == 'i686-pc-windows-msvc'
with:
node-version: ${{ env.NODE_VERSION }}
check-latest: true
cache: pnpm
architecture: x86
- name: Build in docker
uses: addnab/docker-run-action@4f65fabd2431ebc8d299f8e5a018d79a769ae185 # v3
if: ${{ matrix.settings.docker }}
with:
image: ${{ matrix.settings.docker }}
options: --user 0:0 -v ${{ github.workspace }}/.cargo-cache/git/db:/usr/local/cargo/git/db -v ${{ github.workspace }}/.cargo/registry/cache:/usr/local/cargo/registry/cache -v ${{ github.workspace }}/.cargo/registry/index:/usr/local/cargo/registry/index -v ${{ github.workspace }}:/build -w /build
run: ${{ matrix.settings.build }}
- name: Build
run: ${{ matrix.settings.build }}
if: ${{ !matrix.settings.docker }}
shell: bash
- name: Upload artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: bindings-${{ matrix.settings.target }}
path: |
packages/nx/src/native/*.node
packages/nx/src/native/*.wasm
if-no-files-found: error
build-freebsd:
needs: [ resolve-required-data ]
if: ${{ github.repository_owner == 'nrwl' }}
runs-on: ubuntu-latest
name: Build FreeBSD
timeout-minutes: 45
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Build
id: build
uses: cross-platform-actions/action@462ed697694d2ac9aa49e1225f395f7bb6dd49fe # v0.29.0
env:
DEBUG: napi:*
RUSTUP_IO_THREADS: 1
NX_PREFER_TS_NODE: true
PLAYWRIGHT_BROWSERS_PATH: 0
NODE_VERSION: 22.16.0
with:
operating_system: freebsd
version: '14.0'
architecture: x86-64
environment_variables: DEBUG RUSTUP_IO_THREADS CI NX_PREFER_TS_NODE PLAYWRIGHT_BROWSERS_PATH NODE_VERSION
shell: bash
run: |
env
whoami
sudo pkg install -y -f node libnghttp2 www/npm git
sudo npm install --location=global --ignore-scripts pnpm@10.11.1
curl https://sh.rustup.rs -sSf --output rustup.sh
sh rustup.sh -y --profile minimal --default-toolchain stable
source "$HOME/.cargo/env"
echo "~~~~ rustc --version ~~~~"
rustc --version
echo "~~~~ node -v ~~~~"
node -v
echo "~~~~ pnpm --version ~~~~"
pnpm --version
pwd
ls -lah
whoami
env
freebsd-version
echo "Installing dependencies"
pnpm install --frozen-lockfile --ignore-scripts
echo "Building FreeBSD bindings"
pnpm nx run-many --verbose --outputStyle stream --target=build-native -- --target=x86_64-unknown-freebsd
echo "Cleaning up"
pnpm nx reset
rm -rf node_modules
rm -rf dist
echo "KILL ALL NODE PROCESSES"
killall node || true
echo "COMPLETE"
- name: Upload artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: bindings-freebsd
path: |
packages/nx/src/native/*.node
if-no-files-found: error
publish:
if: ${{ github.repository_owner == 'nrwl' }}
name: Publish
runs-on: ubuntu-latest
environment: npm-registry
permissions:
id-token: write
contents: write
pull-requests: write
needs:
- resolve-required-data
- build-freebsd
- build
env:
GH_TOKEN: ${{ github.token }}
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
with:
version: ${{ env.PNPM_VERSION }}
- name: Setup node
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
node-version: ${{ env.NODE_VERSION }}
registry-url: 'https://registry.npmjs.org'
check-latest: true
cache: 'pnpm'
- name: Use npm 11.5.2
run: npm install -g npm@11.5.2
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Download all artifacts
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
path: artifacts
# This command will appropriately fail if no artifacts are available
- name: List artifacts
run: ls -R artifacts
shell: bash
- name: Build Wasm
run: |
wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-23/wasi-sdk-23.0-x86_64-linux.tar.gz
tar -xvf wasi-sdk-23.0-x86_64-linux.tar.gz
pnpm build:wasm
- name: Publish
env:
VERSION: ${{ needs.resolve-required-data.outputs.version }}
DRY_RUN: ${{ needs.resolve-required-data.outputs.dry_run_flag }}
PUBLISH_BRANCH: ${{ needs.resolve-required-data.outputs.publish_branch }}
NX_VERBOSE_LOGGING: true
run: |
echo ""
# Create and check out the publish branch
git checkout -b $PUBLISH_BRANCH
echo ""
echo "Version set to: $VERSION"
echo "DRY_RUN set to: $DRY_RUN"
echo ""
pnpm nx-release --local=false $VERSION $DRY_RUN
- name: (Stable Release Only) Trigger Docs Release
# Publish docs only on a full release
if: ${{ !github.event.release.prerelease && github.event_name == 'release' }}
run: npx ts-node -P ./scripts/tsconfig.scripts.json ./scripts/release-docs.ts
report-pending-publish:
name: Report Pending Publish to Slack
if: ${{ github.repository_owner == 'nrwl' }}
needs:
- resolve-required-data
- build-freebsd
- build
runs-on: ubuntu-latest
timeout-minutes: 10
continue-on-error: true # Don't fail the workflow if notification fails
steps:
- name: Send Slack notification
uses: ravsamhq/notify-slack-action@be814b201e233b2dc673608aa46e5447c8ab13f2 # v11
with:
status: ${{ job.status }}
notification_title: '📦 Publish Pending Review'
message_format: ${{ format('Version `{0}` is being published to NPM - manual review is required', needs.resolve-required-data.outputs.version) }}
footer: '<{run_url}|View Workflow Run>'
mention_groups: 'U9NPA6C90' # Jason
env:
SLACK_WEBHOOK_URL: ${{ secrets.ACTION_MONITORING_SLACK }}
pr_failure_comment:
# Run this job if it is a PR release, running on the nrwl origin, and any of the required jobs failed
if: ${{ github.repository_owner == 'nrwl' && github.event.inputs.pr && always() && contains(needs.*.result, 'failure') }}
needs: [ resolve-required-data, build, build-freebsd, publish ]
name: (PR Release Failure Only) Create comment for failed PR release
runs-on: ubuntu-latest
steps:
- name: Create comment for failed PR release
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
# This script is intentionally kept inline (and e.g. not generated in publish-resolve-data.js)
# to ensure that an error within the data generation itself is not missed.
script: |
const message = `
Failed to publish a PR release of this pull request, triggered by @${{ github.triggering_actor }}.
See the failed workflow run at: https://github.com/nrwl/nx/actions/runs/${{ github.run_id }}
`;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: ${{ github.event.inputs.pr }},
body: message
});
+106 -48
View File
@@ -1,111 +1,169 @@
on:
schedule:
- cron: "0 0 * * *"
- cron: "*/5 * * * *"
name: Stale Bot workflow
permissions: { }
jobs:
build:
if: ${{ github.repository_owner == 'nrwl' }}
permissions:
issues: write # to close stale issues (actions/stale)
pull-requests: write # to close stale PRs (actions/stale)
name: stale
runs-on: ubuntu-latest
steps:
# This handles issues that need more info
- name: stale-more-info-needed
id: stale-more-info-needed
uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # v10.0.0
uses: actions/stale@v3.0.13
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 7
days-before-close: 21
days-before-stale: 21
days-before-close: 14
stale-issue-label: "stale"
operations-per-run: 300
remove-stale-when-updated: true
only-labels: "blocked: more info needed"
stale-issue-message: |
This issue has been automatically marked as stale because more information has not been provided within 7 days.
It will be closed in 21 days if no information is provided.
If information has been provided, please reply to keep it active.
This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs.
If we missed this issue please reply to keep it active.
Thanks for being a part of the Nx community! 🙏
# This handles PRs that need to be rebased
- name: stale-needs-rebase
id: stale-needs-rebase
uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # v10.0.0
uses: actions/stale@v3.0.13
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 7
days-before-close: 21
days-before-stale: 21
days-before-close: 14
stale-issue-label: "stale"
operations-per-run: 300
remove-stale-when-updated: true
only-labels: "blocked: needs rebased"
stale-issue-message: |
This PR has been automatically marked as stale because it has not been rebased in 7 days.
It will be closed in 21 days if it is not rebased.
If the PR has been rebased or you are working on rebasing it, please reply to keep it active.
If you do not have time, please let us know and we can rebase it.
This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs.
If we missed this issue please reply to keep it active.
Thanks for being a part of the Nx community! 🙏
# This handles issues that do not have a repro
- name: stale-repro-needed
id: stale-repro-needed
uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # v10.0.0
uses: actions/stale@v3.0.13
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 7
days-before-close: 21
days-before-stale: 21
days-before-close: 14
stale-issue-label: "stale"
operations-per-run: 300
remove-stale-when-updated: true
only-labels: "blocked: repro needed"
stale-issue-message: |
This issue has been automatically marked as stale because no reproduction was provided within 7 days.
Please help us help you. Providing a repository exhibiting the issue helps us diagnose and fix the issue.
Any time that we spend reproducing this issue is time taken away from addressing this issue and other issues.
This issue will be closed in 21 days if a reproduction is not provided.
If a reproduction has been provided, please reply to keep it active.
This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs.
If we missed this issue please reply to keep it active.
Thanks for being a part of the Nx community! 🙏
- name: stale-retry-with-latest
id: stale-retry-with-latest
uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # v10.0.0
uses: actions/stale@v3.0.13
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 7
days-before-close: 21
days-before-stale: 21
days-before-close: 14
stale-issue-label: "stale"
operations-per-run: 300
remove-stale-when-updated: true
only-labels: "blocked: retry with latest"
stale-issue-message: |
This issue has been automatically marked as stale because no results of retrying on the latest version of Nx was provided within 7 days.
It will be closed in 21 days if no results are provided.
If the issue is still present, please reply to keep it active.
If the issue was not present, please close this issue.
This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs.
If we missed this issue please reply to keep it active.
Thanks for being a part of the Nx community! 🙏
# This handles issues are really old and were made with a previous major
- name: stale-bug
id: stale-bug
uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # v10.0.0
uses: actions/stale@v3.0.13
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 180
days-before-close: 21
days-before-close: 14
stale-issue-label: "stale"
operations-per-run: 300
remove-stale-when-updated: true
only-labels: "type: bug"
stale-issue-message: |
This issue has been automatically marked as stale because it hasn't had any activity for 6 months.
Many things may have changed within this time. The issue may have already been fixed or it may not be relevant anymore.
If at this point, this is still an issue, please respond with updated information.
It will be closed in 21 days if no further activity occurs.
This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs.
If we missed this issue please reply to keep it active.
Thanks for being a part of the Nx community! 🙏
- name: stale-cleanup
id: stale-cleanup
uses: actions/stale@v3.0.13
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 180
days-before-close: 14
stale-issue-label: "stale"
operations-per-run: 300
remove-stale-when-updated: true
only-labels: "type: cleanup"
stale-issue-message: |
This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs.
If we missed this issue please reply to keep it active.
Thanks for being a part of the Nx community! 🙏
- name: stale-docs
id: stale-docs
uses: actions/stale@v3.0.13
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 180
days-before-close: 14
stale-issue-label: "stale"
operations-per-run: 300
remove-stale-when-updated: true
only-labels: "type: docs"
stale-issue-message: |
This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs.
If we missed this issue please reply to keep it active.
Thanks for being a part of the Nx community! 🙏
- name: stale-enhancement
id: stale-enhancement
uses: actions/stale@v3.0.13
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 250
days-before-close: 14
stale-issue-label: "stale"
operations-per-run: 300
remove-stale-when-updated: true
only-labels: "type: enhancement"
stale-issue-message: |
This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs.
If we missed this issue please reply to keep it active.
Thanks for being a part of the Nx community! 🙏
- name: stale-feature
id: stale-feature
uses: actions/stale@v3.0.13
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 250
days-before-close: 14
stale-issue-label: "stale"
operations-per-run: 300
remove-stale-when-updated: true
only-labels: "type: feature"
stale-issue-message: |
This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs.
If we missed this issue please reply to keep it active.
Thanks for being a part of the Nx community! 🙏
- name: stale-question
id: stale-question
uses: actions/stale@v3.0.13
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 90
days-before-close: 14
stale-issue-label: "stale"
operations-per-run: 300
remove-stale-when-updated: true
only-labels: "type: question / discussion"
stale-issue-message: |
This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs.
If we missed this issue please reply to keep it active.
Thanks for being a part of the Nx community! 🙏
+3 -110
View File
@@ -1,121 +1,14 @@
node_modules
/.idea
/.fleet
.idea
/.vscode
dist
out-tsc
/build
/coverage
./test
test
.DS_Store
tmp
*.log
.ng_pkg_build
jest.debug.config.js
.tool-versions
/.nx-cache
/.nx/cache
/.nx/workspace-data
/.verdaccio/build/local-registry
/graph/client/src/assets/environment.js
/graph/client/src/assets/dev/environment.js
/graph/client/src/assets/generated-project-graphs
/graph/client/src/assets/generated-task-graphs
/graph/client/src/assets/generated-task-inputs
/graph/client/src/assets/generated-source-maps
/nx-dev/nx-dev/public/documentation
/nx-dev/nx-dev/public/tutorials
/nx-dev/nx-dev/public/images/open-graph
**/tests/temp-db
# Issues scraper creates these files, stored by github's cache
/scripts/issues-scraper/cached
# We don't commit a CHANELGELOG.md file to the repo, we only create Github releases
CHANGELOG.md
# Next.js
.next
out
# Angular Cache
.angular
# Astro Cache
.astro
# Local dev files
.env.local
.bashrc
*.node
# Fix for issue when working on the repo in a dev container
.pnpm-store
.cargo/.package-cache
.cargo/bin/
.cargo/env
.cargo/registry/
.local/
.npm/
.profile
.rustup/
target
*.wasm
/wasi-sdk*
vite.config.*.timestamp*
storybook-static
# Ignore Gradle project-specific cache directory
.gradle
.kotlin
.claude/settings.local.json
.cursor/rules/nx-rules.mdc
.cursor/mcp.json
.github/instructions/nx.instructions.md
# Added by Claude Task Master
# Logs
logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
dev-debug.log
# Dependency directories
node_modules/
# Environment variables
.env
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
.specstory/**
.cursorindexingignore
# OS specific
# Task files
/tasks.json
/tasks
# Upstream docs local configuration (machine-specific)
.upstreamdocs.local.json
astro-docs/.netlify
# Angular Rspack Specific Options
packages/angular-rspack/coverage
packages/angular-rspack-compiler/coverage
# Angular Rspack Packages use a template to generate the correct README
packages/angular-rspack/README.md
packages/angular-rspack-compiler/README.md
test-output
-1
View File
@@ -1 +0,0 @@
node ./scripts/commit-lint.js "$1"
-12
View File
@@ -1,12 +0,0 @@
# Skip if this is a worktree creation (previous ref is null)
if [ "$1" = "0000000000000000000000000000000000000000" ]; then
exit 0
fi
# Skip if this is a file checkout (not branch switch) - $3 would be 0
if [ "$3" = "0" ]; then
exit 0
fi
changedFiles="$(git diff-tree -r --name-only --no-commit-id $1 $2)"
node ./scripts/notify-lockfile-changes.js $changedFiles
-2
View File
@@ -1,2 +0,0 @@
changedFiles="$(git diff-tree -r --name-only --no-commit-id ORIG_HEAD HEAD)"
node ./scripts/notify-lockfile-changes.js $changedFiles
-1
View File
@@ -1 +0,0 @@
pnpm nx prepush --parallel 8 --tuiAutoExit 0
View File
-9
View File
@@ -1,9 +0,0 @@
{
"mcpServers": {
"nx": {
"command": "pnpm",
"args": ["nx-mcp"],
"env": {}
}
}
}
-163
View File
@@ -1,163 +0,0 @@
launch-templates:
linux-large:
resource-class: 'docker_linux_amd64/large'
image: 'us-east1-docker.pkg.dev/nxcloudoperations/nx-cloud/nx-agents-base-images:ubuntu22.04-node20.19-v1'
env:
GIT_AUTHOR_EMAIL: test@test.com
GIT_AUTHOR_NAME: Test
GIT_COMMITTER_EMAIL: test@test.com
GIT_COMMITTER_NAME: Test
SELECTED_PM: 'pnpm'
NX_NATIVE_LOGGING: 'nx::native::db'
init-steps:
- name: Checkout
uses: 'nrwl/nx-cloud-workflows/v5/workflow-steps/checkout/main.yaml'
- name: Check Node Version
script: node --version
- name: Cache restore
uses: 'nrwl/nx-cloud-workflows/v5/workflow-steps/cache/main.yaml'
inputs:
key: 'pnpm-lock.yaml'
paths: .pnpm-store
base-branch: 'master'
- name: Install zip and unzip
script: sudo apt-get -yqq install zip unzip
- name: Install bun
script: |
curl -fsSL https://bun.sh/install | bash
echo "BUN_INSTALL=$HOME/.bun" >> $NX_CLOUD_ENV
echo "PATH=$HOME/.bun/bin:$PATH" >> $NX_CLOUD_ENV
- name: Check bun
script: |
bun --version
- name: Install e2e deps
script: |
sudo apt-get update
sudo apt-get install -y ca-certificates lsof libvips-dev libglib2.0-dev libgirepository1.0-dev
- name: Pnpm Install from lockfile
script: |
pnpm install --frozen-lockfile
- name: Install Browsers
script: |
pnpm exec cypress install
pnpm exec playwright install --with-deps
- name: Install Rust
script: |
curl --proto '=https' --tlsv1.3 https://sh.rustup.rs -sSf | sh -s -- -y
source "$HOME/.cargo/env"
rustup toolchain install 1.70.0
- name: Configure git metadata (needed for lerna smoke tests)
script: |
git config --global user.email test@test.com
git config --global user.name "Test Test"
- name: Load Cargo Env
script: echo "PATH=$HOME/.cargo/bin:$PATH" >> $NX_CLOUD_ENV
- name: Install Rust Dependencies
script: |
cargo fetch
- name: Setup Java 21
script: |
sudo apt update
sudo apt install -y openjdk-21-jdk
sudo update-alternatives --set java /usr/lib/jvm/java-21-openjdk-amd64/bin/java
java -version
- name: Setup Gradle
script: |
./gradlew wrapper
./gradlew --version
linux-extra-large:
resource-class: 'docker_linux_amd64/extra_large'
image: 'us-east1-docker.pkg.dev/nxcloudoperations/nx-cloud/nx-agents-base-images:ubuntu22.04-node20.19-v1'
env:
GIT_AUTHOR_EMAIL: test@test.com
GIT_AUTHOR_NAME: Test
GIT_COMMITTER_EMAIL: test@test.com
GIT_COMMITTER_NAME: Test
SELECTED_PM: 'pnpm'
NX_NATIVE_LOGGING: 'nx::native::db'
init-steps:
- name: Checkout
uses: 'nrwl/nx-cloud-workflows/v5/workflow-steps/checkout/main.yaml'
- name: Check Node Version
script: node --version
- name: Cache restore
uses: 'nrwl/nx-cloud-workflows/v5/workflow-steps/cache/main.yaml'
inputs:
key: 'pnpm-lock.yaml'
paths: .pnpm-store
base-branch: 'master'
- name: Install zip and unzip
script: sudo apt-get -yqq install zip unzip
- name: Install bun
script: |
curl -fsSL https://bun.sh/install | bash
echo "BUN_INSTALL=$HOME/.bun" >> $NX_CLOUD_ENV
echo "PATH=$HOME/.bun/bin:$PATH" >> $NX_CLOUD_ENV
- name: Check bun
script: |
bun --version
- name: Install e2e deps
script: |
sudo apt-get update
sudo apt-get install -y ca-certificates lsof libvips-dev libglib2.0-dev libgirepository1.0-dev
- name: Pnpm Install from lockfile
script: |
pnpm install --frozen-lockfile
- name: Install Browsers
script: |
pnpm exec cypress install
pnpm exec playwright install --with-deps
- name: Install Rust
script: |
curl --proto '=https' --tlsv1.3 https://sh.rustup.rs -sSf | sh -s -- -y
source "$HOME/.cargo/env"
rustup toolchain install 1.70.0
- name: Configure git metadata (needed for lerna smoke tests)
script: |
git config --global user.email test@test.com
git config --global user.name "Test Test"
- name: Load Cargo Env
script: echo "PATH=$HOME/.cargo/bin:$PATH" >> $NX_CLOUD_ENV
- name: Install Rust Dependencies
script: |
cargo fetch
- name: Setup Java 21
script: |
sudo apt update
sudo apt install -y openjdk-21-jdk
sudo update-alternatives --set java /usr/lib/jvm/java-21-openjdk-amd64/bin/java
java -version
- name: Setup Gradle
script: |
./gradlew wrapper
./gradlew --version
-61
View File
@@ -1,61 +0,0 @@
distribute-on:
default: auto linux-large, 1 linux-extra-large
assignment-rules:
# e2e-release tests must run sequentially due to shared git state and publishing operations
- projects:
- e2e-release
targets:
- e2e-ci**
run-on:
- agent: linux-large
parallelism: 1
- projects:
- e2e-gradle
targets:
- e2e-ci**
run-on:
- agent: linux-large
parallelism: 1
- agent: linux-extra-large
parallelism: 1
# All other e2e tests can run in parallel
- targets:
- e2e-ci**
run-on:
- agent: linux-large
parallelism: 2
- agent: linux-extra-large
parallelism: 3
# These projects should not need to be isolated.
- projects:
- nx-dev
targets:
- build*
run-on:
- agent: linux-extra-large
parallelism: 1
- projects:
- angular
- react
targets:
- test
run-on:
- agent: linux-extra-large
parallelism: 1
- targets:
- lint
run-on:
- agent: linux-large
parallelism: 6
- targets:
- '*'
run-on:
- agent: linux-large
parallelism: 3
- agent: linux-extra-large
parallelism: 3
-5
View File
@@ -1,5 +0,0 @@
nx-dev/**/jest.config.js
.next
_files
_solution
nx-dev/tutorial/**/templates
-13
View File
@@ -1,13 +0,0 @@
# Enable pre/post-install which are disabled by default. Installing peer deps which is also disabled by default
auto-install-peers=true
enable-pre-post-scripts=true
# Enable lifecycle scripts for specific packages that require them (like post-install)
enable-scripts=@napi-rs/canvas,sharp,@swc/core,@swc/cli,@swc-node/register,esbuild
# Compatibility
strict-peer-dependencies=false
lockfile-version-strict=false
# Consistency across environments
use-node-version=20.19.0
+22 -56
View File
@@ -1,56 +1,22 @@
tmp
/test
/build
node_modules
/package.json
/pnpm-lock.yaml
packages/workspace/src/generators/**/files/**/*.json
packages/angular/src/schematics/**/files/**/*.json
packages/angular/src/migrations/**/files/**/*.json
packages/web/src/generators/**/files/**/*.json
packages/node/src/schematics/**/files/**/*.json
packages/express/src/schematics/**/files/**/*.json
packages/nest/src/schematics/**/files/**/*.json
packages/react/src/schematics/**/files/**/*.json
packages/jest/src/schematics/**/files/**/*.json
packages/gradle/project-graph/build/**/*.*
packages/nx/src/plugins/js/lock-file/__fixtures__/**/*.*
packages/**/schematics/**/files/**/*.html
packages/**/generators/**/files/**/*.html
packages/nx/src/native/**/*.rs
packages/nx/src/native/browser.js
packages/nx/src/native/nx.wasi-browser.js
packages/nx/src/native/nx.wasi.cjs
packages/nx/src/native/wasi-worker-browser.mjs
packages/nx/src/native/wasi-worker.mjs
packages/nx/src/native/native-bindings.js
packages/nx/src/native/index.d.ts
nx-dev/nx-dev/.next/
nx-dev/nx-dev/public/documentation
graph/client/src/assets/environment.js
graph/client/src/assets/dev/environment.js
graph/client/src/assets/generated-graphs
graph/client/src/assets/generated-project-graphs
graph/client/src/assets/generated-task-graphs
/.vscode
/.idea
/.fleet
/.github
/coverage
/.yarn
/.verdaccio/build/local-registry
/dist
/.env
CODEOWNERS
/.nx/cache
.pnpm-store
/.nx/workspace-data
/.nx/workflows/dynamic-changesets.yaml
_files
_solution
# this file uses TS import attributes which the current prettier version does not support
tools/documentation/create-embeddings/src/main.mts
tmp
/test
/build
node_modules
/package.json
packages/workspace/src/schematics/**/files/**/*.json
packages/workspace/src/core/dep-graph/vendor.js
packages/angular/src/schematics/**/files/**/*.json
packages/angular/src/migrations/**/files/**/*.json
packages/web/src/schematics/**/files/**/*.json
packages/node/src/schematics/**/files/**/*.json
packages/express/src/schematics/**/files/**/*.json
packages/nest/src/schematics/**/files/**/*.json
packages/react/src/schematics/**/files/**/*.json
packages/jest/src/schematics/**/files/**/*.json
/.vscode
/.idea
/.github
/coverage
/.yarn
/.verdaccio/build/local-registry
/dist
+1 -2
View File
@@ -1,5 +1,4 @@
{
"singleQuote": true,
"endOfLine": "lf",
"plugins": ["prettier-plugin-tailwindcss"]
"endOfLine": "lf"
}
-10
View File
@@ -1,10 +0,0 @@
{
"include": ["apps/**/*", "libs/**/*", "packages/**/*"],
"exclude": [
"**/*.spec.*",
"**/test/**/*",
"**/__tests__/**/*",
"**/*.test.*",
"node_modules/**/*"
]
}
+3 -14
View File
@@ -5,20 +5,14 @@ auth:
htpasswd:
file: ./htpasswd
max_body_size: 20mb
# a list of other known repositories we can talk to
uplinks:
npmjs:
url: https://registry.npmjs.org/
maxage: 60m
max_fails: 20
fail_timeout: 2m
cache: true
yarn:
url: https://registry.yarnpkg.com
maxage: 60m
max_fails: 20
fail_timeout: 2m
cache: true
packages:
'@*/*':
@@ -42,9 +36,4 @@ packages:
# log settings
logs:
type: stdout
format: pretty
level: warn
publish:
allow_offline: true # set offline to true to allow publish offline
- { type: stdout, format: pretty, level: http }
+199664
View File
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
yarnPath: .yarn/releases/yarn-1.19.0.js
-184
View File
@@ -1,184 +0,0 @@
When responding to queries about this repository:
1. Use the `nx_workspace` mcp tool for understanding the workspace architecture when appropriate
2. When working in projects, use the `nx_project` mcp tool to analyze and understand the specific project structure and
dependencies
3. Suggest relevant commands from the "Essential Commands" section when applicable
4. Highlight Nx's focus on monorepos and its key features like smart task execution, code generation, and project graph
analysis
5. Mention the plugin ecosystem and support for various frameworks when relevant
6. Emphasize the importance of running the full validation suite before committing changes
Always strive to provide accurate, helpful responses that align with the best practices and workflows described in this
file.
## GitHub Issue Response Mode
When responding to GitHub issues, determine your approach based on how the request is phrased:
### Plan-First Mode (Default)
Use this approach when users ask you to:
- "analyze", "investigate", "assess", "review", "examine", or "plan"
- Or when the request is ambiguous
In this mode:
1. Provide a detailed analysis of the issue
2. Create a comprehensive implementation plan
3. Break down the solution into clear steps
4. Then please post the plan as a comment on the issue
### Immediate Implementation Mode
Use this approach when users ask you to:
- "fix", "implement", "solve", "build", "create", "update", or "add"
- Or when they explicitly request immediate action
In this mode:
1. Analyze the issue quickly
2. Implement the complete solution immediately
3. Make all necessary code changes. Please make multiple commits so that the changes are easier to review.
4. Run appropriate tests and validation
5. If the tests, are not passing, please fix the issues and continue doing this up to 3 more times until the tests pass
6. Once the tests pass, push a branch and then suggest opening a PR which has a description of the changes made, and
that
it make sure that it explicitly says "Fixes #ISSUE_NUMBER" to automatically close the issue when the PR is merged.
## Avoid making changes to generated files
Files under `generated` directories are generated based on a different source file and should not be modified directly.
Find the underlying source and modify that instead.
## Essential Commands
### Code Formatting
After code changes are made, please make sure to format the files with prettier via `npx prettier -- FILE_NAME`
### Pre-push Validation
```bash
# Full validation suite - run before committing
nx prepush
```
If the prepush validation suite fails, please fix the issues before proceeding with your work. This ensures that all
code adheres to the project's standards and passes all tests. DO NOT make a new commit to fix these issues. Instead,
amend the current commit.
### Testing Changes
After code changes are made, first test the specific project where the changes were made:
```bash
nx run-many -t test,build,lint -p PROJECT_NAME
```
After verifying the individual project, validate that the changes in projects which have been affected:
```bash
# Test only affected projects (recommended for development)
nx affected -t build,test,lint
```
As the last step, run the e2e tests to fully ensure that changes are valid:
```bash
# Run affected e2e tests (recommended for development)
nx affected -t e2e-local
```
## Fixing GitHub Issues
When working on a GitHub issue, follow this systematic approach:
### 1. Get Issue Details
```bash
# Get issue details using GitHub CLI (replace ISSUE_NUMBER with actual number)
gh issue view ISSUE_NUMBER
# View multiple issues efficiently in one command
gh issue list --limit 50 --json number,title,state,labels,assignees,updatedAt,body --jq '.[] | select(.number == 123 or .number == 456 or .number == 789)'
# Or filter by specific criteria to get multiple related issues
gh issue list --label "bug" --state "open" --json number,title,body,labels --jq '.[]'
gh issue list --assignee "@me" --json number,title,body,state --jq '.[]'
```
**Tip**: Instead of running `gh issue view` multiple times, use `gh issue list` with JSON output and filtering to gather
information about multiple issues in a single command. This is much more efficient than viewing issues one at a time.
**Always provide clickable links**: When discussing GitHub issues or PRs, always include the full GitHub URL so the user
can easily open them in their browser. For example:
- Issue #12345: https://github.com/nrwl/nx/issues/12345
- PR #67890: https://github.com/nrwl/nx/pull/67890
When cloning reproduction repos, please clone within `./tmp/claude/repro-ISSUE_NUMBER`
### 2. Analyze the Plan
- Look for a plan or implementation details in the issue description
- Check comments for additional context or clarification
- Identify affected projects and components
### 3. Implement the Solution
- Follow the plan outlined in the issue
- Make focused changes that address the specific problem
- Ensure code follows existing patterns and conventions
### 4. Run Full Validation
Use the testing workflow from the "Essential Commands" section.
### 5. Submit Pull Request
- Create a descriptive PR title that references the issue
- **Always fill in the PR template** - don't leave it empty
- Include "Fixes #ISSUE_NUMBER" in the PR description
- Provide a clear summary of changes made
- Request appropriate reviewers
## Pull Request Template
**IMPORTANT**: When creating a pull request, you MUST fill in the template found in `.github/PULL_REQUEST_TEMPLATE.md`.
Do not leave the template sections empty. The template includes:
### Required Sections
1. **Current Behavior**: Describe the behavior we have today
2. **Expected Behavior**: Describe the behavior we should expect with the changes in this PR
3. **Related Issue(s)**: Link the issue being fixed so it gets closed when the PR is merged
### Template Format
```markdown
## Current Behavior
<!-- This is the behavior we have today -->
## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR -->
## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is merged. -->
Fixes #ISSUE_NUMBER
```
### Guidelines
- Ensure your commit message follows the conventional commit format (use `pnpm commit`)
- Use `fix:`, `feat:`, `chore:`, etc. as appropriate types.
- Scope is **required** for all commits. Possible scopes are listed in `scripts/commitizen.js`.
- Read the submission guidelines in CONTRIBUTING.md before posting
- For complex changes, you can request a dedicated Nx release by mentioning the Nx team
- Always link the related issue using "Fixes #ISSUE_NUMBER" to automatically close it when merged
-213
View File
@@ -1,213 +0,0 @@
# Any file not covered by a rule below, will default to Jason + Victor and a few select others.
* @FrozenPandaz @vsavkin
/packages/**/* @FrozenPandaz @vsavkin @AgentEnder @jaysoo @JamesHenry
/e2e/**/* @FrozenPandaz @vsavkin @AgentEnder @jaysoo @JamesHenry
/scripts/**/* @FrozenPandaz @vsavkin @AgentEnder @jaysoo @JamesHenry
/tools/**/* @FrozenPandaz @vsavkin @AgentEnder @jaysoo @JamesHenry
package.json @nrwl/nx-core-reviewers
pnpm-lock.yaml @nrwl/nx-core-reviewers
rust-toolchain.toml @nrwl/nx-native-reviewers
# Docs Site + Graph
/astro-docs @nrwl/nx-docs-reviewers
/docs @nrwl/nx-docs-reviewers
/docs/nx-cloud @StalkAltan @rarmatei @nixallover @nrwl/nx-docs-reviewers
/graph/** @philipjfulcher @FrozenPandaz @bcabanes @MaxKless @Coly010 @jaysoo @nartc
/images @nrwl/nx-docs-reviewers
/nx-dev/** @nrwl/nx-docs-reviewers
/typedoc-theme @nrwl/nx-docs-reviewers
# Plugin Verticals
## Angular
/docs/generated/packages/angular/** @nrwl/nx-angular-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/angular/** @nrwl/nx-angular-reviewers @nrwl/nx-docs-reviewers
/packages/angular/** @nrwl/nx-angular-reviewers
/packages/angular-rspack/** @nrwl/nx-angular-reviewers
/packages/angular-rspack-compiler/** @nrwl/nx-angular-reviewers
/examples/angular-rspack/** @nrwl/nx-angular-reviewers
/e2e/angular/** @nrwl/nx-angular-reviewers
/packages/angular/plugins/component-testing.ts @nrwl/nx-angular-reviewers @nrwl/nx-testing-tools-reviewers
/packages/angular/src/generators/cypress-component-configuration/** @nrwl/nx-angular-reviewers @nrwl/nx-testing-tools-reviewers
/packages/angular/src/generators/component-test/** @nrwl/nx-angular-reviewers @nrwl/nx-testing-tools-reviewers
## React
/docs/generated/packages/react/** @nrwl/nx-react-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/next/** @nrwl/nx-react-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/react/** @nrwl/nx-react-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/next/** @nrwl/nx-react-reviewers @nrwl/nx-docs-reviewers
/packages/react/** @nrwl/nx-react-reviewers
/e2e/react/** @nrwl/nx-react-reviewers
/packages/next/** @nrwl/nx-react-reviewers
/e2e/next/** @nrwl/nx-react-reviewers
/packages/react/plugins/component-testing/** @nrwl/nx-react-reviewers @nrwl/nx-testing-tools-reviewers
/packages/react/src/generators/cypress-component-configuration/** @nrwl/nx-react-reviewers @nrwl/nx-testing-tools-reviewers
/packages/react/src/generators/component-test/** @nrwl/nx-react-reviewers @nrwl/nx-testing-tools-reviewers
# React Native
/docs/generated/packages/detox/** @nrwl/nx-react-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/expo/** @nrwl/nx-react-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/react-native/** @nrwl/nx-react-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/react-native/** @nrwl/nx-react-reviewers @nrwl/nx-docs-reviewers
/packages/detox/** @nrwl/nx-react-reviewers
/e2e/detox/** @nrwl/nx-react-reviewers
/packages/expo/** @nrwl/nx-react-reviewers
/e2e/expo/** @nrwl/nx-react-reviewers
/packages/react-native/** @nrwl/nx-react-reviewers
/e2e/react-native/** @nrwl/nx-react-reviewers
## remix
/docs/generated/packages/remix/** @nrwl/nx-react-reviewers @nrwl/nx-docs-reviewers @Coly010
/packages/remix/** @nrwl/nx-react-reviewers @Coly010
/e2e/remix/** @nrwl/nx-react-reviewers @Coly010
# Vue
/packages/vue/** @nrwl/nx-vue-reviewers
/e2e/vue/** @nrwl/nx-vue-reviewers
/packages/nuxt/** @nrwl/nx-vue-reviewers
/e2e/nuxt/** @nrwl/nx-vue-reviewers
## Node
/docs/generated/packages/node/** @nrwl/nx-node-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/nest/** @nrwl/nx-node-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/express/** @nrwl/nx-node-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/node/** @nrwl/nx-node-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/express/** @nrwl/nx-node-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/nest/** @nrwl/nx-node-reviewers @FrozenPandaz @nrwl/nx-docs-reviewers
/packages/node/** @nrwl/nx-node-reviewers
/packages/express/** @nrwl/nx-node-reviewers
/packages/nest/** @nrwl/nx-node-reviewers
/e2e/node/** @nrwl/nx-node-reviewers
## JS
/docs/generated/packages/js/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/web/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/webpack/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/rspack/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/esbuild/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/rollup/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/vite/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/js/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/web/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/webpack/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/rspack/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/esbuild/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/vite/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/packages/js/** @nrwl/nx-js-reviewers
/e2e/js/** @nrwl/nx-js-reviewers
/packages/web/** @nrwl/nx-js-reviewers
/e2e/web/** @nrwl/nx-js-reviewers
/packages/webpack/** @nrwl/nx-js-reviewers
/e2e/webpack/** @nrwl/nx-js-reviewers
/packages/rspack/** @nrwl/nx-js-reviewers
/e2e/rspack/** @nrwl/nx-js-reviewers
/packages/rsbuild/** @nrwl/nx-js-reviewers
/packages/esbuild/** @nrwl/nx-js-reviewers
/e2e/esbuild/** @nrwl/nx-js-reviewers
/packages/rollup/** @nrwl/nx-js-reviewers
/e2e/rollup/** @nrwl/nx-js-reviewers
/packages/vite/** @nrwl/nx-js-reviewers
/e2e/vite/** @nrwl/nx-js-reviewers
## Module Federation
/packages/module-federation/** @nrwl/nx-js-reviewers
## Tools
/docs/generated/packages/cypress/** @nrwl/nx-testing-tools-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/cypress/** @nrwl/nx-testing-tools-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/jest/** @nrwl/nx-testing-tools-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/jest/** @nrwl/nx-testing-tools-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/playwright/** @nrwl/nx-testing-tools-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/playwright/** @nrwl/nx-testing-tools-reviewers @nrwl/nx-docs-reviewers
/packages/cypress/** @nrwl/nx-testing-tools-reviewers
/e2e/cypress/** @nrwl/nx-testing-tools-reviewers
/packages/jest/** @nrwl/nx-testing-tools-reviewers
/e2e/jest/** @nrwl/nx-testing-tools-reviewers
/packages/playwright/** @nrwl/nx-testing-tools-reviewers
/e2e/playwright/** @nrwl/nx-testing-tools-reviewers
# Linter
/docs/generated/packages/eslint-plugin/** @nrwl/nx-linter-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/eslint/** @nrwl/nx-linter-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/eslint/** @nrwl/nx-linter-reviewers @nrwl/nx-docs-reviewers
/packages/eslint-plugin/** @nrwl/nx-linter-reviewers
/packages/eslint/** @nrwl/nx-linter-reviewers
/e2e/eslint/** @nrwl/nx-linter-reviewers
.eslint* @nrwl/nx-linter-reviewers
# Storybook
/docs/generated/packages/storybook/** @nrwl/nx-storybook-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/storybook/** @nrwl/nx-storybook-reviewers @nrwl/nx-docs-reviewers
/packages/storybook/** @nrwl/nx-storybook-reviewers
/e2e/storybook/** @nrwl/nx-storybook-reviewers
# Docker
/packages/docker/** @nrwl/nx-core-reviewers @Coly010
## Devkit
/docs/generated/devkit/** @nrwl/nx-devkit-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/devkit/** @nrwl/nx-devkit-reviewers @nrwl/nx-docs-reviewers
/packages/devkit/** @nrwl/nx-devkit-reviewers
/packages/devkit/index.ts @FrozenPandaz @vsavkin
/packages/devkit/public-api.ts @FrozenPandaz @vsavkin
# Gradle
/packages/gradle/** @FrozenPandaz @MaxKless @lourw
/e2e/gradle/** @FrozenPandaz @MaxKless @lourw
# Nx-Plugin
/docs/generated/packages/plugin/** @nrwl/nx-devkit-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/plugin/** @nrwl/nx-devkit-reviewers @nrwl/nx-docs-reviewers
/packages/plugin/** @nrwl/nx-devkit-reviewers
/e2e/plugin/** @nrwl/nx-devkit-reviewers
## Core
/docs/generated/cli/** @nrwl/nx-core-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/nx/** @nrwl/nx-core-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/workspace/** @nrwl/nx-core-reviewers @nrwl/nx-docs-reviewers
/packages/nx/** @nrwl/nx-core-reviewers
/packages/nx/src/adapter @nrwl/nx-core-reviewers @leosvelperez
/packages/nx/src/native @nrwl/nx-core-reviewers @nrwl/nx-native-reviewers
/packages/nx/src/plugins/js/lock-file @nrwl/nx-core-reviewers @meeroslav
/packages/nx/src/command-line/init/implementation/angular/** @nrwl/nx-angular-reviewers @nrwl/nx-core-reviewers
/e2e/nx-init/src/nx-init-angular.test.ts @nrwl/nx-angular-reviewers
/packages/nx/src/command-line/init/implementation/react/** @nrwl/nx-react-reviewers
/e2e/nx-init/src/nx-init-react.test.ts @nrwl/nx-react-reviewers
/e2e/nx-init/src/files/cra/** @nrwl/nx-react-reviewers
/e2e/nx*/** @nrwl/nx-core-reviewers
/packages/workspace/** @nrwl/nx-core-reviewers
/e2e/workspace-create/** @nrwl/nx-core-reviewers
/e2e/release/** @nrwl/nx-core-reviewers
# Misc
/e2e/lerna-smoke-tests/** @vsavkin @JamesHenry
/e2e/utils/** @meeroslav @nrwl/nx-testing-tools-reviewers @vsavkin
/community @nrwl/nx-docs-reviewers
/CONTRIBUTING.md @FrozenPandaz
/CODE_OF_CONDUCT.md @FrozenPandaz
/CODEOWNERS @FrozenPandaz @AgentEnder
/packages/nx/src/nx-cloud/utilities/url-shorten.ts @MaxKless
# Scripts
/scripts/documentation @nrwl/nx-docs-reviewers
/scripts/angular-support-upgrades @nrwl/nx-angular-reviewers
# CI
/.nx/workflows/** @nrwl/nx-pipelines-reviewers
/.github/** @nrwl/nx-pipelines-reviewers
/.husky/** @nrwl/nx-pipelines-reviewers
/packages/workspace/src/generators/ci-workflow/** @nrwl/nx-pipelines-reviewers
# Claude AI Integration
CLAUDE.md @FrozenPandaz
.claude/** @FrozenPandaz
.mcp.json @FrozenPandaz
# Global Files
project.json @FrozenPandaz @vsavkin
jest.config.ts @nrwl/nx-testing-tools-reviewers @FrozenPandaz
jest.preset.js @nrwl/nx-testing-tools-reviewers @FrozenPandaz
# Overrides - These are applied last, so override any matches above.
docs/generated/manifests/* @nrwl/nrwlians
docs/generated/packages-metadata.json @FrozenPandaz @jaysoo @AgentEnder @nrwl/nx-docs-reviewers
-11
View File
@@ -1,11 +0,0 @@
# Contributor Code of Conduct
As contributors and maintainers of the Nx project, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities.
Communication through any of Nx's channels (GitHub, Gitter, Discord, IRC, mailing lists, Twitter, etc.) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
We promise to extend courtesy and respect to everyone involved in this project regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to the Nx project to do the same.
If any member of the community violates this code of conduct, the maintainers of the Nx project may take action, removing issues, comments, and PRs or blocking accounts as deemed appropriate.
If you are subject to or witness unacceptable behavior, or have any other concerns, please email us at conduct@nrwl.io.
+61 -306
View File
@@ -6,93 +6,40 @@ We would love for you to contribute to Nx! Read this document to see how to do i
Watch this 5-minute video:
<a href="https://www.youtube.com/watch?v=8LCA_4qxc08" target="_blank" rel="noreferrer">
<p style="text-align: center;"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/how-to-contribute.png" width="600" alt="Nx - How to contribute"></p>
<a href="https://www.youtube.com/watch?v=o11p0zSm0No&feature=youtu.be" target="_blank">
<p align="center"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/how-to-contribute.png" width="600"></p>
</a>
## Got a Question?
We are trying to keep GitHub issues for bug reports and feature requests. Using the `nrwl` tag
on [Stack Overflow](https://stackoverflow.com/questions/tagged/nrwl) is a much better place to ask general questions
about how to use Nx.
We are trying to keep GitHub issues for bug reports and feature requests. Using the `nrwl` tag on [Stack Overflow](https://stackoverflow.com/questions/tagged/nrwl) is a much better place to ask general questions about how to use Nx.
## Found an Issue?
If you find a bug in the source code or a mistake in the documentation, you can help us
by [submitting an issue](https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#submit-issue)
to [our GitHub Repository](https://github.com/nrwl/nx). Even better, you
can [submit a Pull Request](https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#submit-pr) with a fix.
If you find a bug in the source code or a mistake in the documentation, you can help us by [submitting an issue](https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#submit-issue) to [our GitHub Repository](https://github.com/nrwl/nx). Even better, you can [submit a Pull Request](https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#submit-pr) with a fix.
## Project Structure
Source code and documentation are included in the top-level folders listed below.
- `packages` - Source code for Nx packages such as Angular, React, Web, NestJS, Next and others including generators and
executors (or builders).
- `e2e` - E2E tests for the Nx packages
- `graph` - Source code for the Nx Graph application which shows the project graph, task graph, project details, and more in the browser.
- `docs` - Markdown and configuration files for documentation including tutorials, guides for each supported platform,
and API docs.
- `nx-dev` - Source code for the Nx documentation site which displays the markdown in `docs` and more.
- `tools` - Workspace-specific tooling and plugins
- `docs` - Markdown and configuration files for documentation including tutorials, guides for each supported platform, and API docs.
- `e2e` - E2E tests.
- `packages` - Source code for Nx packages such as Angular, React, Web, NestJS, Next and others including schematics and builders.
- `scripts` - Miscellaneous scripts for project tasks such as building documentation, testing, and code formatting.
- `tmp` - Folder used by e2e tests. If you are a WebStorm user, make sure to mark this folder as excluded.
## Technologies
This repo contains a mix of different technologies, including:
- **Rust**: The core of Nx is written in Rust, which provides performance and safety.
- **TypeScript**: The primary language for Nx packages and the Nx DevKit.
- **Kotlin**: Used for the Gradle and Java plugins.
## Development Workstation Setup
If you are using `VSCode`, and provided you have [Docker](https://docker.com) installed on your machine, then you can leverage [Dev Containers](https://containers.dev) through this [VSCode extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers), to easily setup your development environment, with everything needed to contribute to Nx, already installed (namely `NodeJS`, `Yarn`, `Rust`, `Cargo`, plus some useful extensions like `Nx Console`).
To do so, simply:
- Checkout the repo
- Open it with VSCode
- Open the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) and select "Dev Containers: Open Folder in Container..."
The repo comes with a preconfigured `devcontainer.json` file (located in `.devcontainer/` folder at root), that `VSCode` will automatically use to install the aforementioned tools, inside a Docker image. It will even run `pnpm install` for you, so you can start contributing to Nx right after.
If you open the repo in [Github Codespace](https://github.com/features/codespaces), it will also leverage this config file, to setup the codespace, with the same required tools.
> 💡 **Troubleshooting**
>
> If you are having issues when running Nx commands like `build`, `test`... related to the version of `GLIBC`,
> it probably means the version that is installed on the devcontainer, **is outdated** compare to the minimum version required by Nx tools.
>
> You can check currently installed version by running the following command, in a terminal within the container:
>
> `ldd --version`
>
> Then, try updating the base image used in [devcontainer.json](.devcontainer/devcontainer.json) and rebuild it, to see if it solved the issue.
>
> Current base image is `"mcr.microsoft.com/devcontainers/typescript-node:20-bookworm"` which is based on `Debian-12 (bookworm)`,
> which comes with `GLIBC v2.36` pre-installed (Nx tools currenlty requires `GLIBC v2.33` or higher).
## Building the Project
> 💡 Nx uses `Rust` to build native bindings for Node. Please make sure that you have Rust installed via [rustup.rs](https://rustup.rs)
> If you have `VSCode` + `Docker`, this can be automated for you, see [section](#development-workstation-setup) above
After cloning the project to your machine, to install the dependencies, run:
```bash
pnpm install
// or prefer...
pnpm install --frozen-lockfile // if you haven't changed any dependency
yarn
```
To build all the packages, run:
```bash
pnpm build
yarn build
```
## Publishing to a local registry
@@ -102,55 +49,32 @@ it can be useful to publish to a local registry.
Check out [this video for a live walkthrough](https://youtu.be/Tx257WpNsxc) or follow the instructions below:
- Run `pnpm local-registry` in Terminal 1 (keep it running)
- Run `npm adduser --registry http://localhost:4873` in Terminal 2 (real credentials are not required, you just need to
be logged in. You can use test/test/test@test.io.)
- Run `pnpm nx-release 20.0.0 --local` in Terminal 2 - you can choose any nonexistent version number here, but it's recommended to use the next major
- Run `cd ./tmp` in Terminal 2
- Run `npx create-nx-workspace@20.0.0` in Terminal 2
```bash
# Starts the local registry. Keep this running in a separate terminal.
yarn local-registry start
If you have problems publishing, make sure you use Node 18 and NPM 8.
# Set npm and yarn to use the local registry.
# Note: This reroutes your installs to your local registry
yarn local-registry enable
**NOTE:** To use this newly published local version, you need to make a new workspace, run `nx migrate` or change all of your target packages to this new version, eg: `"nx": "^20.0.0",` and re-run `pnpm i` in your testing project.
# Revert npm and yarn to use their default registries
yarn local-registry disable
```
### Publishing for Yarn 2+ (Berry)
To publish packages to a local registry, do the following:
Yarn Berry operates slightly differently than Yarn Classic. In order to publish packages for Berry follow next steps:
- Run `yarn set version berry` to switch to latest Yarn version.
- Create `.yarnrc.yml` in root with following contents:
```yml
nodeLinker: node-modules
npmRegistryServer: 'http://localhost:4873'
unsafeHttpWhitelist:
- localhost
```
- Run `pnpm local-registry` in Terminal 1 (keep it running)
- If you are creating nx workspace outside of your nx repo, make sure to add npm registry info to your root yarnrc (
usually in ~/.yarnrc.yml). The file should look something like this:
```yml
npmRegistries:
'https://registry.yarnpkg.com':
npmAuthToken: npm_******************
yarnPath: .yarn/releases/yarn-3.2.2.cjs
npmRegistryServer: 'http://localhost:4873'
unsafeHttpWhitelist:
- localhost
```
- Run `pnpm nx-release minor --local` in Terminal 2 to publish next minor version. The output will report the version of published packages.
- Go to your target folder (e.g. `cd ./tmp`) in Terminal 2
- Run `yarn dlx create-nx-workspace@123.4.5` in Terminal 2 (replace `123.4.5` with the version that got published).
- Run `yarn local-registry start` in Terminal 1 (keep it running)
- Run `yarn local-registry enable` in Terminal 2
- Run `yarn nx-release 999.9.9 --local` in Terminal 2
- Run `cd /tmp` in Terminal 2
- Run `npx create-nx-workspace@999.9.9` in Terminal 2
### Running Unit Tests
To make sure your changes do not break any unit tests, run the following:
```bash
nx affected --target=test
yarn test
```
For example, if you need to only run the tests for the jest package, run:
@@ -161,157 +85,63 @@ nx test jest
### Running E2E Tests
**Use Node 18 and NPM 8. E2E tests won't work on Node 15 and NPM 7.**
To make sure your changes do not break any E2E tests, run:
```bash
nx e2e e2e-vite # or any other project here
yarn e2e
```
Running E2E tests can take some time, so it is often useful to run a single test. To run a single suite of tests, run:
```bash
nx e2e e2e-vite -t versions # I often add qqqq to my test name so I can use -t qqqq
yarn e2e e2e-cli
```
Sometimes tests pass locally but they fail on the CI. To reproduce the CI environment and be able to debug the issue, run:
```bash
NX_VERBOSE_LOGGING=true CI=true SELECTED_PM=pnpm pnpm nx e2e e2e-vite --t="should do something is this test"
```
The above command sets verbose logging (this exposes stack traces and underlying errors), sets the defaults to be CI-like and sets Pnpm as the selected package manager.
### Developing on Windows
To build Nx on Windows, you need to use WSL.
- Run `pnpm install` in WSL. Yarn will compile several dependencies. If you don't run `install` in WSL, they will be
compiled for Windows.
- Run `nx affected --target=test` and other commands in WSL.
## Documentation Contributions
We would love for you to contribute to our documentation as well! Please feel welcome to submit fixes or enhancements to
our existing documentation pages and the `nx-dev` application in this repo.
### Documentation Structure
#### Documentation Pages
Our documentation pages can be found within this repo under the `docs` directory.
The `docs/map.json` file is considered our source of truth for our site's structure, and should be updated when adding a
new page to our documentation to ensure that it is included in the documentation site. We also run automated scripts
based on this `map.json` data to safeguard against common human errors that could break our site.
When you make a change to the `map.json` file, make sure to run `pnpm documentation` to propagate your changes to the `nx-dev` application.
#### Nx-Dev Application
Our public `nx.dev` documentation site is a [Next.js](https://nextjs.org/) application, that can be found in
the `nx-dev` directory of this repo.
The documentation site is consuming the `docs/` directly by copy-ing its content while deploying, so the website is
always in sync and reflects the latest version of `docs/`.
Jump to [Running the Documentation Site Locally](#running-the-documentation-site-locally) to see how to preview your
changes while serving.
### Changing Generated API documentation
`.md` files documenting the API for our CLI (including executor and generator API docs) are generated via the
corresponding `schema.json` file for the given command.
After adjusting the `schema.json` file, `.md` files for these commands can be generated by running:
```bash
pnpm documentation
```
This will update the corresponding contents of the `docs` directory. These are generated automatically on push (via
husky) as well.
Note that adjusting the `schema.json` files will also affect the CLI manuals and Nx Console behavior, in addition to
adjusting the docs.
### Running the Documentation Site Locally
To run `nx-dev` locally, run the command:
```bash
npx nx serve-docs nx-dev
```
You can then access the application locally at `localhost:4200`. Changes to markdown documentation files will be automatically applied to the site when you refresh the browser.
#### Troubleshooting: `JavaScript heap out of memory`
If you see an error that states: `FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory`,
you need
to [increase the max memory size of V8's old memory section](https://nodejs.org/api/cli.html#--max-old-space-sizesize-in-megabytes):
```bash
export NODE_OPTIONS="--max-old-space-size=4096"
```
After configuring this, try to run `npx nx serve nx-dev` again.
### PR Preview
When submitting a PR, this repo will automatically generate a preview of the `nx-dev` application based on the contents
of your pull request.
Once the preview site is launched, a comment will automatically be added to your PR with the link your PR's preview. To
check your docs changes, make sure to select `Preview` from the version selection box of the site.
- Run `yarn install` in WSL. Yarn will compile several dependencies. If you don't run `install` in WSL, they will be compiled for Windows.
- Run `yarn test` and other commands in WSL.
## Submission Guidelines
### <a name="submit-issue"></a> Submitting an Issue
Before you submit an issue, please search the issue tracker. An issue for your problem may already exist and has been
resolved, or the discussion might inform you of workarounds readily available.
Before you submit an issue, please search the issue tracker. An issue for your problem may already exist and has been resolved, or the discussion might inform you of workarounds readily available.
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. Having a
reproducible scenario gives us wealth of important information without going back and forth with you requiring
additional information, such as:
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. Having a reproducible scenario gives us wealth of important information without going back and forth with you requiring additional information, such as:
- the output of `nx report`
- `yarn.lock` or `package-lock.json` or `pnpm-lock.yaml`
- `yarn.lock` or `package-lock.json`
- and most importantly - a use-case that fails
A minimal reproduction allows us to quickly confirm a bug (or point out a coding problem) as well as confirm that we are
fixing the right problem.
A minimal reproduction allows us to quickly confirm a bug (or point out coding problem) as well as confirm that we are fixing the right problem.
We will be insisting on a minimal reproduction in order to save maintainers' time and ultimately be able to fix more
bugs. Interestingly, from our experience, users often find coding problems themselves while preparing a minimal
reproduction repository. We understand that sometimes it might be hard to extract essentials bits of code from a larger
codebase, but we really need to isolate the problem before we can fix it.
We will be insisting on a minimal reproduction in order to save maintainers time and ultimately be able to fix more bugs. Interestingly, from our experience, users often find coding problems themselves while preparing a minimal repository. We understand that sometimes it might be hard to extract essentials bits of code from a larger code-base but we really need to isolate the problem before we can fix it.
You can file new issues by filling out our [issue form](https://github.com/nrwl/nx/issues/new/choose).
You can file new issues by filling out our [issue form](https://github.com/nrwl/nx/issues/new).
### <a name="submit-pr"></a> Submitting a PR
Please follow the following guidelines:
- Make sure unit tests pass (`nx affected --target=test`)
- Target a specific project with: `nx run proj:test` (i.e. `nx run angular:test` to target `packages/angular`)
- Target a specific unit test file (i.e. `packages/angular/src/utils/ast-command-line-utils.spec.ts`)
with `npx jest angular/src/utils/ast-utils` or `npx jest packages/angular/src/utils/ast-utils`
- For more options on running tests - check `npx jest --help` or visit [jestjs.io](https://jestjs.io/)
- Make sure unit tests pass (`yarn test`)
- Target a specific unit test (i.e. `/build/packages/angular/src/utils/ast-utils.spec.js`) with `yarn test angular/src/utils/ast-utils`
- Debug with `node --inspect-brk ./node_modules/jest/bin/jest.js build/packages/angular/src/utils/ast-utils.spec.js`
- Make sure e2e tests pass (this can take a while, so you can always let CI check those) (`nx affected --target=e2e`)
- Target a specific e2e test with `nx e2e e2e-cypress`
- Make sure you run `nx format`
- Update documentation with `pnpm documentation`. For documentation, check for spelling and grammatical errors.
- Update your commit message to follow the guidelines below (use `pnpm commit` to automate compliance)
- `pnpm check-commit` will check to make sure your commit messages are formatted correctly
- Make sure e2e tests pass (this can take a while, so you can always let CI check those) (`yarn e2e`)
- Target a specific e2e test (i.e. `/build/e2e/cypress.test.js`) with `yarn e2e cypress`
- Debug with `node --inspect-brk ./node_modules/jest/bin/jest.js build/e2e/cypress.test.js`
- Make sure you run `yarn format`
- Update documentation with `yarn documentation`. For documentation, check for spelling and grammatical errors.
- Update your commit message to follow the guidelines below (use `yarn commit` to automate compliance)
- `yarn check-commit` will check to make sure your commit messages are formatted correctly
#### Commit Message Guidelines
The commit message should follow the following format:
```plain
```
type(scope): subject
BLANK LINE
body
@@ -321,61 +151,42 @@ body
The type must be one of the following:
- feat - New or improved behavior being introduced (e.g. Updating to new versions of React or Jest which bring in new
features)
- fix - Fixes the current unexpected behavior to match expected behavior (e.g. Fixing the library generator to create
the proper named project)
- cleanup - Code Style changes that have little to no effect on the user (e.g. Refactoring some functions into a
different file)
- docs - Changes to the documentation (e.g. Adding more details into the getting started guide)
- chore - Changes that have absolutely no effect on users (e.g. Updating the version of Nx used to build the repo)
- chore
- feat
- fix
- cleanup
- docs
##### Scope
The scope must be one of the following:
- angular - anything Angular specific
- bundling - anything bundling specific (e.g. rollup, webpack, etc.)
- core - anything Nx core specific
- detox - anything Detox specific
- devkit - devkit-related changes
- graph - anything graph app specific
- expo - anything Expo specific
- express - anything Express specific
- js - anything related to @nx/js package or general js/ts support
- linter - anything Linter specific
- module-federation - anything Nx Module Federation specific
- nest - anything Nest specific
- docs - anything related to docs infrastructure
- nextjs - anything Next specific
- nest - anything Nest specific
- node - anything Node specific
- nx-cloud - anything Nx Cloud specific
- nx-plugin - anything Nx Plugin specific
- nx-dev - anything related to docs infrastructure
- linter - anything Linter specific
- react - anything React specific
- react-native - anything React Native specific
- release - anything related to nx release
- repo - anything related to managing the Nx repo itself
- storybook - anything Storybook specific
- testing - anything testing specific (e.g., Jest or Cypress)
- vite - anything Vite specific
- vue - anything Vue specific
- web - anything Web specific
- webpack - anything Webpack specific
- storybook - anything Storybook specific
- testing - anything testing specific (e.g., jest or cypress)
- repo - anything related to managing the repo itself
- misc - misc stuff
##### Subject and Body
The subject must contain a description of the change, and the body of the message contains any additional details to
provide more context about the change.
The subject must contain a description of the change, and the body of the message contains any additional details to provide more context about the change.
Including the issue number that the PR relates to also helps with tracking.
#### Example
```plain
feat(angular): add an option to generate lazy-loadable modules
```
feat(schematics): add an option to generate lazy-loadable modules
`nx generate lib libs/mylib --lazy` provisions the mylib project in .eslintrc.json
`nx generate lib mylib --lazy` provisions the mylib project in tslint.json
Closes #157
```
@@ -383,60 +194,4 @@ Closes #157
#### Commitizen
To simplify and automate the process of committing with this format,
**Nx is a [Commitizen](https://github.com/commitizen/cz-cli) friendly repository**, just do `git add` and
execute `pnpm commit`.
##### Using the Interactive Commit Tool
Instead of `git commit`, use:
```bash
pnpm commit
```
This will launch an interactive prompt that will:
1. Ask you to select the type of change (feat, fix, docs, cleanup, chore)
2. Let you choose the appropriate scope from the predefined list
3. Guide you through writing a clear, descriptive commit message
4. Ensure your commit follows the conventional commit format
##### Available Commit Types
- **feat**: A new feature
- **fix**: A bug fix
- **docs**: Documentation only changes
- **cleanup**: A code change that neither fixes a bug nor adds a feature
- **chore**: Other changes that don't modify src or test files
##### Available Scopes
The repository includes many predefined scopes. Use the one which is most specific to the changes being committed
- **core**: anything Nx core specific
- **angular**: anything Angular specific
- **react**: anything React specific
- **nextjs**: anything Next specific
- **node**: anything Node specific
- **devkit**: devkit-related changes
- **graph**: anything graph app specific
- **testing**: anything testing specific (e.g. jest or cypress)
- **misc**: misc stuff
- **repo**: anything related to managing the repo itself
- **nx-dev**: anything related to docs infrastructure
For the complete list of available scopes, see `/scripts/commitizen.js`.
##### Example Commits
```bash
feat(core): add new project graph visualization
fix(angular): resolve build issues with standalone components
docs(misc): update contributing guidelines
chore(repo): bump dependencies
cleanup(devkit): refactor utility functions for better readability
```
#### PR releases
If you are working on a particularly complex change or feature addition, you can request a dedicated Nx release for the associated pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate.
**Nx is a [Commitizen](https://github.com/commitizen/cz-cli) friendly repository**, just do `git add` and execute `yarn commit`.
Generated
-5085
View File
File diff suppressed because it is too large Load Diff
-9
View File
@@ -1,9 +0,0 @@
[workspace]
resolver = '2'
members = [
'packages/nx',
]
[profile.release]
lto = true
+22 -22
View File
@@ -1,22 +1,22 @@
(The MIT License)
Copyright (c) 2017-2025 Narwhal Technologies Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
(The MIT License)
Copyright (c) 2017-2020 Narwhal Technologies Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+225 -67
View File
@@ -1,103 +1,261 @@
<p style="text-align: center;">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-dark.svg">
<img alt="Nx - Smart Repos · Fast Builds" src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-light.svg" width="100%">
</picture>
</p>
<p align="center"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx.png" width="600"></p>
<div style="text-align: center;">
<div align="center">
[![CircleCI](https://circleci.com/gh/nrwl/nx.svg?style=svg)](https://circleci.com/gh/nrwl/nx)
[![License](https://img.shields.io/npm/l/nx.svg?style=flat-square)]()
[![NPM Version](https://badge.fury.io/js/nx.svg)](https://www.npmjs.com/package/nx)
[![Semantic Release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic-release-e10079.svg?style=flat-square)]()
[![License](https://img.shields.io/npm/l/@nrwl/workspace.svg?style=flat-square)]()
[![NPM Version](https://badge.fury.io/js/%40nrwl%2Fworkspace.svg)](https://www.npmjs.com/@nrwl/workspace)
[![Semantic Release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square)]()
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
[![Join the chat at https://gitter.im/nrwl-nx/community](https://badges.gitter.im/nrwl-nx/community.svg)](https://gitter.im/nrwl-nx/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Join the Official Nx Discord Server](https://img.shields.io/discord/1143497901675401286?label=discord)](https://go.nx.dev/community)
[![Join us @nrwl/community on slack](https://img.shields.io/badge/slack-%40nrwl%2Fcommunity-brightgreen)](https://bit.ly/2ZApcSo)
</div>
<hr>
# Smart Repos · Fast Builds
# What is Nx?
Get to green PRs in half the time. Nx optimizes your builds, scales your CI, and fixes failed PRs. Built for developers and AI agents.
🔎 **Extensible Dev Tools for Monorepos.**
Create a new Nx workspace with
## Nx Helps You
```shell
### Develop like Google, Facebook, and Microsoft
Nx helps scale your development from one team building one application to many teams building multiple frontend and backend applications all in the same workspace. When using Nx, developers have a holistic dev experience powered by an advanced CLI (with editor plugins), capabilities for controlled code sharing and consistent code generation.
### Use Intelligent Build System with Distributed Caching
Nx is smart. It analyzes your workspace and figures out what can be affected by every code change. That's why Nx doesn't rebuild and retest everything on every commit--it only rebuilds what is necessary.
Nx also uses a distributed computation cache. If someone has already built or tested similar code, Nx will use their results to speed up the command for everyone else instead of rebuilding or retesting the code from scratch. This, in combination with Nxs support for distributed and incremental builds, can help teams see up to 10x reduction in build and test times.
### Use Modern Tools
Nx is an open platform with plugins for many modern tools and frameworks. It has support for TypeScript, React, Angular, Cypress, Jest, Prettier, Nest.js, Next.js, Storybook, Ionic among others. With Nx, you get a consistent dev experience regardless of the tools used.
# Getting Started
## Creating an Nx Workspace
**Using `npx`**
```bash
npx create-nx-workspace
```
...or run
**Using `npm init`**
```
npx nx init
```bash
npm init nx-workspace
```
to add Nx to your existing workspace to get faster task scheduling, caching and more. More [in the docs](https://nx.dev/getting-started/intro).
**Using `yarn create`**
## Learn about CI with Nx Cloud
[Nx Cloud](https://nx.dev/nx-cloud) connects directly to your existing CI setup, helping you scale your monorepos on CI by leveraging [remote caching](https://nx.dev/ci/features/remote-cache?utm_source=nxrepo&utm_medium=readme&utm_campaign=nxrepo), [task distribution across multiple machines](https://nx.dev/ci/features/distribute-task-execution?utm_source=nxrepo&utm_medium=readme&utm_campaign=nxrepo), [automated e2e test splitting](https://nx.dev/ci/features/split-e2e-tasks?utm_source=nxrepo&utm_medium=readme&utm_campaign=nxrepo) and [automated task flakiness detection](https://nx.dev/ci/features/flaky-tasks?utm_source=nxrepo&utm_medium=readme&utm_campaign=nxrepo)
Connect your existing Nx workspace with
```
npx nx connect
```bash
yarn create nx-workspace
```
Learn more in the [Nx CI docs &raquo;](https://nx.dev/ci/getting-started/intro?utm_source=nxrepo&utm_medium=readme&utm_campaign=nxrepo)
The `create-nx-workspace` command will ask you to select a preset, which will configure some plugins and create your applications to help you get started.
## Useful links
```
? What to create in the new workspace (Use arrow keys)
empty [an empty workspace with a layout that works best for building apps]
oss [an empty workspace with a layout that works best for open-source projects]
web components [a workspace with a single app built using web components]
angular [a workspace with a single Angular application]
angular-nest [a workspace with a full stack application (Angular + Nest)]
react [a workspace with a single React application]
react-express [a workspace with a full stack application (React + Express)]
next.js [a workspace with a single Next.js application]
```
- [Our docs](https://nx.dev/docs)
- [Our blog](https://nx.dev/blog)
- [Our community discord, live stream,...](https://nx.dev/community)
- [Our YouTube channel](https://www.youtube.com/@NxDevtools)
- [Our Twitter/X](https://x.com/nxdevtools)
Select the preset that works best for you. You can always add plugins later.
<p style="text-align: center;"><a href="https://www.youtube.com/@nxdevtools/videos" target="_blank" rel="noreferrer"><img src="./images/nx-courses-and-videos.svg"
width="100%" alt="Nx - Smart Repos · Fast Builds"></a></p>
```
? Workspace name (e.g., org name) happyorg
? What to create in the new workspace web components [a workspace with a single app built using web components]
? Application name myapp
? Default stylesheet format CSS
```
If it's your first Nx project, the command will recommend you to install the `nx` package globally, so you can invoke `nx` directly without going through yarn or npm.
## Serving Application
- Run `nx serve myapp` to serve the newly generated application!
- Run `nx test myapp` to test it.
- Run `nx e2e myapp-e2e` to run e2e tests for it.
Angular users can also run `ng g/serve/test/e2e`.
You are good to go!
### Documentation
- [Nx Documentation and Guides](https://nx.dev)
### Quick Start Videos
<table>
<tr>
<td>
<a href="https://www.youtube.com/watch?v=mVKMse-gFBI" target="_blank">
<p align="center">Angular<br><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-angular-video.png" width="350"></p>
</a>
</td>
<td>
<a href="https://www.youtube.com/watch?v=E188J7E_MDU" target="_blank">
<p align="center">React<br><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-react-video.png" width="350"></p>
</a>
</td>
</tr>
</table>
### Courses
<table>
<tr>
<td>
<a href="https://www.youtube.com/watch?v=2mYLe9Kp9VM&list=PLakNactNC1dH38AfqmwabvOszDmKriGco" target="_blank">
<p align="center"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-workspace-course.png" width="350"></p>
</a>
</td>
<td>
<a href="https://nxplaybook.com/p/advanced-nx-workspaces" target="_blank">
<p align="center"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/advanced-nx-workspace-course.png" width="350"></p>
</a>
</td>
</tr>
</table>
### Talks
- [Smarter & Faster Angular Development with Nx (ngconf webinar)](https://youtu.be/LEqJ1xKf_1w), Juri Strumpflohner, Isaac Mann (Oct 16, 2020)
- [React Development At Scale (React Vancouver Virtual Meetup)](https://youtu.be/ZGXuzVipe1U?t=3721), Jack Hsu (May 27, 2020)
- [Scalable React Development (React Summit Remote Edition)](https://www.youtube.com/watch?v=Lr-u2ALSEQg), Jason Jean (April 17, 2020)
Slides: [https://prezi.com/view/fm9sUbR7vbr5fZlO9C8D/](https://prezi.com/view/fm9sUbR7vbr5fZlO9C8D/)
- [Beyond Basics: Scaling Development across Large Teams (Angular Rome Meetup online)](https://docs.google.com/presentation/d/1zEgeppole9avhrvV6Zmpmk-L1W9-6JsHbnjaJwBigtQ/edit?usp=sharing), Juri Strumpflohner (April 2, 2020)
- [Develop like Google, Microsoft, and Facebook with Nx - Dev Nexus](https://prezi.com/view/BVhl92reqg7cnhvv6hhH/), Jason Jean (February 18, 2020)
- [Enhancing the workspace with Custom Builders - AngularToronto](https://www.youtube.com/watch?v=M1Bk_O49n94), Benjamin Cabanes (February 18, 2020)
- [Advanced Nx - Angular Air](https://www.youtube.com/watch?v=pcTSDMid-aE), Isaac Mann (February 5th, 2020)
- [Teach Me Anything - HackFlix](https://www.youtube.com/watch?v=WRmj4JwfoMs) - Isaac Mann (January 9th, 2020)
* [E2E Testing at Half the Cost - NG-BE 2019](https://www.youtube.com/watch?v=C88th0SbepE), Isaac Mann (Dev 10, 2019)
* [Sneak Peek of New Nx Workspace Course - ngHouston](https://www.youtube.com/watch?v=uLbA4f2SINE&feature=youtu.be), Isaac Mann (Nov 27, 2019)
* [Building Large Angular Apps - ngBucharest](https://www.youtube.com/watch?v=bKhyTeTCf7M), Isaac Mann (March 30, 2019)
- Slides: [https://prezi.com/view/jglXvEfeqnjEr4l2L11h/](https://prezi.com/view/jglXvEfeqnjEr4l2L11h/)
* [Modern Development with Angular CLI & Nrwl Nx](https://www.youtube.com/watch?v=tE8sUAfKI3g), Victor Savkin at ngAtlanta (Feb 5, 2019)
* [Supercharging the Angular CLI](https://www.youtube.com/watch?v=bMkKz8AedHc) - ngVikings, James Henry (March 10, 2018)
* [Hands on Full Stack development with Nx and Bazel](https://www.youtube.com/watch?v=1KDDIhcQORM) - ngConf, Alex Eagle, Torgeir Helgevold (April 19, 2018)
* [Angular at Large Organizations](https://www.youtube.com/watch?v=piQ0EZhtus0) - ngConf, Victor Savkin(April 20, 2018)
* [Building Large Angular Apps Successfully with Nx - AngularNYC Meetup](https://youtu.be/Jwv3wRZ3BTM), Jason Jean (December 19, 2018)
- [Nx: The New Way to Build Enterprise Angular Apps](https://www.youtube.com/watch?v=xo-1SDmvM8Y) - Angular Mix, Jeff Cross & Victor Savkin (October 11, 2017)
### Podcasts and Shows
- [Nx Plugins - ngHouston](https://youtu.be/bydqr-Yxsu8), Wes Grimes and Jon Cammisuli (April 8 2020)
- [Apollo GQL, Angular & Nx - ngHouston](https://youtu.be/bydqr-Yxsu8), Philip Fulcher (Feb 26, 2020)
- [Teach Me Anything - With Isaac Mann from Nrwl](https://youtu.be/WRmj4JwfoMs), Isaac Mann (Jan 9, 2020)
- [Sneak Peek of New Nx Workspace Course - ngHouston](https://www.youtube.com/watch?v=uLbA4f2SINE&feature=youtu.be), Isaac Mann (Nov 27, 2019)
- [React Roundup: Nx and Monorepos](https://player.fm/series/react-round-up/rru-081-nx-and-monorepos-with-jeffrey-cross-and-victor-savkin), Victor Savkin (Oct 1, 2019)
- [Nx and Angular CLI - Adventures in Angular](https://devchat.tv/adv-in-angular/aia-254-nx-and-angular-cli-with-brandon-roberts/), Brandon Roberts (Aug 27th 2019)
- [ngHouston: NX Demo](https://www.youtube.com/watch?v=E_UlU2Yv4G0) (Dec 7, 2017)
- [ngAir 140: Nx for Enterprise Angular Development](https://www.youtube.com/watch?v=qYNiOKDno_I), Victor Savkin (Dec 12, 2017)
### Nx Demo & Tutorial Videos
- [Nx Dev Tools for Monorepos, In-Depth Explainer (React)](https://www.youtube.com/watch?v=jCf92IyR-GE)
- [Nx Dev Tools for Monorepos, In-Depth Explainer (Angular)](https://youtu.be/h5FIGDn5YM0)
- [Storybook Integration with Nx](https://youtu.be/sFpqyjT7u4s)
- [Building Custom Plugins for Nx](https://youtu.be/XYO689PAhow)
- [Improved Dependency Graph Visualization for Nx](https://youtu.be/cMZ-ReC-jWU)
- [Group all your stories into a single viewable Storybook with Nx](https://youtu.be/c323HOuFKkA)
- [Debug Nx with Node and VSCode](https://youtu.be/OGV4R0cPRPc)
- [Debug your Jest tests in Nx with VSCode](https://youtu.be/9_lgM2nokLg)
- [Nx Console - A Must-Have Visual Studio Code Extension for Angular Developers](https://youtu.be/IIetmfgozgI)
- [Introducing Nx Cloud](https://youtu.be/pwG20nNTEQc)
- [Setting up distributed caching using Nx Cloud, @nrwl/nx-cloud](https://youtu.be/w1-GiB74ddc)
- [High Quality React apps with Nx & Cypress](https://youtu.be/mfJBLhjYMdo)
### Books and Blogs
- [Nx blog posts](https://blog.nrwl.io/nx/home)
- [Angular Enterprise Monorepo Patterns Book (free)](https://go.nrwl.io/angular-enterprise-monorepo-patterns-new-book?utm_campaign=Book%3A%20Monorepo%20Patterns%2C%20Jan%202019&utm_source=Github&utm_medium=Banner%20Ad)
* [High Quality React apps with Nx & Cypress](https://cypress.io/blog/2020/04/14/high-quality-react-apps-with-nx-cypress/) (April 2020)
* [Shell Library patterns with Nx and Monorepo Architectures](https://indepth.dev/the-shell-library-patterns-with-nx-and-monorepo-architectures/) (March 2020)
- [Tiny Angular application projects in Nx workspaces](https://indepth.dev/tiny-angular-application-projects-in-nx-workspaces/#peer-reviewers--30/) (March 2020)
### Misc
- [nx-examples](https://github.com/nrwl/nx-examples) repo has branches for different nx comments to display expected behavior and example app and libraries. Check out the branch (workspace, ngrx...) to see what gets created for you. More info on readme.
- [xplat - Cross-platform tools for Nx workspaces](https://nstudio.io/xplat/)
## Want to help?
If you want to file a bug or submit a PR, read up on
our [guidelines for contributing](https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md) and watch this video that will
help you get started.
If you want to file a bug or submit a PR, read up on our [guidelines for contributing](https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md) and watch this video that will help you get started.
<a href="https://www.youtube.com/watch?v=8LCA_4qxc08" target="_blank" rel="noreferrer">
<p style="text-align: center;"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/how-to-contribute.png" width="600" alt="Nx - How to contribute video"></p>
<a href="https://www.youtube.com/watch?v=o11p0zSm0No&feature=youtu.be" target="_blank">
<p align="center"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/how-to-contribute.png" width="600"></p>
</a>
## Core Team
| Victor Savkin | Jason Jean | Benjamin Cabanes | Jack Hsu |
| ---------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| ![Victor Savkin](https://avatars1.githubusercontent.com/u/35996?s=160) | ![Jason Jean](https://avatars2.githubusercontent.com/u/8104246?s=160) | ![Benjamin Cabanes](https://avatars2.githubusercontent.com/u/3447705?s=160) | ![Jack Hsu](https://avatars0.githubusercontent.com/u/53559?s=160) |
| [vsavkin](https://github.com/vsavkin) | [FrozenPandaz](https://github.com/FrozenPandaz) | [bcabanes](https://github.com/bcabanes) | [jaysoo](https://github.com/jaysoo) |
| Victor Savkin | Jason Jean | Benjamin Cabanes | Brandon Roberts |
| ---------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| ![Victor Savkin](https://avatars1.githubusercontent.com/u/35996?s=150) | ![Jason Jean](https://avatars2.githubusercontent.com/u/8104246?s=150) | ![Benjamin Cabanes](https://avatars2.githubusercontent.com/u/3447705?s=150) | ![Brandon Roberts](https://avatars1.githubusercontent.com/u/42211?s=150) |
| [vsavkin](https://github.com/vsavkin) | [FrozenPandaz](https://github.com/FrozenPandaz) | [bcabanes](https://github.com/bcabanes) | [brandonroberts](https://github.com/brandonroberts) |
| James Henry | Jon Cammisuli | Max Kless | Juri Strumpflohner |
| ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | -------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| ![James Henry](https://avatars.githubusercontent.com/u/900523?s=160&v=4) | ![Jon Cammisuli](https://avatars2.githubusercontent.com/u/4332460?s=160) | ![Max Kless](https://avatars.githubusercontent.com/u/34165455?s=160) | ![Juri Strumpflohner](https://avatars1.githubusercontent.com/u/542458?s=160) |
| [JamesHenry](https://github.com/JamesHenry) | [cammisuli](https://github.com/cammisuli) | [MaxKless](https://github.com/MaxKless) | [juristr](https://github.com/juristr) |
| Jack Hsu | Jo Hanna Pearce | Jon Cammisuli | Isaac Mann |
| --------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| ![Jack Hsu](https://avatars0.githubusercontent.com/u/53559?s=150&v=4) | ![Jo Hanna Pearce](https://avatars1.githubusercontent.com/u/439121?s=150&v=4) | ![Jon Cammisuli](https://avatars2.githubusercontent.com/u/4332460?s=150&v=4) | ![Isaac Mann](https://avatars1.githubusercontent.com/u/861504?s=150) |
| [jaysoo](https://github.com/jaysoo) | [jdpearce](https://github.com/jdpearce) | [cammisuli](https://github.com/cammisuli) | [isaacplmann](https://github.com/isaacplmann) |
| Philip Fulcher | Caleb Ukle | Colum Ferry | Steven Nance |
| ------------------------------------------------------------------------- | --------------------------------------------------------------------- | ---------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| ![Philip Fulcher](https://avatars1.githubusercontent.com/u/1536471?s=160) | ![Caleb Ukle](https://avatars.githubusercontent.com/u/23272162?s=160) | ![Colum Ferry](https://avatars.githubusercontent.com/u/12140467?s=160) | ![Steven Nance](https://avatars.githubusercontent.com/u/1036428?s=160) |
| [philipjfulcher](https://github.com/philipjfulcher) | [barbados-clemens](https://github.com/barbados-clemens) | [Coly010](https://github.com/Coly010) | [llwt](https://github.com/llwt) |
| Adam Barrett | Juri Strumpflohner | Max Koretskyi | Philip Fulcher / |
| ------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| ![Adam Barrett](https://avatars0.githubusercontent.com/u/76821?s=150&v=4) | ![Juri Strumpflohner](https://avatars1.githubusercontent.com/u/542458?s=150&v=4) | ![Max Koretskyi](https://avatars2.githubusercontent.com/u/6124091?s=150&v=4) | ![Philip Fulcher](https://avatars1.githubusercontent.com/u/1536471?s=150) |
| [BigAB](https://github.com/BigAB) | [juristr](https://github.com/juristr) | [maxkoretskyi](https://github.com/maxkoretskyi) | [philipjfulcher](https://github.com/philipjfulcher) |
| Miroslav Jonaš | Leosvel Pérez Espinosa | Zachary DeRose | Craigory Coppola |
| ----------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
| ![Miroslav Jonaš](https://avatars.githubusercontent.com/u/881612?s=160) | ![Leosvel Pérez Espinosa](https://avatars.githubusercontent.com/u/12051310?s=160) | ![Zachary DeRose](https://avatars.githubusercontent.com/u/3788405?s=160) | ![Craigory Coppola](https://avatars.githubusercontent.com/u/6933928?s=160) |
| [meeroslav](https://github.com/meeroslav) | [leosvelperez](https://github.com/leosvelperez) | [ZackDeRose](https://github.com/ZackDeRose) | [AgentEnder](https://github.com/AgentEnder) |
| Chau Tran | Nicole Oliver | Rares Matei | Altan Stalker |
| -------------------------------------------------------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| ![Chau Tran](https://avatars.githubusercontent.com/u/25516557?s=160) | ![Nicole Oliver](https://avatars.githubusercontent.com/u/4440385?s=160) | ![Rares Matei](https://avatars.githubusercontent.com/u/5975076?s=160) | ![Altan Stalker](https://avatars.githubusercontent.com/u/6324206?s=160) |
| [nartc](https://github.com/nartc) | [nixallover](https://github.com/nixallover) | [rarmatei](https://github.com/rarmatei) | [StalkAltan](https://github.com/StalkAltan) |
| Josh VanAllen | Austin Fahsl | Louie Weng |
| ----------------------------------------------------------------------- | ---------------------------------------------------------------------- | --------------------------------------------------------------------- |
| ![Josh VanAllen](https://avatars.githubusercontent.com/u/5290334?s=160) | ![Austin Fahsl](https://avatars.githubusercontent.com/u/6913035?s=160) | ![Louie Weng](https://avatars.githubusercontent.com/u/56288712?s=160) |
| [joshvanallen](https://github.com/joshvanallen) | [fahslaj](https://github.com/fahslaj) | [lourw](https://github.com/lourw) |
| Katerina Skroumpelou |
| ----------------------------------------------------------------------------------- |
| ![Katerina Skroumpelou](https://avatars0.githubusercontent.com/u/6603745?s=150&v=4) |
| [mandarini](https://github.com/mandarini) |
-15
View File
@@ -1,15 +0,0 @@
# Security Policy
Nx/Nrwl takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations.
If you believe you have found a security vulnerability in any Nx-owned repository that meets Nx's definition of a security vulnerability, please report it to us as described below.
## Reporting Security Issues
**Please do not report security vulnerabilities through public GitHub issues.**
Instead, please report them to the Security Team at security@nrwl.io.
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message.
Nx follows the principle of Coordinated Vulnerability Disclosure.
+14
View File
@@ -0,0 +1,14 @@
{
"rules": {},
"overrides": [
{
"files": ["src/plugins/index.js"],
"rules": {
"@typescript-eslint/no-var-requires": "off",
"no-undef": "off"
}
}
],
"extends": ["plugin:cypress/recommended", "../../.eslintrc"],
"ignorePatterns": ["!**/*"]
}
+12
View File
@@ -0,0 +1,12 @@
{
"fileServerFolder": ".",
"fixturesFolder": "./src/fixtures",
"integrationFolder": "./src/integration",
"modifyObstructiveCode": false,
"pluginsFile": "./src/plugins/index",
"supportFile": "./src/support/index.ts",
"video": true,
"videosFolder": "../../dist/cypress/apps/dep-graph-client-e2e/videos",
"screenshotsFolder": "../../dist/cypress/apps/dep-graph-client-e2e/screenshots",
"chromeWebSecurity": false
}
@@ -0,0 +1,13 @@
import { getGreeting } from '../support/app.po';
describe('dep-graph-client', () => {
beforeEach(() => cy.visit('/'));
it('should display welcome message', () => {
// Custom command example, see `../support/commands.ts` file
cy.login('my-email@something.com', 'myPassword');
// Function helper example, see `../support/app.po.ts` file
getGreeting().contains('Welcome to dep-graph-client!');
});
});
@@ -0,0 +1,22 @@
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
const { preprocessTypescript } = require('@nrwl/cypress/plugins/preprocessor');
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
// Preprocess Typescript file using Nx helper
on('file:preprocessor', preprocessTypescript(config));
};
@@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"sourceMap": false,
"outDir": "../../dist/out-tsc",
"allowJs": true,
"types": ["cypress", "node"]
},
"include": ["src/**/*.ts", "src/**/*.js"]
}
+10
View File
@@ -0,0 +1,10 @@
{
"extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.e2e.json"
}
]
}
+1
View File
@@ -0,0 +1 @@
{ "extends": "../../.eslintrc", "rules": {}, "ignorePatterns": ["!**/*"] }
+13
View File
@@ -0,0 +1,13 @@
# This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
#
# If you need to support different browsers in production, you may tweak the list below.
last 1 Chrome version
last 1 Firefox version
last 2 Edge major versions
last 2 Safari major version
last 2 iOS major versions
Firefox ESR
not IE 9-11 # For IE 9-11 support, remove 'not'.
+10
View File
@@ -0,0 +1,10 @@
module.exports = {
name: 'dep-graph-client',
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
globals: {
'ts-jest': {
tsConfig: '<rootDir>/tsconfig.spec.json',
},
},
coverageDirectory: '../../coverage/apps/dep-graph-client',
};
@@ -0,0 +1,594 @@
import { default as tippy, hideAll } from 'tippy.js';
import { select, curveBasis, zoom, zoomIdentity } from 'd3';
import * as dagreD3 from 'dagre-d3';
function getProjectsByType(type) {
return window.projects.filter((project) => project.type === type);
}
function groupProjectsByDirectory(projects) {
let groups = {};
projects.forEach((project) => {
const split = project.data.root.split('/');
const directory = split.slice(1, -1).join('/');
if (!groups.hasOwnProperty(directory)) {
groups[directory] = [];
}
groups[directory].push(project);
});
return groups;
}
function createProjectList(headerText, projects) {
const header = document.createElement('h5');
header.textContent = headerText;
const formGroup = document.createElement('div');
formGroup.className = 'form-group';
let sortedProjects = [...projects];
sortedProjects.sort(function (a, b) {
return a.name.localeCompare(b.name);
});
projects.forEach((project) => {
let formLine = document.createElement('div');
formLine.className = 'form-line';
let focusButton = document.createElement('button');
focusButton.className = 'icon';
let buttonIconContainer = document.createElementNS(
'http://www.w3.org/2000/svg',
'svg'
);
let buttonIcon = document.createElementNS(
'http://www.w3.org/2000/svg',
'use'
);
buttonIcon.setAttributeNS(
'http://www.w3.org/1999/xlink',
'xlink:href',
'#crosshair'
);
buttonIconContainer.appendChild(buttonIcon);
focusButton.append(buttonIconContainer);
focusButton.onclick = () => {
focusProject(project.name);
};
let label = document.createElement('label');
label.className = 'form-checkbox';
let checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.name = 'projectName';
checkbox.value = project.name;
checkbox.checked = false;
checkbox.addEventListener('change', filterProjects);
const labelText = document.createTextNode(project.name);
formLine.append(focusButton);
formLine.append(label);
label.append(checkbox);
label.append(labelText);
formGroup.append(formLine);
});
const projectsListContainer = document.getElementById('project-lists');
projectsListContainer.append(header);
projectsListContainer.append(formGroup);
}
function addProjectCheckboxes() {
const appProjects = getProjectsByType('app');
const libProjects = getProjectsByType('lib');
const e2eProjects = getProjectsByType('e2e');
const npmProjects = getProjectsByType('npm');
const libDirectoryGroups = groupProjectsByDirectory(libProjects);
const projectsListContainer = document.getElementById('project-lists');
const appsHeader = document.createElement('h4');
appsHeader.textContent = 'app projects';
projectsListContainer.append(appsHeader);
createProjectList('apps', appProjects);
const e2eHeader = document.createElement('h4');
e2eHeader.textContent = 'e2e projects';
projectsListContainer.append(e2eHeader);
createProjectList('e2e', e2eProjects);
const libHeader = document.createElement('h4');
libHeader.textContent = 'lib projects';
projectsListContainer.append(libHeader);
const sortedDirectories = Object.keys(libDirectoryGroups).sort();
sortedDirectories.forEach((directoryName) => {
createProjectList(directoryName, libDirectoryGroups[directoryName]);
});
if (npmProjects.length > 0) {
const npmHeader = document.createElement('h4');
npmHeader.textContent = 'npm dependencies';
projectsListContainer.append(npmHeader);
createProjectList('npm', npmProjects);
}
}
function hasPath(target, node, visited) {
if (target === node) return true;
for (let d of window.graph.dependencies[node] || []) {
if (visited.indexOf(d.target) > -1) continue;
visited.push(d.target);
if (hasPath(target, d.target, visited)) return true;
}
return false;
}
function getProjectCheckboxes(): HTMLInputElement[] {
return Array.from(document.querySelectorAll('input[name=projectName]'));
}
function checkForAffected() {
const isAffected = window.affected.length > 0;
if (isAffected) {
const selectedAffectedButton = document.getElementById(
'select-affected-button'
);
selectedAffectedButton.classList.remove('hide');
selectAffectedProjects();
}
}
function selectAffectedProjects() {
window.focusedProject = null;
document.getElementById('focused-project').hidden = true;
document.getElementById('focused-project-name').innerText = '';
getProjectCheckboxes().forEach((checkbox) => {
checkbox.checked = window.affected.includes(checkbox.value);
});
window.filterProjects();
}
window.selectAffectedProjects = selectAffectedProjects;
function selectAllProjects() {
window.focusedProject = null;
document.getElementById('focused-project').hidden = true;
document.getElementById('focused-project-name').innerText = '';
getProjectCheckboxes().forEach((checkbox) => {
checkbox.checked = true;
});
window.filterProjects();
}
window.selectAllProjects = selectAllProjects;
function deselectAllProjects() {
window.focusedProject = null;
document.getElementById('focused-project').hidden = true;
document.getElementById('focused-project-name').innerText = '';
getProjectCheckboxes().forEach((checkbox) => {
checkbox.checked = false;
});
window.filterProjects();
}
window.deselectAllProjects = deselectAllProjects;
function createDirectoryParents(g, directories) {
let childDirectory = directories.join('/');
let childDirectoryId = `dir-${childDirectory}`;
if (!g.hasNode(childDirectoryId)) {
g.setNode(childDirectoryId, {
label: childDirectory,
clusterLabelPos: 'top',
});
}
if (directories.length > 1) {
let parentDirectory = directories.slice(0, -1).join('/');
let parentDirectoryId = `dir-${parentDirectory}`;
if (!g.hasNode(parentDirectoryId)) {
g.setNode(parentDirectoryId, {
label: parentDirectory,
clusterLabelPos: 'top',
});
}
g.setParent(childDirectoryId, parentDirectoryId);
createDirectoryParents(g, directories.slice(0, -1));
}
}
function generateLayout() {
const g = new dagreD3.graphlib.Graph({
compound: true,
orderRestarts: 10,
});
const groupByFolder = document.querySelector<HTMLInputElement>(
'input[name=displayOptions][value=groupByFolder]'
).checked;
g.setGraph({
ranksep: 150,
edgesep: 100,
});
g.setDefaultEdgeLabel(function () {
return {};
});
window.filteredProjects.forEach((p) => {
const shape =
p.name === window.focusedProject
? p.type === 'app' || p.type === 'e2e'
? 'glowRect'
: 'glowEllipse'
: p.type === 'app' || p.type === 'e2e'
? 'rect'
: 'ellipse';
const clazz = window.affected.includes(p.name) ? 'affected' : 'no-affected';
g.setNode(p.name, { label: p.name, shape: shape, class: clazz });
if (
groupByFolder &&
p.type == 'lib' &&
p.data.hasOwnProperty('sourceRoot')
) {
const split = p.data.sourceRoot.split('/');
let directories = split.slice(1, -2);
if (directories.length > 0) {
let directory = directories.join('/');
createDirectoryParents(g, directories);
let directoryId = `dir-${directory}`;
g.setParent(p.name, directoryId);
}
}
});
Object.keys(window.graph.dependencies).forEach((p) => {
const filteredProjectNames = window.filteredProjects.map((f) => f.name);
window.graph.dependencies[p].forEach((d) => {
if (
filteredProjectNames.indexOf(p) > -1 &&
filteredProjectNames.indexOf(d.target) > -1
) {
let clazz =
window.affected.indexOf(p) > -1 &&
window.affected.indexOf(d.target) > -1
? 'affected'
: 'no-affected';
if (d.type === 'dynamic') {
clazz += ' lazy';
}
const label = d.type === 'implicit' ? 'implicit' : undefined;
g.setEdge(p, d.target, {
label: label,
class: clazz,
curve: curveBasis,
});
}
});
});
return g;
}
function createRenderer() {
var render = new dagreD3.render();
render.shapes().glowRect = (parent, bbox, node) => {
const filter = node.class.includes('no-affected')
? 'sofGlowFocus'
: 'sofGlowFocusAffected';
var shapeSvg = parent
.insert('rect', ':first-child')
.attr('x', -bbox.width / 2)
.attr('y', -bbox.height / 2)
.attr('width', bbox.width)
.attr('height', bbox.height)
.attr('filter', `url(#${filter})`);
node.intersect = function (point) {
return dagreD3.intersect.rect(node, point);
};
return shapeSvg;
};
render.shapes().glowEllipse = (parent, bbox, node) => {
const filter = node.class.includes('no-affected')
? 'sofGlowFocus'
: 'sofGlowFocusAffected';
var rx = bbox.width / 2;
var ry = bbox.height / 2;
var shapeSvg = parent
.insert('ellipse', ':first-child')
.attr('x', -bbox.width / 2)
.attr('y', -bbox.height / 2)
.attr('rx', rx)
.attr('ry', ry)
.attr('filter', `url(#${filter})`);
node.intersect = function (point) {
return dagreD3.intersect.ellipse(node, rx, ry, point);
};
return shapeSvg;
};
return render;
}
function render() {
hideAll();
const g = generateLayout();
const render = createRenderer();
// Set up an SVG group so that we can translate the final graph.
var svg = select('#svg-canvas');
svg.select('g').remove();
let inner = svg.append('g');
// Set up zoom support
var z = zoom().on('zoom', function (event: any) {
inner.attr('transform', event.transform);
});
svg.call(z);
// Run the renderer. This is what draws the final graph.
setTimeout(() => {
render(inner, g);
// Center the graph
var initialScale = 0.75;
const mainContent = document.getElementById('main-content');
svg.call(
z.transform as any,
zoomIdentity
.translate(
(+svg.attr('width') - g.graph().width * initialScale) / 2,
20
)
.scale(initialScale)
);
svg.attr('height', mainContent.offsetHeight);
svg.attr('width', mainContent.offsetWidth);
addTooltips(inner);
});
}
function addTooltips(inner) {
const createTipTemplate = (project) => {
return `
<h4><span class="tag">${project.type}</span>${project.name}</h4>
<p><strong>tags</strong><br> ${project.data.tags.join(', ')}</p>
<div class="flex">
<button onclick="window.focusProject('${project.name}')">Focus</button>
<button onclick="window.excludeProject('${
project.name
}')">Exclude</button>
</div>
`;
};
inner.selectAll('g.node').each(function (id) {
const project = window.projects.find((p) => p.name === id);
tippy(this, {
content: createTipTemplate(project),
allowHTML: true,
interactive: true,
appendTo: document.body,
interactiveBorder: 10,
trigger: 'click',
});
});
}
function focusProject(id, doFilter = true) {
window.focusedProject = id;
document.getElementById('focused-project').hidden = false;
document.getElementById('focused-project-name').innerText = id;
Array.from(
document.querySelectorAll<HTMLInputElement>('input[name=projectName]')
).forEach((checkbox) => {
const showProject =
hasPath(id, checkbox.value, []) || hasPath(checkbox.value, id, []);
checkbox.checked = showProject;
checkbox.parentElement.hidden = !showProject;
});
if (doFilter) {
window.filterProjects();
}
}
window.focusProject = focusProject;
function unfocusProject() {
window.focusedProject = null;
document.getElementById('focused-project').hidden = true;
document.getElementById('focused-project-name').innerText = '';
Array.from(
document.querySelectorAll<HTMLInputElement>('input[name=projectName]')
).forEach((checkbox) => {
checkbox.checked = false;
checkbox.parentElement.hidden = false;
});
window.filterProjects();
}
window.unfocusProject = unfocusProject;
function excludeProject(id, doFilter = true) {
document.querySelector<HTMLInputElement>(
`input[name=projectName][value=${id}]`
).checked = false;
if (doFilter) {
window.filterProjects();
}
}
window.excludeProject = excludeProject;
function filterProjects() {
const checkboxes = Array.from(
document.querySelectorAll<HTMLInputElement>('input[name=projectName]')
);
const selectedProjects = checkboxes
.filter((checkbox) => checkbox.checked)
.map((checkbox) => checkbox.value);
const unselectedProjects = checkboxes
.filter((checkbox) => !checkbox.checked)
.map((checkbox) => checkbox.value);
if (selectedProjects.length === window.projects.length) {
window.filteredProjects = window.projects;
} else {
window.filteredProjects = window.projects.filter((p) => {
const filtered = selectedProjects.find(
(f) => hasPath(f, p.name, []) || hasPath(p.name, f, [])
);
return unselectedProjects.indexOf(p.name) === -1 && filtered;
});
}
if (window.filteredProjects.length === 0) {
document.getElementById('no-projects-chosen').style.display = 'flex';
} else {
document.getElementById('no-projects-chosen').style.display = 'none';
}
render();
}
window.filterProjects = filterProjects;
function listenForTextFilterChanges() {
const textFilterInput = document.getElementById(
'textFilterInput'
) as HTMLInputElement;
const textFilterButton = document.getElementById('textFilterButton');
textFilterButton.addEventListener('click', () => {
filterProjectsByText(textFilterInput.value.toLowerCase());
});
textFilterInput.addEventListener('keyup', (event) => {
if (event.key === 'Enter') {
filterProjectsByText(textFilterInput.value.toLowerCase());
}
});
}
function filterProjectsByText(text) {
const checkboxes = Array.from(
document.querySelectorAll<HTMLInputElement>('input[name=projectName]')
);
checkboxes.forEach((checkbox) => (checkbox.checked = false));
const split = text.split(',').map((splitItem) => splitItem.trim());
const matchedProjects = checkboxes
.map((checkbox) => checkbox.value)
.filter(
(project) =>
split.findIndex((splitItem) => project.includes(splitItem)) > -1
);
const includeInPath = document.querySelector<HTMLInputElement>(
'input[name=textFilterCheckbox]'
).checked;
matchedProjects.forEach((project) => {
checkboxes.forEach((checkbox) => {
if (
checkbox.value === project ||
(includeInPath &&
(hasPath(project, checkbox.value, []) ||
hasPath(checkbox.value, project, [])))
) {
checkbox.checked = true;
}
});
});
window.filterProjects();
}
export function main() {
addProjectCheckboxes();
checkForAffected();
document
.querySelector('input[name=displayOptions][value=groupByFolder]')
.addEventListener('change', () => window.filterProjects());
window.addEventListener('resize', () => render());
if (window.groupByFolder) {
document.querySelector<HTMLInputElement>(
'input[name=displayOptions][value=groupByFolder]'
).checked = true;
}
if (window.focusedProject !== null) {
focusProject(window.focusedProject, false);
}
if (window.exclude.length > 0) {
window.exclude.forEach((project) => excludeProject(project, false));
}
listenForTextFilterChanges();
filterProjects();
}
@@ -0,0 +1,3 @@
export const environment = {
production: true,
};
@@ -0,0 +1,6 @@
// This file can be replaced during build by using the `fileReplacements` array.
// When building for production, this file is replaced with `environment.prod.ts`.
export const environment = {
production: false,
};

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

+20
View File
@@ -0,0 +1,20 @@
import { ProjectGraph, ProjectGraphNode } from '@nrwl/workspace';
export declare global {
export interface Window {
projects: ProjectGraphNode[];
graph: ProjectGraph;
filteredProjects: ProjectGraphNode[];
affected: string[];
exclude: string[];
focusedProject: string;
groupByFolder: boolean;
focusProject: Function;
unfocusProject: Function;
excludeProject: Function;
selectAffectedProjects: Function;
filterProjects: Function;
selectAllProjects: Function;
deselectAllProjects: Function;
}
}
File diff suppressed because it is too large Load Diff
+140
View File
@@ -0,0 +1,140 @@
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title>DepGraphClient</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="crosshair" viewBox="0 0 24 24">
<g
fill="none"
stroke="#ffffff"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<circle cx="12" cy="12" r="10" />
<line x1="22" y1="12" x2="18" y2="12" />
<line x1="6" y1="12" x2="2" y2="12" />
<line x1="12" y1="6" x2="12" y2="2" />
<line x1="12" y1="22" x2="12" y2="18" />
</g>
</symbol>
</svg>
<div id="app">
<div class="sidebar">
<div class="sidebar-content">
<div id="focused-project" class="sidebar-section" hidden>
<h4>Focused on <span id="focused-project-name"></span></h4>
<button onclick="window.unfocusProject()">Unfocus</button>
</div>
<div class="sidebar-section">
<h4>Display Options</h4>
<div class="flex">
<button
id="select-affected-button"
onclick="window.selectAffectedProjects()"
class="hide"
>
Select Affected
</button>
<button id="select-all-button" onclick="window.selectAllProjects()">
Select All
</button>
<button
id="deselect-all-button"
onclick="window.deselectAllProjects()"
>
Deselect All
</button>
</div>
<label>
<input
type="checkbox"
name="displayOptions"
value="groupByFolder"
/>
group by folder
</label>
</div>
<div class="sidebar-section">
<div class="flex">
<input id="textFilterInput" type="text" name="filter" />
<button id="textFilterButton">Filter</button>
</div>
<label>
<input
type="checkbox"
name="textFilterCheckbox"
value="includeInPath"
/>
include projects in path
</label>
</div>
<div id="project-lists"></div>
</div>
</div>
<div id="main-content">
<div id="no-projects-chosen">
<h4>Please select projects in the sidebar.</h4>
</div>
<svg id="svg-canvas" width="960" height="600">
<defs>
<filter
id="sofGlowFocus"
height="300%"
width="300%"
x="-75%"
y="-75%"
>
<feDropShadow
dx="0"
dy="0"
stdDeviation="10"
flood-color="rgb(8, 108, 159)"
flood-opacity="1"
/>
</filter>
<filter
id="sofGlowFocusAffected"
height="300%"
width="300%"
x="-75%"
y="-75%"
>
<feDropShadow
dx="0"
dy="0"
stdDeviation="10"
flood-color="rgb(248,84,119)"
flood-opacity="1"
/>
</filter>
</defs>
</svg>
</div>
</div>
<script>
window.projects = null;
window.graph = null;
window.affected = null;
window.focusedProject = null;
window.filteredProjects = [];
window.groupByFolder = null;
window.exclude = null;
</script>
</body>
@@ -0,0 +1,3 @@
import { main } from './dep-graph/dep-graph';
setTimeout(() => main());
+15
View File
@@ -0,0 +1,15 @@
import { main } from './dep-graph/dep-graph';
import { mediumGraph } from './graphs/medium';
const currentGraph = mediumGraph;
const nodes = Object.values(currentGraph.nodes).filter(
(node) => node.type !== 'npm'
);
window.projects = nodes;
window.graph = currentGraph;
window.affected = [];
window.exclude = [];
setTimeout(() => main());
+7
View File
@@ -0,0 +1,7 @@
/**
* Polyfill stable language features. These imports will be optimized by `@babel/preset-env`.
*
* See: https://github.com/zloirock/core-js#babel
*/
import 'core-js/stable';
import 'regenerator-runtime/runtime';
+266
View File
@@ -0,0 +1,266 @@
@import '~tippy.js/dist/tippy.css';
:root {
--color-nrwl-blue: #48c4e5;
--color-nrwl-light-blue: #96d8e9;
--color-nrwl-gray: #333333;
--color-nrwl-navy: #143055;
--color-nrwl-twilight: #086c9f;
--color-nrwl-black: #231f20;
--color-nrwl-red: rgb(248, 84, 119);
--color-primary: var(--color-nrwl-navy);
--font-family: 'Montserrat', 'Helvetica Neue', sans-serif;
}
* {
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
html {
line-height: 1.6;
font-size: 14px;
font-family: var(--font-family);
}
button {
padding: 0.5em 1em;
border-radius: 4px;
border: 1px solid transparent;
font-size: 1em;
line-height: 1;
text-align: center;
-webkit-transition: opacity 0.2s ease;
transition: opacity 0.2s ease;
text-decoration: none;
-webkit-transform: scale(1);
transform: scale(1);
display: inline-block;
cursor: pointer;
background-color: var(--color-primary);
color: #fff;
}
button:hover {
opacity: 0.8;
}
button.icon {
width: 1.5em;
height: 1.5em;
padding: 0;
text-align: center;
line-height: 50%;
}
button.icon svg {
width: 1.25em;
height: 1.25em;
}
.form-line {
display: flex;
align-items: center;
justify-content: center;
}
.form-line label {
flex: 1;
}
.flex {
display: flex;
}
.flex button {
flex: 1;
}
.flex button:not(:last-child) {
margin-right: 1.5em;
}
label {
display: inline-block;
margin: 0.5em 0;
}
h4,
h5 {
margin-top: 0;
margin-bottom: 0.5em;
}
.form-group {
margin-bottom: 1em;
}
.sidebar-section {
margin-bottom: 1em;
}
.sidebar {
min-width: 200px;
max-width: calc(50% - 10px);
z-index: 1;
position: relative;
height: 100%;
min-width: 260px;
box-shadow: 2px 0 2px rgba(51, 51, 51, 0.1);
}
.sidebar-content {
box-sizing: border-box;
height: 100%;
overflow-y: auto;
padding: 1.5em;
width: 100%;
}
#main-content {
flex: 1;
overflow: hidden;
}
#apps,
#libs,
#e2e {
padding: 0;
list-style: none;
}
#libs,
#apps,
#e2e input {
padding-right: 8px;
}
#app,
body,
html {
height: 100%;
margin: 0;
overflow: hidden;
padding: 0;
width: 100%;
}
#app {
display: flex;
}
.clusters rect {
fill: var(--color-nrwl-twilight);
opacity: 0.5;
stroke: var(--color-nrwl-black);
stroke-width: 1.5px;
}
.clusters text {
font-weight: 300;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serf;
font-size: 48px;
}
text {
font-weight: 300;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serf;
font-size: 14px;
}
#svg-canvas {
cursor: grab;
}
#svg-canvas:active {
cursor: grabbing;
}
.node {
cursor: pointer;
}
.node rect,
.node ellipse {
stroke: var(--color-nrwl-black);
stroke-width: 1.5px;
fill: #fff;
}
g.affected rect,
g.affected ellipse {
stroke: var(--color-nrwl-red);
}
.edgePath.affected path {
stroke: var(--color-nrwl-red);
}
.edgePath.affected marker path {
fill: var(--color-nrwl-red);
}
.edgePath path {
stroke: var(--color-nrwl-gray);
stroke-width: 1.5px;
}
.edgePath.lazy path {
stroke-dasharray: 5, 5;
}
.sidebar-content .form-line {
display: flex;
}
.sidebar-content .form-line label {
flex: 1;
}
.sidebar-content h5 {
color: var(--color-nrwl-twilight);
}
.tippy-box {
background-color: var(--color-nrwl-twilight);
}
.tippy-content {
padding: 1.5em;
}
.tag {
padding: 0.4rem;
font-size: 0.75em;
display: inline-block;
border: 1px solid var(--color-nrwl-light-blue);
text-transform: uppercase;
color: var(--color-grey);
padding: 0.5rem;
line-height: 1;
letter-spacing: 0.5px;
margin-right: 0.4em;
}
.hide {
display: none;
}
#no-projects-chosen {
display: flex;
width: 100%;
height: 100%;
align-items: center;
justify-content: center;
}
#textFilterInput {
flex: 1;
margin-right: 1.5em;
}
#textFilterButton {
flex: none;
}
+1
View File
@@ -0,0 +1 @@
import 'document-register-element';
+10
View File
@@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["node"],
"lib": ["DOM"]
},
"exclude": ["**/*.spec.ts"],
"include": ["**/*.ts"]
}
+13
View File
@@ -0,0 +1,13 @@
{
"extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}
+10
View File
@@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"files": ["src/test-setup.ts"],
"include": ["**/*.spec.ts", "**/*.d.ts"]
}
-6
View File
@@ -1,6 +0,0 @@
node_modules/
dist/
.astro/
.netlify/
test-output/
playwright-report/
-22
View File
@@ -1,22 +0,0 @@
{
"extends": ["plugin:playwright/recommended", "../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
},
{
"files": ["e2e/**/*.{ts,js,tsx,jsx}"],
"rules": {}
}
]
}
-24
View File
@@ -1,24 +0,0 @@
# build output
dist/
# generated types
.astro/
# dependencies
node_modules/
# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# environment variables
.env
.env.production
# macOS-specific files
.DS_Store
# Local Netlify folder
.netlify
-235
View File
@@ -1,235 +0,0 @@
# Nx Documentation Site
[![Built with Starlight](https://astro.badg.es/v2/built-with-starlight/tiny.svg)](https://starlight.astro.build)
The Nx documentation site built with Astro and Starlight, featuring advanced content management through Markdoc and dynamic plugin documentation generation.
## Architecture Overview
This documentation site leverages Astro's static site generation capabilities with Starlight for documentation-specific features. The architecture consists of:
### Core Technologies
- [**Astro**](https://docs.astro.build) - Static site generator with island architecture
- [**Starlight**](https://starlight.astro.build) - Documentation theme with built-in navigation, search, and i18n
- **React** - For implementing UI components
- **Netlify** - Deployment and hosting
### Key Features
- [Markdoc](https://markdoc.dev) with custom tags for rich content such as videos, graphs, etc.
- TailwindCSS for styling in Astro and React components
- Dynamic API documentation generation from Nx packages and CLI commands
- Community plugin registry
## Project Structure
```
astro-docs/
├── src/
│ ├── assets/ # Images and static assets to be optimized by Astro
│ │ ├── nx/ # Nx branding assets
│ │ ├── nx-cloud/ # Nx Cloud assets
│ │ └── nx-console/ # Nx Console assets
│ ├── components/ # React and Astro components
│ │ ├── layout/ # Layout components (e.g. Sidebar)
│ │ ├── markdoc/ # Markdoc tag components
│ │ └── utils/ # Utility functions
│ ├── content/ # Documentation content
│ │ ├── docs/ # Main documentation files (.mdoc, .mdx)
│ │ ├── approved-community-plugins.json # Powers plugin registry
│ │ └── notifications.json # Notifications banners for docs site
│ ├── pages/ # Dynamic pages and routes (e.g. devkit)
│ ├── plugins/ # Content loaders and plugins
│ │ ├── *.loader.ts # Dynamic content loaders (e.g. CLI commands and API docs generation)
│ │ └── utils/ # Plugin utilities
│ └── styles/ # Global styles
├── public/ # Static assets not to be optimized by Astro (fonts, robots.txt)
├── astro.config.mjs # Astro configuration
├── markdoc.config.mjs # Markdoc tags configuration
├── sidebar.mts # Sidebar structure definition
└── package.json
```
## Plugins and Loaders
### Content Loaders
The site uses custom content loaders to dynamically generate documentation:
- **PluginLoader** (`plugin.loader.ts`) - Generates official plugin documentation (generators, executors, migrations)
- **CommunityPluginsLoader** (`community-plugins.loader.ts`) - Generates data for plugin registry (e.g. GitHub stars, npm downloads)
- **NxReferencePackagesLoader** (`nx-reference-packages.loader.ts`) - Generated data for CNW, Devkit, nx cli (e.g. nx core related things)
## Content Management
### Content Types
1. **Regular Documentation** (`src/content/docs/`)
- Written in `.mdoc` (Markdoc) or `.mdx` (MDX) format
- Organized by sections: getting-started, concepts, guides, api
- File-based routing (filename = URL path)
2. **Dynamic Plugin Documentation**
- Auto-generated from Nx packages
- Includes generators, executors, and migrations
- Updated during build process
- **Note**: Requires a rebuild and restart to reflect changes
3. **CLI Documentation**
- Auto-generated from Nx CLI commands
- Parsed from actual CLI implementation
- **Note**: Requires a rebuild and restart to reflect changes
### Markdoc Tags
The site includes custom Markdoc tags for rich content.
**Note**: Starlight supports many Markdown and Markdoc features, such as code blocks, asides, etc.
- https://starlight.astro.build/components/using-components/#using-a-component-in-markdoc
- https://starlight.astro.build/guides/authoring-content
#### Layout & Organization
- `{% aside %}` - Highlighted information boxes
- `{% cardgrid %}`, `{% card|linkcard %}` - Card layouts
- `{% tabs %}`, `{% tabitem label="some-label" %}` - Tab layouts
- Use the `syncKey` so tabs are auto switched to the users preference if it makes sense.
- e.g. `{% tabs syncKey="package-manager" %}`
#### Interactive Components
- `{% graph %}` - Interactive project/task graph visualization
- `{% project_details %}` - Project configuration viewer
#### Media & Embeds
- `{% youtube %}` - YouTube video embeds
- `{% video_player %}` - Custom video player
- `{% iframe %}` - Generic iframe embeds
#### Developer Tools
- `{% github_repository %}` - GitHub repo cards
- `{% stackblitz_button %}` - StackBlitz demo launcher
- `{% install_nx_console %}` - IDE extension installer
#### Content Enhancement
- `{% badge %}` - Status/label pills
- `{% metrics %}` - Metrics display
- `{% testimonial %}` - Customer testimonials
## Development Workflow
### Getting Started
```bash
# Install dependencies and link workspace packages
# This will build Nx packages as well for API docs
nx serve astro-docs
# Or run astro dev directly
# This will not build Nx packages
cd astro-docs
npx astro dev
# Custom ports (useful for AI agents with git worktrees)
npx astro dev --port 3000
```
### Adding New Content
#### Regular Documentation
1. Create `.mdoc` file in `src/content/docs/`
2. Add frontmatter with title and description
3. Use Markdoc tags for rich content
4. File location determines URL structure
Example:
```markdown
---
title: 'My New Guide'
description: 'Learn how to use this feature'
---
# Introduction
{% aside type="note" title="Important" %}
This is a note about the feature.
{% /aside %}
```
#### Adding Custom Markdoc Tags
1. Create Astro component in `src/components/markdoc/`
2. (Optional) Create React component for more complex components, or ones that need to be shared with blog or non-docs pages
3. Register in `markdoc.config.mjs`
4. Define attributes and validation
### Updating Plugin Documentation
Plugin documentation is auto-generated during build. To update:
1. Make changes to the plugin's schema/implementation
2. Run the build process
3. The loader will automatically fetch and generate updated docs
### Sidebar Management
The sidebar structure is defined in `sidebar.mts`. To add new sections:
```javascript
export const sidebar = [
{
label: 'Section Name',
items: [
{
label: 'Page Title',
link: 'path/to/page',
},
// Nested sections
{
label: 'Subsection',
collapsed: true,
items: [...]
}
]
}
];
```
> Note there is a special case for sidebar items appearing in the sidebar. Such as the `Reference` section which is handled via the `[sidebar-reference-updater](./src/plugins/sidebar-reference-updater.middleware.ts)` middleware.
## Styling and Theming
- Uses Tailwind CSS v4 with Vite plugin
- Global styles in `src/styles/global.css`
- Component-specific styles use Tailwind utilities
- Dark/light mode support built into Starlight and customized in `global.css`
## Configuration Files
### `astro.config.mjs`
- Site configuration
- Integration setup (React, Markdoc, Starlight)
- Vite plugins
- Build options
### `markdoc.config.mjs`
- Custom tag definitions
- Attribute validation
- Component mappings
### `sidebar.mts`
- Navigation structure
- Section organization
- Dynamic content injection points
-131
View File
@@ -1,131 +0,0 @@
// @ts-check
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
import netlify from '@astrojs/netlify';
import react from '@astrojs/react';
import markdoc from '@astrojs/markdoc';
import tailwindcss from '@tailwindcss/vite';
import { sidebar } from './sidebar.mts';
const BASE = '/docs';
const PUBLIC_CONFIG = {
cookiebotDisabled: process.env.COOKIEBOT_DISABLED === 'true',
cookiebotId: process.env.COOKIEBOT_ID ?? null,
gaMeasurementId: 'UA-88380372-10',
gtmMeasurementId: 'GTM-KW8423B6',
isProd: process.env.NODE_ENV === 'production',
};
// https://astro.build/config
export default defineConfig({
base: BASE,
vite: { plugins: [tailwindcss()] },
// Allow this to be configured per environment
// Note: this happens during build time so we don't use `import.meta.env`
site: process.env.NX_DEV_URL ?? 'https://nx.dev',
image: {
service: {
entrypoint: 'astro/assets/services/sharp',
config: {
limitInputPixels: false, // Disable pixel limit
},
},
},
trailingSlash: 'never',
// This adapter doesn't support local previews, so only load it on Netlify.
adapter: process.env['NETLIFY'] ? netlify() : undefined,
integrations: [
markdoc(),
// https://starlight.astro.build/reference/configuration/
starlight({
title: 'Nx',
tagline:
'Get to green PRs in half the time. Nx optimizes your builds, scales your CI, and fixes failed PRs. Built for developers and AI agents.',
customCss: ['./src/styles/global.css'],
favicon: '/favicon.svg',
logo: {
light: './src/assets/nx/Nx-dark.png',
dark: './src/assets/nx/Nx-light.png',
replacesTitle: true,
},
head: [
{
tag: 'script',
content: `window.__CONFIG = ${JSON.stringify(PUBLIC_CONFIG)};`,
},
...(process.env.COOKIEBOT_ID &&
process.env.COOKIEBOT_DISABLED !== 'true'
? [
{
/** @type {"script"} */
tag: 'script',
attrs: {
id: 'Cookiebot',
src: 'https://consent.cookiebot.com/uc.js',
'data-cbid': process.env.COOKIEBOT_ID,
'data-blockingmode': 'auto',
type: 'text/javascript',
},
},
]
: []),
{
tag: 'script',
attrs: {
src: `${BASE}/global-scripts.js`,
defer: true,
},
},
],
plugins: [],
routeMiddleware: [
'./src/plugins/banner.middleware.ts',
// NOTE: this is responsibile for populating the Reference section
// with generated routes from the nx-reference-packages content collection
// since the sidebar doesn't auto generate w/ dynamic routes from src/pages/reference
// only the src/content/docs/reference files
'./src/plugins/sidebar-reference-updater.middleware.ts',
'./src/plugins/sidebar-icons.middleware.ts',
'./src/plugins/og.middleware.ts',
],
markdown: {
// this breaks the renderMarkdown function in the plugin loader due to starlight path normalization
// as to _why_ it has to normalize a path?
// idk just working around the issue for now but we'll want to have linked headers so will need to fix
headingLinks: false,
},
social: [
{ icon: 'github', label: 'GitHub', href: 'https://github.com/nrwl/nx' },
{
icon: 'youtube',
label: 'YouTube',
href: 'https://www.youtube.com/@NxDevtools?utm_source=nx.dev',
},
{
icon: 'x.com',
label: 'X',
href: 'https://x.com/NxDevTools?utm_source=nx.dev',
},
{
icon: 'discord',
label: 'Discord',
href: 'https://go.nx.dev/community',
},
],
editLink: {
baseUrl: 'https://github.com/nrwl/nx/tree/main/',
},
sidebar,
components: {
Header: './src/components/layout/Header.astro',
Footer: './src/components/layout/Footer.astro',
PageFrame: './src/components/layout/PageFrame.astro',
Sidebar: './src/components/layout/Sidebar.astro',
TwoColumnContent: './src/components/layout/TwoColumnContent.astro',
PageTitle: './src/components/layout/PageTitle.astro',
},
}),
react(),
],
});
@@ -1,45 +0,0 @@
import { test, expect } from '@playwright/test';
test('links in descriptions of properties should correctly link to the same page w/ url fragments', async ({
page,
}) => {
await page.goto('/docs/reference/devkit/NxJsonConfiguration');
await expect(
page.getByRole('heading', { name: 'NxJsonConfiguration' })
).toBeVisible();
await page
.getByTestId('main-pane')
.getByRole('link', { name: 'nxCloudAccessToken' })
.click();
await expect(
page.getByRole('heading', { name: 'nxCloudAccessToken' })
).toBeVisible();
const description = page
.getByRole('paragraph')
.filter({ has: page.getByRole('link', { name: 'tasksRunnerOptions' }) })
.first();
await expect(description).toBeVisible();
const linkedProperty = description.getByRole('link', {
name: 'tasksRunnerOptions',
});
await expect(linkedProperty).toBeVisible();
await expect(linkedProperty).toHaveAttribute(
'href',
'/docs/reference/devkit/NxJsonConfiguration#tasksrunneroptions'
);
await linkedProperty.click();
expect(page.url()).toContain('#tasksrunneroptions');
await expect(
page.getByRole('heading', { name: 'tasksRunnerOptions' })
).toBeVisible();
});
-129
View File
@@ -1,129 +0,0 @@
#!/usr/bin/env bash
# | xargs -0 sed -i '' 's/<match>/<replace>/g'
# replace links that start with /concepts to /docs/concepts
rg "\(/concepts" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/concepts|](/docs/concepts|g'
# usage in link card aka href="/concepts/..."
rg "=\"/concepts" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/concepts|="/docs/concepts|g'
# /recipes -> /docs/guides
rg "\(/recipes" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/recipes|](/docs/guides|g'
rg "=\"/recipes" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/recipes|="/docs/guides|g'
# /deprecated -> /docs/reference/deprecated
rg "\(/deprecated" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/deprecated|](/docs/reference/deprecated|g'
rg "=\"/deprecated" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/deprecated|="/docs/reference/deprecated|g'
# /troubleshooting -> /docs/troublshooting
rg "\(/troubleshooting" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/troubleshooting|](/docs/troubleshooting|g'
rg "=\"/troubleshooting" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/troubleshooting|="/docs/troubleshooting|g'
# /plugin-registry -> /docs/plugin-registry
rg "\(/plugin-registry" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/plugin-registry|](/docs/plugin-registry|g'
rg "=\"/plugin-registry" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/plugin-registry|="/docs/plugin-registry|g'
# /features -> /docs/features
rg "\(/features" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/features|](/docs/features|g'
rg "=\"/features" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/features|="/docs/features|g'
# /extending-nx -> /docs/extending-nx
rg "\(/extending-nx" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/extending-nx|](/docs/extending-nx|g'
rg "=\"/extending-nx" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/extending-nx|="/docs/extending-nx|g'
rg "/extending-nx/recipes" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|/extending-nx/recipes|/extending-nx|g'
# /tech -> /docs/tech
rg "\(/tech" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/tech|](/docs/tech|g'
rg "=\"/tech" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/tech|="/docs/tech|g'
## /recipes/running-tasks -> /docs/guides/tasks--caching
rg "\(/recipes/running-tasks" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/recipes/running-tasks|](/docs/guides/tasks--caching|g'
rg "=\"/recipes/running-tasks" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/recipes/running-tasks|="/docs/guides/tasks--caching|g'
# /ci/features -> /docs/features/ci-features
rg "\(/ci/features" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/ci/features|](/docs/features/ci-features|g'
rg "=\"/ci/features" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/ci/features|="/docs/features/ci-features|g'
# /ci/concepts -> /docs/concepts/ci-concepts
rg "\(/ci/concepts" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/ci/concepts|](/docs/concepts/ci-concepts|g'
rg "=\"/ci/concepts" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/ci/concepts|="/docs/concepts/ci-concepts|g'
# /ci/guides/security -> /docs/guides/nx-cloud
rg "\(/ci/guides/security" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/ci/guides/security|](/docs/guides/nx-cloud|g'
rg "=\"/ci/guides/security" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/ci/guides/security|="/docs/guides/nx-cloud|g'
rg "\(/ci/recipes/security" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/ci/recipes/security|](/docs/guides/nx-cloud|g'
rg "=\"/ci/recipes/security" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/ci/recipes/security|="/docs/guides/nx-cloud|g'
# /ci/recipes/enterprise -> /docs/enterprise
rg "\(/ci/recipes/enterprise" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/ci/recipes/enterprise|](/docs/enterprise|g'
rg "=\"/ci/recipes/enterprise" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/ci/recipes/enterprise|="/docs/enterprise|g'
# /ci/recipes -> /docs/guides/nx-cloud
rg "\(/ci/guides" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/ci/guides|](/docs/guides/nx-cloud|g'
rg "=\"/ci/guides" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/ci/guides|="/docs/guides/nx-cloud|g'
rg "\(/ci/recipes" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/ci/recipes|](/docs/guides/nx-cloud|g'
rg "=\"/ci/recipes" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/ci/recipes|="/docs/guides/nx-cloud|g'
# /getting-started -> /docs/getting-started
rg "\(/getting" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/getting|](/docs/getting|g'
rg "=\"/getting" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/getting|="/docs/getting|g'
# /ci/recipes/set-up -> /docs/guides/nx-cloud/setup-ci
rg "\(/ci/recipes/set-up" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/ci/recipes/set-up|](/docs/guides/nx-cloud/setup-ci|g'
rg "=\"/ci/recipes/set-up" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/ci/recipes/set-up|="/docs/guides/nx-cloud/setup-ci|g'
# I merged all the set-up ci guides into 1 page with tabs so we need to remove any links that go to specific guides
rg "/monorepo-ci-" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|\(/[^)]*\)/monorepo-ci-[^)]*\()\)|\1\2|g'
# /ci/reference/nx-cloud-cli -> /docs/reference/nx-cloud-cli
rg "\(/ci/reference/nx-cloud-cli" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/ci/reference/nx-cloud-cli|](/docs/reference/nx-cloud-cli|g'
rg "=\"/ci/reference/nx-cloud-cli" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/ci/reference/nx-cloud-cli|="/docs/reference/nx-cloud-cli|g'
# /blog -> https://nx.dev/blog
rg "\(/blog" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/blog|](https://nx.dev/blog|g'
rg "=\"/blog" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/blog|="https://nx.dev/blog|g'
# /enterprise -> https://nx.dev/enterprise
rg "\(/enterprise" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/enterprise|](https://nx.dev/enterprise|g'
rg "=\"/enterprise" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/enterprise|="https://nx.dev/enterprise|g'
# /pricing -> https://nx.dev/pricing
rg "\(/pricing" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/pricing|](https://nx.dev/pricing|g'
rg "=\"/pricing" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/pricing|="https://nx.dev/pricing|g'
# /contact -> https://nx.dev/contact
rg "\(/contact" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/contact|](https://nx.dev/contact|g'
rg "=\"/contact" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/contact|="https://nx.dev/contact|g'
# /nx-cloud -> https://nx.dev/nx-cloud
rg "\(/nx-cloud" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/nx-cloud|](https://nx.dev/nx-cloud|g'
rg "=\"/nx-cloud" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/nx-cloud|="https://nx.dev/nx-cloud|g'
# /courses -> https://nx.dev/courses
rg "\(/courses" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/courses|](https://nx.dev/courses|g'
rg "=\"/courses" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/courses|="https://nx.dev/courses|g'
# /community -> https://nx.dev/community
rg "\(/community" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/community|](https://nx.dev/community|g'
rg "=\"/community" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/community|="https://nx.dev/community|g'
# though these URLS that have `core-api` in them need to be special handled
# but we can search for 'core-api' later and do a different replace mechinism
# /reference -> /docs/reference
rg "\(/reference" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/reference|](/docs/reference|g'
rg "=\"/reference" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/reference|="/docs/reference|g'
# /docs/reference/core-api/nx/documents/:command -> /docs/reference/nx-commands#:command
rg "\(/docs/reference/core-api/nx/documents/" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|](/docs/reference/core-api/nx/documents/|](/docs/reference/nx-commands#|g'
rg "=\"/docs/reference/core-api/nx/documents/" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|="/docs/reference/core-api/nx/documents/|="/docs/reference/nx-commands#|g'
# /docs/reference/core-api/:remote-cache-plugin/overview -> /docs/reference/remote-cache-plugins/:remote-cache-plugin/overview
# For s3-cache
rg "/docs/reference/core-api/s3-cache" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|/docs/reference/core-api/s3-cache|/docs/reference/remote-cache-plugins/s3-cache|g'
# For azure-cache
rg "/docs/reference/core-api/azure-cache" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|/docs/reference/core-api/azure-cache|/docs/reference/remote-cache-plugins/azure-cache|g'
# For gcs-cache
rg "/docs/reference/core-api/gcs-cache" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|/docs/reference/core-api/gcs-cache|/docs/reference/remote-cache-plugins/gcs-cache|g'
# For shared-fs-cache
rg "/docs/reference/core-api/shared-fs-cache" --type-add "mdoc:*mdoc" -t mdoc -l --null | xargs -0 sed -i '' 's|/docs/reference/core-api/shared-fs-cache|/docs/reference/remote-cache-plugins/shared-fs-cache|g'
-35
View File
@@ -1,35 +0,0 @@
const url = 'http://localhost:4321/docs';
const timeout = 120000; // 2 minutes in milliseconds
console.log('starting up....');
export default async function globalSetup() {
const startTime = Date.now();
const maxEndTime = startTime + timeout;
console.log(`Waiting for ${url} to be available...`);
while (Date.now() < maxEndTime) {
try {
const response = await fetch(url);
if (response.ok) {
console.log(`✓ Server is ready at ${url}`);
return;
}
console.log(
`Server responded with status ${response.status}, retrying...`
);
} catch (error) {
// Server not available yet, continue polling
const remainingTime = Math.round((maxEndTime - Date.now()) / 1000);
if (remainingTime % 10 === 0 && remainingTime > 0) {
console.log(`Still waiting... ${remainingTime} seconds remaining`);
}
}
await new Promise((resolve) => setTimeout(resolve, 1000));
}
throw new Error(
`Server at ${url} did not become available within ${timeout / 1000} seconds`
);
}
-397
View File
@@ -1,397 +0,0 @@
import { defineMarkdocConfig, component } from '@astrojs/markdoc/config';
import starlightMarkdoc from '@astrojs/starlight-markdoc';
export default defineMarkdocConfig({
extends: [starlightMarkdoc()],
tags: {
call_to_action: {
render: component('./src/components/markdoc/CallToAction.astro'),
attributes: {
url: {
type: 'String',
required: true,
},
title: {
type: 'String',
required: true,
},
description: {
type: 'String',
required: false,
},
icon: {
type: 'String',
required: false,
},
variant: {
type: 'String',
required: false,
default: 'default',
matches: [
'default',
'gradient',
'inverted',
'gradient-alt',
'simple',
],
},
size: {
type: 'String',
required: false,
default: 'sm',
matches: ['sm', 'md', 'lg'],
},
},
},
callout: {
render: component('./src/components/markdoc/Callout.astro'),
children: ['paragraph', 'tag', 'list'],
attributes: {
type: {
type: 'String',
default: 'note',
matches: [
'announcement',
'caution',
'check',
'note',
'warning',
'deepdive',
],
errorLevel: 'critical',
},
title: {
type: 'String',
required: true,
},
expanded: {
type: 'Boolean',
default: false,
},
},
},
card: {
render: component('./src/components/markdoc/Card.astro'),
attributes: {
title: {
type: 'String',
required: true,
},
description: {
type: 'String',
default: '',
},
type: {
type: 'String',
default: 'documentation',
},
url: {
type: 'String',
default: '',
},
},
},
cards: {
render: component('./src/components/markdoc/Cards.astro'),
attributes: {
cols: {
type: 'Number',
},
smCols: {
type: 'Number',
},
mdCols: {
type: 'Number',
},
lgCols: {
type: 'Number',
},
moreLink: {
type: 'String',
},
},
},
course_video: {
render: component('./src/components/markdoc/CourseVideo.astro'),
attributes: {
src: {
type: 'String',
required: true,
},
courseTitle: {
type: 'String',
required: true,
},
courseUrl: {
type: 'String',
required: true,
},
},
},
github_repository: {
render: component('./src/components/markdoc/GithubRepository.astro'),
attributes: {
url: {
type: 'String',
required: true,
},
title: {
type: 'String',
required: false,
},
},
},
graph: {
render: component('./src/components/markdoc/Graph.astro'),
children: [],
attributes: {
jsonFile: {
type: 'String',
},
title: {
type: 'String',
},
type: {
type: 'String',
matches: ['project', 'task'],
default: 'project',
},
height: {
type: 'String',
required: true,
},
},
},
iframe: {
render: component('./src/components/markdoc/Iframe.astro'),
attributes: {
src: {
type: 'String',
required: true,
},
title: {
type: 'String',
required: true,
},
width: {
type: 'String',
default: '50%',
},
},
},
install_nx_console: {
render: component('./src/components/markdoc/InstallNxConsole.astro'),
attributes: {},
},
link_card: {
render: component('./src/components/markdoc/LinkCard.astro'),
attributes: {
title: {
type: 'String',
required: true,
},
type: {
type: 'String',
required: true,
},
icon: {
type: 'String',
required: false,
},
url: {
type: 'String',
default: '',
},
appearance: {
type: 'String',
default: 'default',
},
},
},
index_page_cards: {
render: component('./src/components/markdoc/IndexPageCards.astro'),
attributes: {
path: {
type: 'String',
required: true,
},
},
},
metrics: {
render: component('./src/components/markdoc/Metrics.astro'),
attributes: {
metrics: {
type: 'Array',
required: true,
},
},
},
persona: {
render: component('./src/components/markdoc/Persona.astro'),
children: ['paragraph', 'tag', 'list'],
attributes: {
title: {
type: 'String',
},
type: {
type: 'String',
default: 'integrated',
required: true,
matches: [
'cache',
'distribute',
'javascript',
'lerna',
'react',
'angular',
'integrated',
],
errorLevel: 'critical',
},
url: {
type: 'String',
required: true,
errorLevel: 'critical',
},
},
},
personas: {
render: component('./src/components/markdoc/Personas.astro'),
},
pill: {
render: component('./src/components/markdoc/Pill.astro'),
attributes: {
url: {
type: 'String',
default: '',
},
},
},
project_details: {
render: component('./src/components/markdoc/ProjectDetails.astro'),
children: [],
attributes: {
jsonFile: {
type: 'String',
},
title: {
type: 'String',
},
height: {
type: 'String',
},
expandedTargets: {
type: 'Array',
},
},
},
stackblitz_button: {
render: component('./src/components/markdoc/StackblitzButton.astro'),
attributes: {
url: {
type: 'String',
required: true,
},
title: {
type: 'String',
required: false,
},
},
},
testimonial: {
render: component('./src/components/markdoc/Testimonial.astro'),
children: ['paragraph'],
attributes: {
name: {
type: 'String',
},
title: {
type: 'String',
},
image: {
type: 'String',
},
},
},
video_link: {
render: component('./src/components/markdoc/VideoLink.astro'),
attributes: {
link: {
type: 'String',
required: true,
},
text: {
type: 'String',
required: false,
},
},
},
video_player: {
render: component('./src/components/markdoc/VideoPlayer.astro'),
attributes: {
src: {
type: 'String',
required: true,
},
alt: {
type: 'String',
required: false,
},
link: {
type: 'String',
required: false,
},
showDescription: {
type: 'Boolean',
required: false,
default: false,
},
showControls: {
type: 'Boolean',
required: false,
default: false,
},
autoPlay: {
type: 'Boolean',
required: false,
default: false,
},
loop: {
type: 'Boolean',
required: false,
default: false,
},
},
},
youtube: {
render: component('./src/components/markdoc/Youtube.astro'),
attributes: {
src: {
type: 'String',
required: true,
},
title: {
type: 'String',
required: true,
},
width: {
type: 'String',
default: '100%',
},
caption: {
type: 'String',
required: false,
},
},
},
side_by_side: {
render: component('./src/components/markdoc/SideBySide.astro'),
attributes: {
align: {
type: 'String',
default: 'center',
},
},
},
},
});

Some files were not shown because too many files have changed in this diff Show More