Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fcc181700e | |||
| a4ce4879a4 |
@@ -1,7 +1,7 @@
|
||||
# Every commit that lands on `main` publishes a prerelease of both packages to
|
||||
# the Gitea npm registry under the `main` dist-tag:
|
||||
#
|
||||
# pnpm add @bitstack/nopy@main
|
||||
# pnpm add @bitsquare/nopy@main
|
||||
#
|
||||
# The verification gate runs here rather than in ci.yml so a snapshot can never
|
||||
# be published from a red `main`. Versions are derived, never committed —
|
||||
@@ -87,7 +87,7 @@ jobs:
|
||||
fi
|
||||
install -m 600 /dev/null "$NPMRC"
|
||||
{
|
||||
printf '@bitstack:registry=%s\n' "$REGISTRY"
|
||||
printf '@bitsquare:registry=%s\n' "$REGISTRY"
|
||||
printf '//%s:_authToken=%s\n' "${REGISTRY#*://}" "$REGISTRY_TOKEN"
|
||||
} >> "$NPMRC"
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
# of `latest`.
|
||||
#
|
||||
# Required secrets:
|
||||
# NPM_TOKEN npmjs granular token, read-and-write on @bitstack/*, 2FA
|
||||
# NPM_TOKEN npmjs granular token, read-and-write on @bitsquare/*, 2FA
|
||||
# not required. Expires after 90 days — rotate it.
|
||||
# MYGITEA_NPM_TOKEN Gitea PAT with write:package. The automatic GITEA_TOKEN is
|
||||
# a repo-scoped task token and the package registry rejects it.
|
||||
@@ -131,7 +131,7 @@ jobs:
|
||||
set -euo pipefail
|
||||
install -m 600 /dev/null "$NPMRC"
|
||||
{
|
||||
printf '@bitstack:registry=%s\n' "$GITEA_REGISTRY"
|
||||
printf '@bitsquare:registry=%s\n' "$GITEA_REGISTRY"
|
||||
printf '//%s:_authToken=%s\n' "${GITEA_REGISTRY#*://}" "$GITEA_REGISTRY_TOKEN"
|
||||
} >> "$NPMRC"
|
||||
export npm_config_userconfig="$NPMRC"
|
||||
@@ -152,7 +152,7 @@ jobs:
|
||||
set -euo pipefail
|
||||
install -m 600 /dev/null "$NPMRC"
|
||||
{
|
||||
printf '@bitstack:registry=%s\n' "$NPMJS_REGISTRY"
|
||||
printf '@bitsquare:registry=%s\n' "$NPMJS_REGISTRY"
|
||||
printf '//%s:_authToken=%s\n' "${NPMJS_REGISTRY#*://}" "$NPMJS_TOKEN"
|
||||
} >> "$NPMRC"
|
||||
export npm_config_userconfig="$NPMRC"
|
||||
|
||||
+19
-19
@@ -23,8 +23,8 @@ shipped. If you only want to cut a release, jump to
|
||||
|
||||
| Directory | Package | Binary |
|
||||
| ----------------- | ------------------ | -------- |
|
||||
| `packages/nopy` | `@bitstack/nopy` | `nopy` |
|
||||
| `packages/keyman` | `@bitstack/keyman` | `keyman` |
|
||||
| `packages/nopy` | `@bitsquare/nopy` | `nopy` |
|
||||
| `packages/keyman` | `@bitsquare/keyman` | `keyman` |
|
||||
|
||||
Both are ESM, both declare `engines.node >= 22`, and both expose a single
|
||||
executable through `bin`, so `npm install -g` puts `nopy` / `keyman` on the
|
||||
@@ -155,7 +155,7 @@ semver even when the abbreviated sha happens to be all digits. The run number is
|
||||
monotonic, so every push produces a version that has never existed before.
|
||||
|
||||
```sh
|
||||
pnpm add @bitstack/nopy@main
|
||||
pnpm add @bitsquare/nopy@main
|
||||
```
|
||||
|
||||
Snapshots never reach npmjs and never move `latest`. The version is written into
|
||||
@@ -175,7 +175,7 @@ edit is discarded with the workspace and is never committed.
|
||||
```
|
||||
|
||||
The tag name is `<directory>-v<version>` — the directory under `packages/`, not
|
||||
the npm name. `nopy-v1.2.0`, not `@bitstack/nopy-v1.2.0`.
|
||||
the npm name. `nopy-v1.2.0`, not `@bitsquare/nopy-v1.2.0`.
|
||||
|
||||
The tag decides **which** package ships; `package.json` decides the **version**.
|
||||
The workflow re-reads the manifest and refuses to continue if the two disagree:
|
||||
@@ -193,7 +193,7 @@ a coincidence, not a requirement.
|
||||
|
||||
What a successful run leaves behind:
|
||||
|
||||
- `@bitstack/<pkg>@<version>` on the Gitea registry
|
||||
- `@bitsquare/<pkg>@<version>` on the Gitea registry
|
||||
- the same tarball on npmjs, public, under `latest` or `next`
|
||||
- a Gitea release on the tag, with notes and an install snippet
|
||||
- a step summary with both install commands
|
||||
@@ -228,7 +228,7 @@ organisation to share across repos.
|
||||
|
||||
| Secret | Required | Purpose |
|
||||
| ----------------- | -------- | --------------------------------------------------------- |
|
||||
| `NPM_TOKEN` | yes | npmjs granular token, read-and-write on `@bitstack/*` |
|
||||
| `NPM_TOKEN` | yes | npmjs granular token, read-and-write on `@bitsquare/*` |
|
||||
| `MYGITEA_NPM_TOKEN` | yes | Gitea PAT with `write:package` |
|
||||
|
||||
`GITEA_TOKEN` is injected into every run by Gitea itself, and the workflows fall
|
||||
@@ -241,12 +241,12 @@ practice. Create it under **Settings → Applications → Access Tokens** with t
|
||||
`package` scope set to read-and-write; its owner needs package-write on the
|
||||
`BitSquare` organisation, since the registry path is org-owned.
|
||||
|
||||
For npmjs, create a **granular access token** scoped to `@bitstack/*` with
|
||||
For npmjs, create a **granular access token** scoped to `@bitsquare/*` with
|
||||
read-and-write permission, and set 2FA to not-required so it works
|
||||
unattended. npm warns against that combination and points at Trusted Publishing
|
||||
instead — but Trusted Publishing federates only GitHub Actions and GitLab CI/CD
|
||||
over OIDC, and Gitea is not a provider it accepts. A token is the only route
|
||||
from this runner. Scoping the token to `@bitstack/*` is what keeps the exposure
|
||||
from this runner. Scoping the token to `@bitsquare/*` is what keeps the exposure
|
||||
small: a leak lets someone publish to that scope, not touch the account.
|
||||
|
||||
> npm caps granular token lifetime at 90 days, so `NPM_TOKEN` needs rotating
|
||||
@@ -264,7 +264,7 @@ small: a leak lets someone publish to that scope, not touch the account.
|
||||
|
||||
## Registry authentication in the workflows
|
||||
|
||||
`release.yml` has to talk to two different registries about the same `@bitstack`
|
||||
`release.yml` has to talk to two different registries about the same `@bitsquare`
|
||||
scope inside one job. It does that without ever mutating `~/.npmrc`:
|
||||
|
||||
- each publish step writes its own credentials file, created with
|
||||
@@ -284,20 +284,20 @@ file written into the workspace can never be committed by accident.
|
||||
From npmjs — public, no configuration:
|
||||
|
||||
```sh
|
||||
npm install -g @bitstack/nopy @bitstack/keyman
|
||||
npm install -g @bitsquare/nopy @bitsquare/keyman
|
||||
```
|
||||
|
||||
From the Gitea registry, which holds every snapshot plus a mirror of every
|
||||
release. Per-project, in the repo's `.npmrc`:
|
||||
|
||||
```ini
|
||||
@bitstack:registry=https://gitea.bitsquare.dev/api/packages/BitSquare/npm/
|
||||
@bitsquare:registry=https://gitea.bitsquare.dev/api/packages/BitSquare/npm/
|
||||
```
|
||||
|
||||
Globally with credentials, in `~/.npmrc`:
|
||||
|
||||
```ini
|
||||
@bitstack:registry=https://gitea.bitsquare.dev/api/packages/BitSquare/npm/
|
||||
@bitsquare:registry=https://gitea.bitsquare.dev/api/packages/BitSquare/npm/
|
||||
//gitea.bitsquare.dev/api/packages/BitSquare/npm/:_authToken=<your gitea token>
|
||||
```
|
||||
|
||||
@@ -308,7 +308,7 @@ instance and organisation automatically.
|
||||
To track snapshots in another project:
|
||||
|
||||
```sh
|
||||
pnpm add @bitstack/nopy@main
|
||||
pnpm add @bitsquare/nopy@main
|
||||
```
|
||||
|
||||
## Design decisions
|
||||
@@ -360,14 +360,14 @@ Try the binary as an end user would get it, without publishing:
|
||||
```sh
|
||||
cd packages/nopy && pnpm run link:local # build + npm link
|
||||
nopy --help
|
||||
npm unlink -g @bitstack/nopy
|
||||
npm unlink -g @bitsquare/nopy
|
||||
```
|
||||
|
||||
Check that a version is not already taken before you tag:
|
||||
|
||||
```sh
|
||||
npm view @bitstack/nopy@1.2.0 version # npmjs
|
||||
npm view @bitstack/nopy@1.2.0 version \
|
||||
npm view @bitsquare/nopy@1.2.0 version # npmjs
|
||||
npm view @bitsquare/nopy@1.2.0 version \
|
||||
--registry https://gitea.bitsquare.dev/api/packages/BitSquare/npm/
|
||||
```
|
||||
|
||||
@@ -391,14 +391,14 @@ npm view @bitstack/nopy@1.2.0 version \
|
||||
Meanwhile:
|
||||
|
||||
```sh
|
||||
npm dist-tag add @bitstack/nopy@1.1.9 latest # point users back
|
||||
npm deprecate @bitstack/nopy@1.2.0 "Broken build, use 1.2.1"
|
||||
npm dist-tag add @bitsquare/nopy@1.1.9 latest # point users back
|
||||
npm deprecate @bitsquare/nopy@1.2.0 "Broken build, use 1.2.1"
|
||||
```
|
||||
|
||||
`npm unpublish` is only possible within 72 hours and burns the version number
|
||||
forever; a deprecation with a working `latest` is almost always the better move.
|
||||
|
||||
**On Gitea**, delete the version under **Packages → @bitstack/… → Settings**
|
||||
**On Gitea**, delete the version under **Packages → @bitsquare/… → Settings**
|
||||
before that exact version can be published again.
|
||||
|
||||
**A bad tag** can be moved, but only before the release workflow has published
|
||||
|
||||
@@ -5,12 +5,12 @@ they deploy.
|
||||
|
||||
| Path | Package | Binary | What it is |
|
||||
| ----------------- | ------------------ | -------- | --------------------------------------------------- |
|
||||
| `packages/nopy` | `@bitstack/nopy` | `nopy` | interactive pyinfra script management and execution |
|
||||
| `packages/keyman` | `@bitstack/keyman` | `keyman` | SSH key management with `age` encryption |
|
||||
| `packages/nopy` | `@bitsquare/nopy` | `nopy` | interactive pyinfra script management and execution |
|
||||
| `packages/keyman` | `@bitsquare/keyman` | `keyman` | SSH key management with `age` encryption |
|
||||
| `cubes/` | — | — | the deployment units `nopy` runs |
|
||||
|
||||
```sh
|
||||
npm install -g @bitstack/nopy @bitstack/keyman
|
||||
npm install -g @bitsquare/nopy @bitsquare/keyman
|
||||
```
|
||||
|
||||
See each package's README for usage, and
|
||||
@@ -37,7 +37,7 @@ pnpm install
|
||||
|
||||
`typescript` is on the 7.x native compiler, so `tsc` *is* the fast one — there is
|
||||
no separate `tsgo` binary to keep in sync. Each package also has a dev-run script
|
||||
(`pnpm --filter @bitstack/nopy run nopy`) that executes the TypeScript sources
|
||||
(`pnpm --filter @bitsquare/nopy run nopy`) that executes the TypeScript sources
|
||||
directly through `tsx`.
|
||||
|
||||
## Git hooks
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
|
||||
export default cubes.Manifest({
|
||||
id: 'admin:cockpit',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes, uniqid } from '@bitstack/nopy';
|
||||
import { cubes, uniqid } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ Configures system keyboard layout permanently by updating `/etc/default/keyboard
|
||||
## Usage
|
||||
|
||||
```javascript
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
|
||||
export default cubes.Manifest({
|
||||
name: 'My Host Setup',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default cubes.Manifest({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default cubes.Manifest({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default cubes.Manifest({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
|
||||
export default cubes.Manifest({
|
||||
id: 'armor:fail2ban',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default cubes.Manifest({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default cubes.Manifest({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default cubes.Manifest({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default cubes.Manifest({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default cubes.Manifest({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default cubes.Manifest({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default cubes.Manifest({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
// [agnt://cogen/cogen/network-wifi-connection-1]{cartridge: "ansiblings/cubes", action: "generated", status: "generated"}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default cubes.Manifest({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default cubes.Manifest({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default cubes.Manifest({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default cubes.Manifest({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default cubes.Manifest({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default cubes.Manifest({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default cubes.Manifest({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
// [agnt://cogen/cogen/user-edit-1]{cartridge: "ansiblings/cubes", action: "generated", status: "generated"}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@bitstack/keyman",
|
||||
"name": "@bitsquare/keyman",
|
||||
"version": "1.0.0",
|
||||
"description": "A system to simplify ssh key management",
|
||||
"keywords": [
|
||||
|
||||
@@ -20,7 +20,7 @@ Self-contained deployment units consisting of:
|
||||
|
||||
```javascript
|
||||
import { z } from 'zod'
|
||||
import { cubes } from '@bitstack/nopy'
|
||||
import { cubes } from '@bitsquare/nopy'
|
||||
|
||||
export default cubes.Manifest({
|
||||
id: 'apt:install',
|
||||
@@ -209,7 +209,7 @@ This package is part of a yarn workspace monorepo. Install from the repository r
|
||||
```bash
|
||||
# From repository root (/ansiblings)
|
||||
yarn install
|
||||
yarn workspace @bitstack/nopy build
|
||||
yarn workspace @bitsquare/nopy build
|
||||
```
|
||||
|
||||
To use the `nopy` command globally, you can:
|
||||
@@ -217,7 +217,7 @@ To use the `nopy` command globally, you can:
|
||||
1. **Use yarn workspace command**:
|
||||
|
||||
```bash
|
||||
yarn workspace @bitstack/nopy nopy
|
||||
yarn workspace @bitsquare/nopy nopy
|
||||
```
|
||||
|
||||
2. **Link the package globally**:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
|
||||
export default cubes.Manifest({
|
||||
name: '[apt-all] Test dependencies',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default cubes.Manifest({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
|
||||
export default cubes.Manifest({
|
||||
name: '[apt-more] Test dependencies',
|
||||
|
||||
@@ -24,7 +24,7 @@ This document describes the public API for the nopy package.
|
||||
Main entry point for nopy deployments.
|
||||
|
||||
```typescript
|
||||
import { nopy } from '@bitstack/nopy';
|
||||
import { nopy } from '@bitsquare/nopy';
|
||||
|
||||
const result = await nopy({
|
||||
useDefaults: false,
|
||||
@@ -608,7 +608,7 @@ cubes/
|
||||
|
||||
```javascript
|
||||
// my-cube.manifest.mjs
|
||||
import { createManifest } from '@bitstack/nopy';
|
||||
import { createManifest } from '@bitsquare/nopy';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default createManifest({
|
||||
|
||||
@@ -15,7 +15,7 @@ Hooks are defined as an array of functions in the cube manifest.
|
||||
|
||||
```javascript
|
||||
import { z } from 'zod';
|
||||
import { cubes } from '@bitstack/nopy';
|
||||
import { cubes } from '@bitsquare/nopy';
|
||||
|
||||
export default cubes.Manifest({
|
||||
name: 'my-cube',
|
||||
|
||||
@@ -252,7 +252,7 @@ generateSession({
|
||||
Both formats are loaded the same way:
|
||||
|
||||
```javascript
|
||||
import { loadSession } from '@bitstack/nopy';
|
||||
import { loadSession } from '@bitsquare/nopy';
|
||||
|
||||
// Load JSON
|
||||
const jsonSession = await loadSession('./my-session.session.json');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bitstack/nopy",
|
||||
"version": "1.0.0-alpha3",
|
||||
"name": "@bitsquare/nopy",
|
||||
"version": "1.0.0-alpha5",
|
||||
"description": "A system to simplify pyinfra script management and execution.",
|
||||
"keywords": [
|
||||
"pyinfra",
|
||||
|
||||
+2
-2
@@ -12,8 +12,8 @@
|
||||
"skipLibCheck": true,
|
||||
"resolveJsonModule": true,
|
||||
"paths": {
|
||||
"@bitstack/nopy": ["./packages/nopy/src"],
|
||||
"@bitstack/keyman": ["./packages/keyman/src"]
|
||||
"@bitsquare/nopy": ["./packages/nopy/src"],
|
||||
"@bitsquare/keyman": ["./packages/keyman/src"]
|
||||
}
|
||||
},
|
||||
"exclude": ["coverage", "node_modules", "dist"]
|
||||
|
||||
Reference in New Issue
Block a user