feat: gateway publishability + npmjs publish script #370
@@ -35,8 +35,8 @@ steps:
|
|||||||
- |
|
- |
|
||||||
echo "//git.mosaicstack.dev/api/packages/mosaic/npm/:_authToken=$NPM_TOKEN" > ~/.npmrc
|
echo "//git.mosaicstack.dev/api/packages/mosaic/npm/:_authToken=$NPM_TOKEN" > ~/.npmrc
|
||||||
echo "@mosaic:registry=https://git.mosaicstack.dev/api/packages/mosaic/npm/" >> ~/.npmrc
|
echo "@mosaic:registry=https://git.mosaicstack.dev/api/packages/mosaic/npm/" >> ~/.npmrc
|
||||||
# Publish all non-private packages (--no-git-checks skips dirty/branch checks in CI)
|
# Publish non-private packages to Gitea (--no-git-checks skips dirty/branch checks in CI)
|
||||||
# --filter excludes private apps (gateway, web) and the root
|
# --filter excludes gateway (published to npmjs instead) and web (private)
|
||||||
- >
|
- >
|
||||||
pnpm --filter "@mosaic/*"
|
pnpm --filter "@mosaic/*"
|
||||||
--filter "!@mosaic/gateway"
|
--filter "!@mosaic/gateway"
|
||||||
@@ -46,6 +46,20 @@ steps:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- build
|
- build
|
||||||
|
|
||||||
|
publish-npmjs:
|
||||||
|
image: *node_image
|
||||||
|
environment:
|
||||||
|
NPM_TOKEN:
|
||||||
|
from_secret: npmjs_token
|
||||||
|
commands:
|
||||||
|
- *enable_pnpm
|
||||||
|
- apk add --no-cache jq bash
|
||||||
|
- bash scripts/publish-npmjs.sh
|
||||||
|
depends_on:
|
||||||
|
- build
|
||||||
|
when:
|
||||||
|
- event: [tag]
|
||||||
|
|
||||||
build-gateway:
|
build-gateway:
|
||||||
image: gcr.io/kaniko-project/executor:debug
|
image: gcr.io/kaniko-project/executor:debug
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@@ -1,9 +1,18 @@
|
|||||||
{
|
{
|
||||||
"name": "@mosaic/gateway",
|
"name": "@mosaic/gateway",
|
||||||
"version": "0.0.2",
|
"version": "0.0.2",
|
||||||
"private": true,
|
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/main.js",
|
"main": "dist/main.js",
|
||||||
|
"bin": {
|
||||||
|
"mosaic-gateway": "dist/main.js"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"publishConfig": {
|
||||||
|
"registry": "https://registry.npmjs.org/",
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"dev": "tsx watch src/main.ts",
|
"dev": "tsx watch src/main.ts",
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
import { config } from 'dotenv';
|
import { config } from 'dotenv';
|
||||||
import { existsSync } from 'node:fs';
|
import { existsSync } from 'node:fs';
|
||||||
import { resolve, join } from 'node:path';
|
import { resolve, join } from 'node:path';
|
||||||
|
|||||||
165
scripts/publish-npmjs.sh
Executable file
165
scripts/publish-npmjs.sh
Executable file
@@ -0,0 +1,165 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Publish @mosaic/* packages to npmjs.org as @mosaicstack/*
|
||||||
|
#
|
||||||
|
# This script patches each package.json to:
|
||||||
|
# 1. Rename @mosaic/X → @mosaicstack/X
|
||||||
|
# 2. Replace workspace:^ deps with resolved versions using @mosaicstack/* names
|
||||||
|
# 3. Run npm publish
|
||||||
|
# 4. Restore original package.json
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# scripts/publish-npmjs.sh [--dry-run] [--filter <package-name>]
|
||||||
|
#
|
||||||
|
# Requirements:
|
||||||
|
# - NPM_TOKEN env var set (npmjs.org auth token)
|
||||||
|
# - jq installed
|
||||||
|
# - Run from monorepo root after `pnpm build`
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
DRY_RUN=false
|
||||||
|
FILTER=""
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--dry-run) DRY_RUN=true; shift ;;
|
||||||
|
--filter) FILTER="$2"; shift 2 ;;
|
||||||
|
*) echo "Unknown option: $1"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
|
||||||
|
# Collect all publishable package directories (non-private, has publishConfig)
|
||||||
|
PACKAGE_DIRS=()
|
||||||
|
for pkg_json in "$REPO_ROOT"/packages/*/package.json "$REPO_ROOT"/plugins/*/package.json "$REPO_ROOT"/apps/gateway/package.json; do
|
||||||
|
[[ -f "$pkg_json" ]] || continue
|
||||||
|
is_private=$(jq -r '.private // false' "$pkg_json")
|
||||||
|
[[ "$is_private" == "true" ]] && continue
|
||||||
|
PACKAGE_DIRS+=("$(dirname "$pkg_json")")
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Found ${#PACKAGE_DIRS[@]} publishable packages"
|
||||||
|
|
||||||
|
# Build a version map: @mosaic/X → version
|
||||||
|
declare -A VERSION_MAP
|
||||||
|
for dir in "${PACKAGE_DIRS[@]}"; do
|
||||||
|
name=$(jq -r '.name' "$dir/package.json")
|
||||||
|
version=$(jq -r '.version' "$dir/package.json")
|
||||||
|
VERSION_MAP["$name"]="$version"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Configure npmjs auth
|
||||||
|
if [[ -z "${NPM_TOKEN:-}" ]] && [[ "$DRY_RUN" == "false" ]]; then
|
||||||
|
echo "ERROR: NPM_TOKEN is required for publishing. Set it or use --dry-run."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
publish_package() {
|
||||||
|
local dir="$1"
|
||||||
|
local orig_json="$dir/package.json"
|
||||||
|
local backup="$dir/package.json.bak"
|
||||||
|
|
||||||
|
local name
|
||||||
|
name=$(jq -r '.name' "$orig_json")
|
||||||
|
|
||||||
|
# Apply filter if set
|
||||||
|
if [[ -n "$FILTER" ]] && [[ "$name" != "$FILTER" ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local new_name="${name/@mosaic\//@mosaicstack/}"
|
||||||
|
echo ""
|
||||||
|
echo "━━━ Publishing $name → $new_name ━━━"
|
||||||
|
|
||||||
|
# Backup original
|
||||||
|
cp "$orig_json" "$backup"
|
||||||
|
|
||||||
|
# Patch: rename package
|
||||||
|
local patched
|
||||||
|
patched=$(jq --arg new_name "$new_name" '.name = $new_name' "$orig_json")
|
||||||
|
|
||||||
|
# Patch: publishConfig to npmjs
|
||||||
|
patched=$(echo "$patched" | jq '.publishConfig = {"registry": "https://registry.npmjs.org/", "access": "public"}')
|
||||||
|
|
||||||
|
# Patch: replace workspace:^ dependencies with @mosaicstack/* and resolved versions
|
||||||
|
for dep_field in dependencies devDependencies peerDependencies; do
|
||||||
|
if echo "$patched" | jq -e ".$dep_field" > /dev/null 2>&1; then
|
||||||
|
local deps
|
||||||
|
deps=$(echo "$patched" | jq -r ".$dep_field // {} | keys[]")
|
||||||
|
for dep in $deps; do
|
||||||
|
local dep_version
|
||||||
|
dep_version=$(echo "$patched" | jq -r ".$dep_field[\"$dep\"]")
|
||||||
|
|
||||||
|
# Only transform @mosaic/* workspace deps
|
||||||
|
if [[ "$dep" == @mosaic/* ]] && [[ "$dep_version" == workspace:* ]]; then
|
||||||
|
local new_dep="${dep/@mosaic\//@mosaicstack/}"
|
||||||
|
local resolved="${VERSION_MAP[$dep]:-}"
|
||||||
|
|
||||||
|
if [[ -z "$resolved" ]]; then
|
||||||
|
echo " WARNING: No version found for $dep — using '*'"
|
||||||
|
resolved="*"
|
||||||
|
else
|
||||||
|
# workspace:^ means ^version, workspace:* means *
|
||||||
|
if [[ "$dep_version" == "workspace:^" ]]; then
|
||||||
|
resolved="^$resolved"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Rename the dep key and set the resolved version
|
||||||
|
patched=$(echo "$patched" | jq \
|
||||||
|
--arg field "$dep_field" \
|
||||||
|
--arg old_dep "$dep" \
|
||||||
|
--arg new_dep "$new_dep" \
|
||||||
|
--arg version "$resolved" \
|
||||||
|
'.[$field] |= (del(.[$old_dep]) | .[$new_dep] = $version)')
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Write patched package.json
|
||||||
|
echo "$patched" > "$orig_json"
|
||||||
|
|
||||||
|
echo " Patched: $new_name"
|
||||||
|
|
||||||
|
# Publish
|
||||||
|
if [[ "$DRY_RUN" == "true" ]]; then
|
||||||
|
echo " [DRY RUN] npm publish --dry-run"
|
||||||
|
(cd "$dir" && npm publish --dry-run 2>&1) || true
|
||||||
|
else
|
||||||
|
echo " Publishing to npmjs..."
|
||||||
|
(cd "$dir" && npm publish 2>&1) || echo " WARNING: Publish failed (may already exist at this version)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Restore original
|
||||||
|
mv "$backup" "$orig_json"
|
||||||
|
echo " Restored original package.json"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set up npmrc for npmjs
|
||||||
|
if [[ -n "${NPM_TOKEN:-}" ]]; then
|
||||||
|
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/.npmrc
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Publish in dependency order: packages first, then plugins, then apps
|
||||||
|
echo ""
|
||||||
|
echo "=== Publishing packages ==="
|
||||||
|
for dir in "$REPO_ROOT"/packages/*/; do
|
||||||
|
[[ -f "$dir/package.json" ]] || continue
|
||||||
|
publish_package "$dir"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Publishing plugins ==="
|
||||||
|
for dir in "$REPO_ROOT"/plugins/*/; do
|
||||||
|
[[ -f "$dir/package.json" ]] || continue
|
||||||
|
publish_package "$dir"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Publishing apps ==="
|
||||||
|
publish_package "$REPO_ROOT/apps/gateway"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Done."
|
||||||
Reference in New Issue
Block a user