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
38 changes: 14 additions & 24 deletions .claude/skills/bump-coana/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
---
name: bump-coana
description: Bump @coana-tech/cli to a new version, update changelog, and create a PR. Use when user wants to upgrade Coana CLI, bump Coana version, or says "bump coana" with a version number.
description: Bump the pinned Coana CLI to a new version, update changelog, and create a PR. Use when user wants to upgrade Coana CLI, bump Coana version, or says "bump coana" with a version number.
allowed-tools: Read, Edit, Write, Bash, Glob
user-invocable: true
---

# Bump Coana CLI Version

Automates the process of upgrading the @coana-tech/cli dependency to a new version, including package.json updates, changelog entry, and PR creation.
Automates the process of upgrading the pinned Coana CLI to a new version, including the pin, changelog entry, and PR creation.

## Input

Expand All @@ -32,22 +32,21 @@ if [[ ! "$COANA_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
fi
```

### Step 2: Update package.json
### Step 2: Update the pin

1. Read `package.json` in the repository root.
2. Find the current `@coana-tech/cli` version in `devDependencies` and note it as `CURRENT_VERSION`.
3. Update `@coana-tech/cli` to the new version.
4. Write the updated `package.json`.
1. Read `src/constants.mts`.
2. Find the line `const COANA_CLI_VERSION = '<version>'` and note the version as `CURRENT_VERSION`.
3. Replace the version on that line with the new one.

🚨 **Do NOT touch the top-level `version` field.** The release workflow owns it:
🚨 **Do NOT touch `package.json`'s top-level `version` field.** The release workflow owns it:
between releases the manifest holds the last released version, and
`scripts/release/bump.mts` derives and writes the next one in-run. Hand-writing
it invents a version that never releases and breaks the next release — a manifest
already sitting on the version being released has no line for the bump to
advance.

**Values to extract**:
- `CURRENT_VERSION`: The old @coana-tech/cli version (for PR body)
- `CURRENT_VERSION`: The old Coana CLI version (for PR body)

### Step 3: Update CHANGELOG.md

Expand Down Expand Up @@ -87,28 +86,20 @@ if it finds one; hand-editing is what puts one there.)
- Updated the Coana CLI to v `COANA_VERSION`.
```

### Step 4: Update Lock File

```bash
pnpm install
```

This updates `pnpm-lock.yaml` with the new dependency version.

### Step 5: Create Branch and Commit
### Step 4: Create Branch and Commit

```bash
# Create branch
git checkout -b "coana-$COANA_VERSION"

# Stage changes
git add package.json CHANGELOG.md pnpm-lock.yaml
git add src/constants.mts CHANGELOG.md

# Commit (skip pre-commit hooks with -n)
git commit -n -m "upgrading coana to version $COANA_VERSION"
```

### Step 6: Push and Create PR
### Step 5: Push and Create PR

```bash
# Push branch
Expand All @@ -117,7 +108,7 @@ git push -u origin "coana-$COANA_VERSION"
# Create PR targeting v1.x branch
gh pr create --base v1.x --title "upgrading coana to version $COANA_VERSION" --body "$(cat <<'EOF'
## Summary
- Upgrades @coana-tech/cli from CURRENT_VERSION to COANA_VERSION
- Upgrades the Coana CLI from CURRENT_VERSION to COANA_VERSION

## Coana Changelog
For details on what's included in this Coana release, see the [Coana Changelogs](https://docs.coana.tech/changelogs).
Expand All @@ -131,16 +122,15 @@ Replace `CURRENT_VERSION` and `COANA_VERSION` with actual values.

- Branch: `coana-<VERSION>` pushed to origin
- PR: Created targeting `v1.x` branch
- Files modified: `package.json` (the `@coana-tech/cli` devDependency only, never
the top-level `version`), `CHANGELOG.md` (under `## [Unreleased]`), `pnpm-lock.yaml`
- Files modified: `src/constants.mts` (the `COANA_CLI_VERSION` line only),
`CHANGELOG.md` (under `## [Unreleased]`)

Report the PR URL to the user when complete.

## Error Handling

- **No version provided**: Ask user for the version number
- **Invalid version format**: Report error with expected format
- **pnpm install fails**: Check network connectivity and npm registry access
- **PR creation fails**: Verify `gh` CLI is authenticated

## Important Notes
Expand Down
8 changes: 0 additions & 8 deletions .config/rollup.base.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
} from '../scripts/utils/packages.js'

const {
INLINED_SOCKET_CLI_COANA_TECH_CLI_VERSION,
INLINED_SOCKET_CLI_CYCLONEDX_CDXGEN_VERSION,
INLINED_SOCKET_CLI_HOMEPAGE,
INLINED_SOCKET_CLI_LEGACY_BUILD,
Expand Down Expand Up @@ -192,13 +191,6 @@ export default function baseConfig(extendConfig = {}) {
delimiters: ['(?<![\'"])\\b', '(?![\'"])'],
preventAssignment: true,
values: [
[
INLINED_SOCKET_CLI_COANA_TECH_CLI_VERSION,
() =>
JSON.stringify(
getRootPkgJsonSync().devDependencies['@coana-tech/cli'],
),
],
[
INLINED_SOCKET_CLI_CYCLONEDX_CDXGEN_VERSION,
() =>
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@
"@babel/preset-typescript": "7.27.1",
"@babel/runtime": "7.28.4",
"@biomejs/biome": "2.2.4",
"@coana-tech/cli": "15.12.9",
"@cyclonedx/cdxgen": "12.1.2",
"@dotenvx/dotenvx": "1.49.0",
"@eslint/compat": "1.3.2",
Expand Down
9 changes: 0 additions & 9 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions scripts/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ const {
} = registryConstants

const CONSTANTS = 'constants'
const INLINED_SOCKET_CLI_COANA_TECH_CLI_VERSION =
'INLINED_SOCKET_CLI_COANA_TECH_CLI_VERSION'
const INLINED_SOCKET_CLI_CYCLONEDX_CDXGEN_VERSION =
'INLINED_SOCKET_CLI_CYCLONEDX_CDXGEN_VERSION'
const INLINED_SOCKET_CLI_HOMEPAGE = 'INLINED_SOCKET_CLI_HOMEPAGE'
Expand Down Expand Up @@ -99,7 +97,6 @@ const constants = createConstantsObject(
...registryConstantsAttribs.props,
CONSTANTS,
ENV: undefined,
INLINED_SOCKET_CLI_COANA_TECH_CLI_VERSION,
INLINED_SOCKET_CLI_CYCLONEDX_CDXGEN_VERSION,
INLINED_SOCKET_CLI_HOMEPAGE,
INLINED_SOCKET_CLI_LEGACY_BUILD,
Expand Down
3 changes: 2 additions & 1 deletion src/commands/fix/cmd-fix.mts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { logger } from '@socketsecurity/registry/lib/logger'

import { handleFix } from './handle-fix.mts'
import constants, {
COANA_CLI_VERSION,
ERROR_UNABLE_RESOLVE_ORG,
FLAG_ID,
} from '../../constants.mts'
Expand Down Expand Up @@ -73,7 +74,7 @@ const generalFlags: MeowFlags = {
},
fixVersion: {
type: 'string',
description: `Override the version of @coana-tech/cli used for fix analysis. Default: ${constants.ENV.INLINED_SOCKET_CLI_COANA_TECH_CLI_VERSION}.`,
description: `Override the version of @coana-tech/cli used for fix analysis. Default: ${COANA_CLI_VERSION}.`,
},
applyFixes: {
aliases: ['onlyCompute'],
Expand Down
6 changes: 2 additions & 4 deletions src/commands/scan/perform-reachability-analysis.mts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import path from 'node:path'
import { logger } from '@socketsecurity/registry/lib/logger'

import { isOmittedReachValue } from './reachability-units.mts'
import constants from '../../constants.mts'
import constants, { COANA_CLI_VERSION } from '../../constants.mts'
import { handleApiCall } from '../../utils/api.mts'
import {
extractTier1ReachabilityScanId,
Expand Down Expand Up @@ -303,9 +303,7 @@ export async function performReachabilityAnalysis(
}

if (!coanaResult.ok) {
const coanaVersion =
reachabilityOptions.reachVersion ||
constants.ENV.INLINED_SOCKET_CLI_COANA_TECH_CLI_VERSION
const coanaVersion = reachabilityOptions.reachVersion || COANA_CLI_VERSION
logger.error(
`Coana reachability analysis failed. Version: ${coanaVersion}, target: ${analysisTarget}, cwd: ${cwd}`,
)
Expand Down
2 changes: 1 addition & 1 deletion src/commands/scan/perform-reachability-analysis.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ vi.mock('../../utils/terminal-link.mts', () => ({
}))

vi.mock('../../constants.mts', () => ({
COANA_CLI_VERSION: 'test',
default: {
DOT_SOCKET_DOT_FACTS_JSON: '.socket.facts.json',
ENV: { INLINED_SOCKET_CLI_COANA_TECH_CLI_VERSION: 'test' },
HTTP_STATUS_UNAUTHORIZED: 401,
SOCKET_DEFAULT_BRANCH: 'socket-default-branch',
SOCKET_DEFAULT_REPOSITORY: 'socket-default-repository',
Expand Down
4 changes: 2 additions & 2 deletions src/commands/scan/reachability-flags.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import constants from '../../constants.mts'
import { COANA_CLI_VERSION } from '../../constants.mts'
import { getReachabilityEcosystemChoices } from '../../utils/ecosystem.mts'

import type { MeowFlags } from '../../flags.mts'
Expand All @@ -12,7 +12,7 @@ export const DYNAMIC_SBOM_INFERENCE_DESCRIPTION =
export const reachabilityFlags: MeowFlags = {
reachVersion: {
type: 'string',
description: `Override the version of @coana-tech/cli used for reachability analysis. Default: ${constants.ENV.INLINED_SOCKET_CLI_COANA_TECH_CLI_VERSION}.`,
description: `Override the version of @coana-tech/cli used for reachability analysis. Default: ${COANA_CLI_VERSION}.`,
},
reachAnalysisMemoryLimit: {
type: 'string',
Expand Down
10 changes: 4 additions & 6 deletions src/constants.mts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ export type ENV = Remap<
GITHUB_REPOSITORY: string
GITHUB_SERVER_URL: string
GITHUB_TOKEN: string
INLINED_SOCKET_CLI_COANA_TECH_CLI_VERSION: string
INLINED_SOCKET_CLI_CYCLONEDX_CDXGEN_VERSION: string
INLINED_SOCKET_CLI_HOMEPAGE: string
INLINED_SOCKET_CLI_LEGACY_BUILD: string
Expand Down Expand Up @@ -193,6 +192,9 @@ const ALERT_TYPE_CVE = 'cve'
const ALERT_TYPE_MEDIUM_CVE = 'mediumCVE'
const ALERT_TYPE_MILD_CVE = 'mildCVE'
const API_V0_URL = 'https://api.socket.dev/v0/'
// The Coana CLI version Socket CLI runs by default. Coana's release workflow
// rewrites this line in its bump PRs.
const COANA_CLI_VERSION = '15.12.9'
const CONFIG_KEY_API_BASE_URL = 'apiBaseUrl'
const CONFIG_KEY_API_PROXY = 'apiProxy'
const CONFIG_KEY_API_TOKEN = 'apiToken'
Expand Down Expand Up @@ -493,11 +495,6 @@ const LAZY_ENV = () => {
// workflow.
// https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication#about-the-github_token-secret
GITHUB_TOKEN,
// Comp-time inlined @coana-tech/cli package version.
// The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_COANA_TECH_CLI_VERSION']".
INLINED_SOCKET_CLI_COANA_TECH_CLI_VERSION: envAsString(
process.env['INLINED_SOCKET_CLI_COANA_TECH_CLI_VERSION'],
),
// Comp-time inlined @cyclonedx/cdxgen package version.
// The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_CYCLONEDX_CDXGEN_VERSION']".
INLINED_SOCKET_CLI_CYCLONEDX_CDXGEN_VERSION: envAsString(
Expand Down Expand Up @@ -1145,6 +1142,7 @@ export {
ALERT_TYPE_MEDIUM_CVE,
ALERT_TYPE_MILD_CVE,
API_V0_URL,
COANA_CLI_VERSION,
CONFIG_KEY_API_BASE_URL,
CONFIG_KEY_API_PROXY,
CONFIG_KEY_API_TOKEN,
Expand Down
4 changes: 2 additions & 2 deletions src/utils/dlx.mts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { spawn } from '@socketsecurity/registry/lib/spawn'

import { getDefaultOrgSlug } from '../commands/ci/fetch-default-org-slug.mts'
import constants, {
COANA_CLI_VERSION,
FLAG_QUIET,
FLAG_SILENT,
NPM,
Expand Down Expand Up @@ -470,8 +471,7 @@ export async function spawnCoanaDlx(
...spawnEnv,
}

const resolvedVersion =
coanaVersion || constants.ENV.INLINED_SOCKET_CLI_COANA_TECH_CLI_VERSION
const resolvedVersion = coanaVersion || COANA_CLI_VERSION

// `shadowNpmBase` (the dlx launcher) configures the child's stdio from its
// `options` arg, NOT from the registry-spawn `extra` arg — the latter only
Expand Down
20 changes: 6 additions & 14 deletions test/utils.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { readFileSync } from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'

Expand All @@ -7,19 +6,15 @@ import { it } from 'vitest'
import { SpawnOptions, spawn } from '@socketsecurity/registry/lib/spawn'
import { stripAnsi } from '@socketsecurity/registry/lib/strings'

import constants, { FLAG_HELP, FLAG_VERSION } from '../src/constants.mts'
import constants, {
COANA_CLI_VERSION,
FLAG_HELP,
FLAG_VERSION,
} from '../src/constants.mts'

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

// Read Coana version from package.json for test normalization.
// This is needed because constants.ENV.INLINED_SOCKET_CLI_COANA_TECH_CLI_VERSION
// is a compile-time value that's empty in the test environment.
const rootPackageJson = JSON.parse(
readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'),
) as { devDependencies: Record<string, string> }
const coanaVersion = rootPackageJson.devDependencies['@coana-tech/cli'] ?? ''

// The asciiUnsafeRegexp match characters that are:
// * Control characters in the Unicode range:
// - \u0000 to \u0007 (e.g., NUL, BEL)
Expand Down Expand Up @@ -57,10 +52,7 @@ function stripZeroWidthSpace(str: string): string {

// Normalize Coana version to a placeholder for stable snapshots.
function normalizeCoanaVersion(str: string): string {
if (!coanaVersion) {
return str
}
return str.replaceAll(coanaVersion, '<coana-version>')
return str.replaceAll(COANA_CLI_VERSION, '<coana-version>')
}

// Normalize CLI banner output for stable snapshots.
Expand Down
Loading