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
76 changes: 76 additions & 0 deletions .github/workflows/publish-cli.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Publish CLI

# Publishes @codeplans/cli to npm. It runs after Publish Release creates a
# release, when a release is published from the GitHub UI, or by hand. The
# version in cli/package.json must match the tag (v0.7.7 → 0.7.7), and a
# version that is already on npm (or a tag from before the CLI existed) is
# skipped, so re-running and backfilling releases are safe.
on:
release:
types: [published]
workflow_call:
inputs:
tag:
required: true
type: string
secrets:
NPM_TOKEN:
required: true
workflow_dispatch:
inputs:
tag:
description: Release tag to publish the CLI from (e.g. v0.7.7)
required: true
type: string

permissions:
contents: read
id-token: write # npm provenance

jobs:
publish:
runs-on: ubuntu-latest
env:
TAG: ${{ inputs.tag || github.event.release.tag_name }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ env.TAG }}
- uses: pnpm/action-setup@v4
with:
version: 10
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
registry-url: https://registry.npmjs.org
- run: pnpm install --frozen-lockfile
- name: Check the version
id: version
run: |
if [ ! -f cli/package.json ]; then
echo "$TAG has no CLI; nothing to publish."
echo "skip=true" >> "$GITHUB_OUTPUT"
exit 0
fi
version=$(node -p "require('./cli/package.json').version")
if [ "v$version" != "$TAG" ]; then
echo "::error::cli/package.json is $version, but the tag is $TAG"
exit 1
fi
if npm view "@codeplans/cli@$version" version >/dev/null 2>&1; then
echo "@codeplans/cli@$version is already on npm; nothing to publish."
echo "skip=true" >> "$GITHUB_OUTPUT"
fi
- name: Test
if: steps.version.outputs.skip != 'true'
run: pnpm vitest run cli
- name: Build and publish
if: steps.version.outputs.skip != 'true'
working-directory: cli
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
npm run build
test "$(node dist/index.js --version)" = "${TAG#v}"
npm publish --access public --provenance
13 changes: 13 additions & 0 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,16 @@ jobs:
else
gh release create "$TAG" --verify-tag --title "${TITLE:-$TAG}" --notes "$NOTES"
fi

# Releases made here use the workflow token, which doesn't trigger other
# workflows, so the CLI is published from here explicitly.
cli:
needs: publish
permissions:
contents: read
id-token: write
uses: ./.github/workflows/publish-cli.yml
with:
tag: ${{ inputs.tag }}
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
2 changes: 1 addition & 1 deletion cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@codeplans/cli",
"version": "0.1.0",
"version": "0.7.7",
"description": "Command-line tool for CodePlans: script workspace setups, work with code plans, tasks and work items from your terminal.",
"license": "MIT",
"type": "module",
Expand Down
4 changes: 3 additions & 1 deletion cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
// node:util parseArgs; the runner adds --json, --profile and --help, turns
// errors into messages on stderr and exit codes, and creates the client lazily
// (login and help never need one).
import { readFileSync } from 'node:fs'
import { parseArgs, type ParseArgsConfig } from 'node:util'
import { Client, CliError, EXIT, type FetchLike } from './client.js'
import { configPath, resolveConnection, type Connection, type Env } from './config.js'
import { createOut, paint, table, type Out, type Sink } from './output.js'

export const VERSION = '0.1.0'
/** From the package's own package.json (one level up from both src/ and dist/), so it can't drift. */
export const VERSION: string = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version

type Options = NonNullable<ParseArgsConfig['options']>
export type Values = Record<string, string | boolean | string[] | undefined>
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "codeplans",
"version": "0.7.6",
"version": "0.7.7",
"description": "Manage and track coordinated changes across your software architecture.",
"author": "Sai Prakash <sylonzero@gmail.com>",
"homepage": "https://codeplans.ai",
Expand Down
Loading