Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Changesets

Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)

We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
29 changes: 29 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"$schema": "https://unpkg.com/@changesets/[email protected]/schema.json",
"changelog": ["@changesets/changelog-github", { "repo": "likec4/likec4" }],
"commit": false,
"fixed": [
[
"@likec4/config",
"@likec4/core",
"@likec4/diagram",
"@likec4/generators",
"@likec4/language-server",
"@likec4/layouts",
"likec4",
"@likec4/log",
"@likec4/mcp",
"likec4-vscode",
"@likec4/vscode-preview",
"@likec4/style-preset",
"@likec4/styles"
]
],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": [
"create-likec4"
]
}
6 changes: 6 additions & 0 deletions .changeset/dark-turtles-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@likec4/core": patch
"@likec4/language-server": patch
---

Deployment nodes name is wrong derived from instanceOf, fixes #2387
96 changes: 96 additions & 0 deletions .github/actions/bot-token/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
name: bot-token
description: Create a GitHub App token (and optionally configure git author)

inputs:
app-id:
required: true
description: GitHub App ID
private-key-base64:
required: true
description: Base64 encoded GitHub App private key
owner:
required: false
description: Owner for the GitHub App token
fetch-user-id:
required: false
default: "true"
description: Whether to fetch the bot user id via GitHub API
configure-git:
required: false
default: "true"
description: Whether to configure git user.name and user.email

outputs:
token:
description: GitHub App installation token
value: ${{ steps.token.outputs.token }}
app-slug:
description: GitHub App slug
value: ${{ steps.token.outputs.app-slug }}
user-id:
description: GitHub user id for the GitHub App bot user
value: ${{ steps.get-user-id.outputs.user-id }}
bot-name:
description: Git author name configured for the bot
value: ${{ steps.bot.outputs.name }}
bot-email:
description: Git author email configured for the bot
value: ${{ steps.bot.outputs.email }}

runs:
using: "composite"
steps:
- name: Decode the GitHub App Private Key
id: decode
shell: bash
run: |
private_key=$(echo "${{ inputs.private-key-base64 }}" | base64 -d | awk 'BEGIN {ORS="\\n"} {print}' | head -c -2) &> /dev/null
echo "::add-mask::$private_key"
echo "private-key=$private_key" >> "$GITHUB_OUTPUT"

- uses: actions/create-github-app-token@v2
id: app-token-default
if: ${{ inputs.owner == '' }}
with:
app-id: ${{ inputs.app-id }}
private-key: ${{ steps.decode.outputs.private-key }}

- uses: actions/create-github-app-token@v2
id: app-token-owner
if: ${{ inputs.owner != '' }}
with:
app-id: ${{ inputs.app-id }}
private-key: ${{ steps.decode.outputs.private-key }}
owner: ${{ inputs.owner }}

- name: Collect token outputs
id: token
shell: bash
run: |
echo "token=${{ steps.app-token-owner.outputs.token || steps.app-token-default.outputs.token }}" >> "$GITHUB_OUTPUT"
echo "app-slug=${{ steps.app-token-owner.outputs.app-slug || steps.app-token-default.outputs.app-slug }}" >> "$GITHUB_OUTPUT"

- name: Get GitHub App User ID
id: get-user-id
if: ${{ inputs.fetch-user-id == 'true' }}
shell: bash
run: echo "user-id=$(gh api \"/users/${{ steps.token.outputs.app-slug }}[bot]\" --jq .id)" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ steps.token.outputs.token }}

- name: Resolve bot identity
id: bot
if: ${{ inputs.fetch-user-id == 'true' }}
shell: bash
run: |
bot_name='${{ steps.token.outputs.app-slug }}[bot]'
bot_email='${{ steps.get-user-id.outputs.user-id }}+${{ steps.token.outputs.app-slug }}[bot]@users.noreply.github.com'
echo "name=$bot_name" >> "$GITHUB_OUTPUT"
echo "email=$bot_email" >> "$GITHUB_OUTPUT"

- name: Configure git identity
if: ${{ inputs.configure-git == 'true' && inputs.fetch-user-id == 'true' }}
shell: bash
run: |
git config --global user.name '${{ steps.bot.outputs.name }}'
git config --global user.email '${{ steps.bot.outputs.email }}'
85 changes: 39 additions & 46 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,10 @@ LikeC4 is an architecture-as-code tool for visualizing software architecture. It

**Tech Stack**: TypeScript monorepo using pnpm workspaces, Turbo for build orchestration, React for UI, Langium for language parsing, Vite for bundling.
**Size**: ~20 packages across 1,686 dependencies. Main packages: `likec4` (CLI/Vite plugin), `@likec4/core` (model builder), `@likec4/language-server` (Langium-based parser), `@likec4/diagram` (React/ReactFlow renderer), `@likec4/vscode` (VSCode extension).
**Node Requirements**: Node.js ^20.19.0 or >=22.18.0, pnpm 10.19.0 (.tool-versions specifies 22.19.0)
**Node Requirements**: Node.js 22.21.1, pnpm 10.26.0 (see .tool-versions for correct versions)

## Build & Validation Commands

### Environment Setup (CRITICAL - DO THIS FIRST)
```bash
# Install correct pnpm version BEFORE running any other commands
npm install -g [email protected]

# Install dependencies with specific environment variables to avoid husky issues
HUSKY=0 NODE_ENV=development pnpm install --prefer-offline
```

**IMPORTANT**: Always set `HUSKY=0` and `NODE_ENV=development` when installing dependencies to prevent husky pre-commit hook setup issues.

### Build Workflow (ALWAYS follow this order)

1. **Generate sources first** (before any other build command):
Expand All @@ -31,25 +20,24 @@ HUSKY=0 NODE_ENV=development pnpm install --prefer-offline

2. **Build packages**:
```bash
pnpm ci:build # Production build, excludes docs (~3-4 minutes)
pnpm build # Same as ci:build (common alias)
pnpm build # Build all, except docs
```

3. **Type checking**:
```bash
pnpm ci:typecheck # Type check all except docs (~1.5 minutes)
pnpm typecheck # Type check all, except docs
```

4. **Run tests**:
```bash
NODE_ENV=test pnpm ci:test # Run all unit tests (~1 minute)
pnpm test # Run all unit tests (~1 minute)
```

5. **Linting**:
```bash
pnpm ci:lint # Uses oxlint with type-aware rules
pnpm lint:fix # Auto-fix lint issues
pnpm fmt # Format code with dprint
pnpm lint # Uses oxlint with type-aware rules
pnpm lint:fix # Auto-fix lint issues
pnpm fmt # Format code with dprint
```

### Clean & Rebuild (When Things Go Wrong)
Expand Down Expand Up @@ -80,13 +68,13 @@ pnpm build

```bash
# From root - builds tarballs, installs in isolated workspace, runs Playwright tests (~10 minutes)
pnpm pretest:e2e # Packs likec4 and core packages
pnpm test:e2e # Runs e2e tests in isolated environment
```

## Project Structure & Key Locations

### Repository Layout

```
/
├── packages/
Expand All @@ -109,6 +97,7 @@ pnpm test:e2e # Runs e2e tests in isolated environment
```

### Configuration Files (Root)

- `turbo.json` - Turbo build orchestration, defines task dependencies
- `pnpm-workspace.yaml` - Workspace packages and dependency catalog
- `tsconfig.json` - TypeScript project references (for IDE/task runner)
Expand All @@ -118,6 +107,7 @@ pnpm test:e2e # Runs e2e tests in isolated environment
- `.tool-versions` - Required versions for Node, pnpm, dprint

### Build Outputs (Gitignored)

- `packages/*/lib/` - TypeScript build outputs
- `packages/*/dist/` - Bundled outputs
- `packages/language-server/src/generated/` - Langium-generated parser
Expand All @@ -126,6 +116,7 @@ pnpm test:e2e # Runs e2e tests in isolated environment
- `**/.tsbuildinfo` - TypeScript incremental build cache

### Test File Locations

- Unit tests: `packages/*/src/**/*.spec.ts`, `packages/*/src/**/__test__/*.spec.ts`
- E2E tests: `e2e/tests/*.spec.ts`, `e2e/src/*.spec.ts`

Expand All @@ -134,16 +125,18 @@ pnpm test:e2e # Runs e2e tests in isolated environment
### Main Workflows (`.github/workflows/`)

**checks.yaml** (runs on PRs):

1. `check-types`: TypeScript type checking (`pnpm ci:typecheck`)
2. `check-lint`: Linting (`pnpm ci:lint`)
3. `check-build`: Build all packages, pack tarballs, run `pnpm lint:package`
3. `check-build`: Build all packages, pack tarballs
4. `check-tests`: Run unit tests (`pnpm ci:test`)
5. `check-on-windows`: Windows compatibility build and test
6. `check-e2e-tests`: E2E tests using built tarballs
7. `check-e2e-types`: Type check E2E generated types
8. `check-docs-astro`: Build documentation site

**Bootstrap Action** (`.github/actions/bootstrap/action.yml`):

```yaml
- Setup pnpm with NODE_ENV=development
- Setup Node from .tool-versions
Expand All @@ -168,18 +161,24 @@ pnpm test:e2e # Runs E2E tests
## Common Gotchas & Workarounds

### TypeScript Project References

The repo uses TypeScript project references for faster incremental builds. If you see errors like "Output file 'X' has not been built from source file 'Y'":

1. Run `pnpm generate` to regenerate all source files
2. If that doesn't work, run `pnpm clean:lib` then `pnpm generate && pnpm typecheck`

### Turbo Cache Issues

Turbo caches build outputs. If you suspect stale cache:

```bash
pnpm clean # Cleans turbo caches and build outputs
```

### Generated Files

Several packages have auto-generated files that MUST be generated before building:

- `packages/language-server/src/generated/` - Langium parser (from grammar)
- `packages/vscode/src/meta.ts` - VSCode extension metadata
- `packages/likec4/app/src/routeTree.gen.ts` - TanStack Router routes
Expand All @@ -188,47 +187,41 @@ Several packages have auto-generated files that MUST be generated before buildin
Always run `pnpm generate` after checkout or when these files are missing.

### Formatting

Use `pnpm fmt` to format code with dprint. The project does NOT use Prettier or eslint for formatting.

### Icons Package
The `packages/icons/` package generates icon bundles. During `pnpm clean`, icon files are deleted and regenerated from source. This is expected behavior.

The `packages/icons/` package contains icon bundles. Maintained by scripts in `packages/icons/scripts/`:
You don't need to do anything with this package.

### Husky Hooks

Pre-commit hooks run `nano-staged` to format staged files. If you need to bypass:

```bash
git commit --no-verify
```

## Development Workflows

### Working on VSCode Extension
```bash
cd packages/vscode
pnpm dev # Watches for changes in dependencies
# Then launch "Run Extension" in VSCode (F5)
```
### Common Tasks

### Working on Playground
```bash
cd apps/playground
pnpm dev # Starts dev server with hot reload
```
All packages have the same tasks. For example:

### Working on Core/Language Server
```bash
# Make changes, then run tests
pnpm test # Run all tests
pnpm test:watch # Watch mode
pnpm vitest:ui # Visual test UI (from root)
cd packages/language-server
pnpm generate # Generate source files
pnpm typecheck # Type check package
pnpm build # Build package
pnpm test # Run tests
```

### Adding New Dependencies
When adding dependencies to any package, check if a catalog version exists in `pnpm-workspace.yaml`. Use catalog versions when available for consistency.
Turbo handles task orchestration.
Commands like `pnpm generate` or `pnpm build` run tasks across packages in dependency order.
Before running `typecheck` or `test`, always run `generate` first.

## Final Notes
### Adding New Dependencies

- **Trust these instructions**: Only search for additional information if these instructions are incomplete or found to be incorrect.
- **Always run `pnpm generate` first** when starting work or after cleaning.
- **Use `NODE_ENV=development`** for install and dev, `NODE_ENV=production` or `NODE_ENV=test` for CI commands.
- **Turbo handles task orchestration**: Commands like `pnpm build` run tasks across packages in dependency order.
- **Check `.gitignore`** before committing to avoid committing build artifacts, especially `lib/`, `dist/`, `.turbo/`, and generated files.
When adding dependencies to any package, check if a catalog version exists in `pnpm-workspace.yaml`.
Use catalog versions when available for consistency.
33 changes: 9 additions & 24 deletions .github/workflows/e2e-update-screenshots.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,17 @@ jobs:
timeout-minutes: 15
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v6
with:
ssh-strict: "no"

- name: Decode the GitHub App Private Key
id: decode
run: |
private_key=$(echo "${{ secrets.BOT_APP_PRIVATE_KEY }}" | base64 -d | awk 'BEGIN {ORS="\\n"} {print}' | head -c -2) &> /dev/null
echo "::add-mask::$private_key"
echo "private-key=$private_key" >> "$GITHUB_OUTPUT"

- uses: actions/create-github-app-token@v2
id: app-token
- name: bot token
id: bot-token
uses: ./.github/actions/bot-token
with:
app-id: ${{ secrets.BOT_APP_ID }}
private-key: ${{ steps.decode.outputs.private-key }}
private-key-base64: ${{ secrets.BOT_APP_PRIVATE_KEY }}

- name: Get GitHub App User ID
id: get-user-id
run: echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}

- run: |
git config --global user.name '${{ steps.app-token.outputs.app-slug }}[bot]'
git config --global user.email '${{ steps.get-user-id.outputs.user-id }}+${{ steps.app-token.outputs.app-slug }}[bot]@users.noreply.github.com'
- uses: actions/checkout@v6
with:
token: ${{ steps.bot-token.outputs.token }}
ssh-strict: "no"

- name: 🛠️ bootstrap
uses: ./.github/actions/bootstrap
Expand All @@ -70,7 +55,7 @@ jobs:
id: cpr
uses: peter-evans/create-pull-request@v7
with:
token: ${{ steps.app-token.outputs.token }}
token: ${{ steps.bot-token.outputs.token }}
commit-message: "chore: update e2e screenshots"
title: "chore: update e2e screenshots"
branch: update-screenshots/${{ github.ref_name }}
Expand Down
Loading
Loading