Skip to content
Open
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
63 changes: 63 additions & 0 deletions .claude/commands/release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Release Workflow

Creates a new release by triggering the GitHub Actions release-dispatch workflow.

## Arguments

- `$ARGUMENTS`: Version type or specific version (e.g., `minor`, `patch`, `major`, or `0.12.0`)

## Process

1. **Determine the new version**:

```bash
# Get current version from controller package
CURRENT_VERSION=$(jq -r '.version' packages/controller/package.json)
echo "Current version: $CURRENT_VERSION"
```

Based on the argument:
- `major`: Bump major version (e.g., 0.11.4 -> 1.0.0)
- `minor`: Bump minor version (e.g., 0.11.4 -> 0.12.0)
- `patch`: Bump patch version (e.g., 0.11.4 -> 0.11.5)
- Specific version (e.g., `0.12.0`): Use as-is

2. **Trigger the release workflow**:

```bash
# Trigger release-dispatch workflow
gh workflow run release-dispatch.yml \
--field version=<NEW_VERSION> \
--field tag=latest
```

For prerelease versions (containing `-alpha`, `-beta`, `-rc`):

```bash
gh workflow run release-dispatch.yml \
--field version=<NEW_VERSION> \
--field tag=prerelease
```

3. **Verify workflow started**:

```bash
# List recent workflow runs
gh run list --workflow=release-dispatch.yml --limit=3
```

4. **Provide next steps**:

After triggering, inform the user:
- A PR titled "Prepare release: X.Y.Z" will be created from branch `prepare-release`
- A draft GitHub release will be created with tag `vX.Y.Z`
- Once the PR is merged, packages will be published to npm automatically
- The draft release will be finalized with changelog notes

## Version calculation

Use semver rules to calculate the new version:
- Strip any prerelease suffix (e.g., `-alpha.1`) before bumping
- For `major`: Set to `<major+1>.0.0`
- For `minor`: Set to `<major>.<minor+1>.0`
- For `patch`: Set to `<major>.<minor>.<patch+1>`
23 changes: 23 additions & 0 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,42 @@
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: dorny/paths-filter@v3

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'quality' step
Uses Step: changes
uses 'dorny/paths-filter' with ref 'v3', not a pinned commit hash
id: changes
with:
filters: |
code:
- '**/*.ts'
- '**/*.tsx'
- '**/*.js'
- '**/*.jsx'
- '**/*.json'
- '!**/package.json'

- name: Skip for version-only changes
if: steps.changes.outputs.code != 'true'
run: echo "Only version changes detected, skipping lint"

- uses: actions/setup-node@v4
if: steps.changes.outputs.code == 'true'
with:
node-version: 20.x
- uses: actions/cache@v4
if: steps.changes.outputs.code == 'true'
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-
- run: corepack enable pnpm
if: steps.changes.outputs.code == 'true'
- uses: pnpm/action-setup@v4
if: steps.changes.outputs.code == 'true'
id: pnpm-install
with:
run_install: false
- run: pnpm install --frozen-lockfile
if: steps.changes.outputs.code == 'true'
- run: pnpm lint:check
if: steps.changes.outputs.code == 'true'
45 changes: 41 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,50 @@
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: dorny/paths-filter@v3

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium test

Unpinned 3rd party Action 'test' step
Uses Step: changes
uses 'dorny/paths-filter' with ref 'v3', not a pinned commit hash
id: changes
with:
filters: |
code:
- '**/*.ts'
- '**/*.tsx'
- '**/*.js'
- '**/*.jsx'
- '!**/package.json'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent JSON path filter across workflow files

The code filter in quality.yml includes **/*.json (excluding package.json), but the code filter in test.yml omits JSON files entirely. This means changes to configuration files like tsconfig.json will trigger linting but skip tests. If a TypeScript config change breaks compilation, it won't be caught until a subsequent PR modifies TypeScript source files.

Additional Locations (1)

Fix in Cursor Fix in Web

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dependency-only updates skip all CI checks

The code path filters don't include pnpm-lock.yaml or other lock files. When a dependency update PR changes only package.json (excluded) and pnpm-lock.yaml (not in filter), code evaluates to false and all tests and linting are skipped. This means Renovate/Dependabot PRs with breaking dependency changes could merge without running any CI checks. Before this change, tests always ran regardless of which files changed.

Additional Locations (1)

Fix in Cursor Fix in Web


- name: Skip for version-only changes
if: steps.changes.outputs.code != 'true'
run: echo "Only version changes detected, skipping tests"

- uses: actions/setup-node@v4
if: steps.changes.outputs.code == 'true'
with:
node-version: 20.x
- uses: actions/cache@v4
if: steps.changes.outputs.code == 'true'
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-
- uses: pnpm/action-setup@v4
if: steps.changes.outputs.code == 'true'
with:
run_install: |
- args: [--frozen-lockfile]
- name: Clean iframe dist directory
if: steps.changes.outputs.code == 'true'
run: rm -rf packages/controller/dist
- run: pnpm build
if: steps.changes.outputs.code == 'true'
- name: Run tests with coverage
if: steps.changes.outputs.code == 'true'
run: pnpm test:ci --coverage
env:
NODE_OPTIONS: --max-old-space-size=16384
- uses: codecov/codecov-action@v3
if: steps.changes.outputs.code == 'true'
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: coverage/lcov.info
Expand Down Expand Up @@ -72,10 +95,20 @@
ui:
- '.github/workflows/test.yml'
- 'packages/keychain/**'
- '**/package.json'
- '**/pnpm-lock.yaml'

- if: steps.changes.outputs.ui == 'true'
code:
- '**/*.ts'
- '**/*.tsx'
- '**/*.js'
- '**/*.jsx'
- '**/*.css'
- '!**/package.json'

- name: Skip for version-only changes
if: steps.changes.outputs.code != 'true'
run: echo "Only version changes detected, skipping storybook tests"

- if: steps.changes.outputs.code == 'true' && steps.changes.outputs.ui == 'true'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cache step condition stricter than build steps

The cache step in the storybook job requires both code == 'true' && ui == 'true', but subsequent build and test steps (pnpm install, pnpm build, test:storybook:update) only require code == 'true'. When code changes occur outside the packages/keychain directory (code=true but ui=false), the storybook tests will run without the benefit of caching, resulting in slower CI runs. The cache condition likely needs to match the other steps by checking only code == 'true'.

Additional Locations (1)

Fix in Cursor Fix in Web

uses: actions/cache@v4
with:
path: |
Expand All @@ -89,12 +122,16 @@
${{ runner.os }}-storybook-

- run: pnpm i --frozen-lockfile
if: steps.changes.outputs.code == 'true'
- run: pnpm build
if: steps.changes.outputs.code == 'true'
- run: pnpm test:storybook:update
if: steps.changes.outputs.code == 'true'
id: test-storybook
continue-on-error: true

- name: Update and commit snapshots
if: steps.changes.outputs.code == 'true'
id: update-snapshots
run: |
# Check if there are any changes to commit
Expand Down Expand Up @@ -260,7 +297,7 @@

# Modify the final check step to handle different failure types
- name: Check for failures
if: always() # Run this step even if previous steps failed
if: always() && steps.changes.outputs.code == 'true'
run: |
echo "Test Storybook Outcome: ${{ steps.test-storybook.outcome }}"
echo "Snapshot Failed (changes detected in PR diff): ${{ env.snapshot_failed }}"
Expand Down
Loading