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
47 changes: 47 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Dependabot — keeps npm + GitHub Actions versions current.
# Security-patch PRs arrive out-of-band the moment a CVE is published.

version: 2
updates:
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
day: monday
time: '06:00'
timezone: Europe/Vilnius
open-pull-requests-limit: 10
labels:
- dependencies
commit-message:
prefix: 'chore(deps)'
groups:
npm-minor-and-patch:
update-types:
- minor
- patch
ignore:
# conventional-changelog-conventionalcommits 10 needs
# conventional-changelog-writer@9; @semantic-release/release-notes-generator
# 14.x ships writer 8, so v10 breaks release notes ("Missing helper").
- dependency-name: 'conventional-changelog-conventionalcommits'
versions: ['>= 10']

- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
day: monday
time: '06:00'
timezone: Europe/Vilnius
open-pull-requests-limit: 5
labels:
- dependencies
- ci
commit-message:
prefix: 'ci'
groups:
actions-minor-and-patch:
update-types:
- minor
- patch
59 changes: 59 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: CI

on:
push:
branches: [main]
pull_request:

permissions:
contents: read

jobs:
build:
name: Node ${{ matrix.node }} · ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node: [20, 22, 24]
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: ${{ matrix.node }}
cache: npm
- run: npm ci
- run: npm run typecheck
- run: npm run build
# vitest 5 requires Node ^22.12 || >=24, so the test suite runs on 22+.
# The CLI itself still has to build and start on every Node in the matrix.
- run: npm test
if: matrix.node >= 22
# Smoke test: the CLI must at least print help on every OS/Node combo.
- run: node ./bin/run.js --help
- run: node ./bin/run.js db --help

package:
name: Package contents
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 22
cache: npm
- run: npm ci
- name: npm pack --dry-run
run: |
npm pack --dry-run --json 2>/dev/null > pack.json
node -e "
const s = require('fs').readFileSync('pack.json', 'utf8');
const p = JSON.parse(s.slice(s.indexOf('[')))[0];
console.log('Tarball:', (p.size / 1024).toFixed(1), 'KB,', p.files.length, 'files');
const paths = p.files.map((f) => f.path);
if (!paths.includes('oclif.manifest.json')) { console.error('::error::oclif.manifest.json missing from the package'); process.exit(1); }
const leaked = paths.filter((f) => /^(src|test|tests|scripts|docs|\.github)\//.test(f));
if (leaked.length) { console.error('::error::Files that must not ship:', leaked); process.exit(1); }
"
- run: npm audit --omit=dev --audit-level=high
124 changes: 124 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
name: Release

# Publishes `@norbix.ai/cli` to npm via semantic-release on every push to `main`
# (and prerelease branches `next` / `beta`). The next version comes from
# conventional commits since the last `v*` tag: `feat:` → minor, `fix:` → patch,
# `feat!:` / `BREAKING CHANGE:` → major. `chore:`, `ci:`, `test:` don't release.
#
# Authentication:
# - npm: trusted publishing (OIDC) first — npmjs.com trusts this repo +
# workflow file (package Settings → Trusted Publisher). npm requires 2FA for
# token-based publishes, which CI cannot do, so NPM_TOKEN is only a fallback.
# Trusted publishing needs `id-token: write` and npm >= 11.5.1.
# - GITHUB_TOKEN: provided by Actions; pushes the release tag and creates the
# GitHub Release.
#
# `main` is protected (changes only through pull requests), so the release does
# NOT commit back: `version` in package.json on main stays stale. The git tag is
# the source of truth for the version; release notes live on GitHub Releases.

on:
push:
branches: [main, next, beta]
workflow_dispatch:
inputs:
republish:
description: >-
Recovery mode — skip semantic-release and publish the version of the
latest git tag to npm, then create its GitHub Release if missing (use
when a tag exists but npm publish failed).
type: boolean
default: false

concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false

permissions:
contents: write
issues: write
pull-requests: write
id-token: write # trusted publishing + npm provenance

jobs:
release:
name: semantic-release
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v7
with:
# semantic-release needs the full history and tags.
fetch-depth: 0
persist-credentials: false

- name: Setup Node
uses: actions/setup-node@v7
with:
node-version: 22
cache: npm

- name: Use npm 11 (trusted publishing needs >= 11.5.1)
# Node 22 bundles npm 10, which cannot publish via OIDC.
run: |
npm install -g npm@^11.6.2
npm --version

- name: Install deps
run: npm ci --no-audit --no-fund

- name: Typecheck
run: npm run typecheck

- name: Test
run: npm test

- name: Smoke test
run: node ./bin/run.js --help

- name: npm audit (production deps only)
run: npm audit --omit=dev --audit-level=high

- name: Release
if: github.event_name != 'workflow_dispatch' || inputs.republish != true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: 'true'
run: npx semantic-release

- name: Republish to npm (recovery)
if: github.event_name == 'workflow_dispatch' && inputs.republish == true
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: 'true'
run: |
NAME=$(node -pe "require('./package.json').name")
TAG=$(git describe --tags --abbrev=0 --match 'v[0-9]*')
VERSION="${TAG#v}"
echo "Recovery publish: ${NAME}@${VERSION} (from tag ${TAG})"
if npm view "${NAME}@${VERSION}" version 2>/dev/null; then
echo "Already published on npm — nothing to do."
else
git checkout --detach "${TAG}"
npm ci --no-audit --no-fund
npm version "${VERSION}" --no-git-tag-version --allow-same-version
# Trusted publishing (OIDC) when configured; NPM_TOKEN as a fallback.
if [ -n "$NPM_TOKEN" ]; then
npm config set //registry.npmjs.org/:_authToken "$NPM_TOKEN"
fi
npm publish --access public
fi
if ! gh release view "${TAG}" >/dev/null 2>&1; then
gh release create "${TAG}" --verify-tag --title "${TAG}" --generate-notes
fi

- name: Summary
if: always()
run: |
echo "### Release · ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
TAG=$(git describe --tags --abbrev=0 --match 'v[0-9]*' 2>/dev/null || true)
if [ -n "$TAG" ]; then
echo "Latest tag: \`${TAG}\` — notes: ${{ github.server_url }}/${{ github.repository }}/releases/tag/${TAG}" >> $GITHUB_STEP_SUMMARY
fi
26 changes: 26 additions & 0 deletions .releaserc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"repositoryUrl": "https://github.com/norbix-code/cli.git",
"branches": ["main", { "name": "next", "prerelease": true }, { "name": "beta", "prerelease": true }],
"plugins": [
[
"@semantic-release/commit-analyzer",
{
"preset": "conventionalcommits",
"releaseRules": [
{ "type": "feat", "release": "minor" },
{ "type": "fix", "release": "patch" },
{ "type": "perf", "release": "patch" },
{ "type": "refactor", "release": "patch" },
{ "type": "docs", "scope": "readme", "release": "patch" },
{ "type": "chore", "release": false },
{ "type": "test", "release": false },
{ "type": "ci", "release": false },
{ "type": "style", "release": false }
]
}
],
["@semantic-release/release-notes-generator", { "preset": "conventionalcommits" }],
"@semantic-release/npm",
"@semantic-release/github"
]
}
2 changes: 1 addition & 1 deletion RESEARCH.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ with auto-update support — worth testing since we already use oclif.
## 5. Ideas / next steps

1. ~~`norbix files upload/download`~~ — done (signed-URL upload flow: request URL → PUT bytes → commit).
2. **Device-code or browser login** — `norbix login` opens hub.norbix.dev,
2. **Device-code or browser login** — `norbix login` opens hub.norbix.ai,
user confirms, CLI receives token. No password in the terminal.
3. **`norbix api <method> <path> --body '{...}'`** — raw escape hatch for any
endpoint the CLI doesn't wrap yet (like `gh api`).
Expand Down
22 changes: 9 additions & 13 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,12 @@ Quality gates:
4. **README polish**: add an install GIF or asciinema recording, a badges row
(CI, npm version), and a short "why CLI vs portal" paragraph.

Publish steps (first time, manual):

```sh
npm login # as the @norbix.ai org owner
npm pack --dry-run # check exactly which files go into the package
npm publish --access public
npx @norbix.ai/cli --help # verify from a clean machine
```

After that, releases are just: `npm version patch && git push --follow-tags`
(the release workflow publishes with provenance).
Releases (automated): `.github/workflows/release.yml` runs semantic-release on
every push to `main`. Merge a PR whose squash title is a conventional commit —
`feat:` → minor, `fix:` → patch, `feat!:` → major; `chore:` / `ci:` /
`test:` don't release. It tags `vX.Y.Z`, publishes to npm with provenance and
creates the GitHub Release. `package.json` `version` on `main` is not bumped
(main is protected); the tag is the source of truth.

## Next — v0.2.x

Expand Down Expand Up @@ -80,7 +75,8 @@ Functionality:
- [ ] Push code to github.com/norbix-code/cli (see README "Development")
- [ ] Remove the stray `# cli` line if GitHub's starter README got merged
- [ ] `git update-index --chmod=+x bin/run.js` so the exec bit survives git
- [ ] Add NPM_TOKEN secret for the release workflow
- [x] Add NPM_TOKEN secret for the release workflow (fallback; prefer npm trusted publishing)
- [ ] Configure npm Trusted Publisher for `@norbix.ai/cli` (repo `norbix-code/cli`, workflow `release.yml`)
- [ ] Branch protection on main (same ruleset as sdk-ts:
MainBranchProtectionRuleSet.json in the sdks folder)
- [ ] Enable Dependabot / npm audit in CI
- [x] Enable Dependabot / npm audit in CI
27 changes: 0 additions & 27 deletions github-workflows/ci.yml

This file was deleted.

34 changes: 0 additions & 34 deletions github-workflows/release.yml

This file was deleted.

Loading