refactor(gitea): robust manifest-based publish pipeline
publish-outdated-packages.sh rewritten: - Manifest-based change detection (no registry tarball downloads) - Single pack per package (not double-pack for check+publish) - Deterministic content hash: normalizes version, publishConfig, and @bytelyst/* dep versions (workspace:* resolution noise) - Single metadata fetch per package (cached in-process) - Fixed .npmrc overwrite bug that broke auth during publish phase - npm_clean() helper strips all proxy env vars uniformly release-packages.sh fixed: - .npmrc now includes scoped registry + proxy=false for corp - Unified corp/home publish path (no duplicated code) - version_on_registry() uses proxy-stripped env - Registry credential check uses proxy-stripped env CI workflow: switched to publish-outdated-packages.sh --skip-build
This commit is contained in:
parent
4e92634f62
commit
deff216c7e
@ -71,5 +71,5 @@ jobs:
|
||||
- name: Build all packages
|
||||
run: pnpm -r --filter './packages/**' build
|
||||
|
||||
- name: Publish to local Gitea registry
|
||||
run: bash ./scripts/gitea/publish-local-packages.sh
|
||||
- name: Publish outdated packages to Gitea registry
|
||||
run: bash ./scripts/gitea/publish-outdated-packages.sh --skip-build
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/accessibility",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/api-client",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/auth-client",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"description": "Browser/React Native-safe auth API client for platform-service",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/auth-ui",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"description": "Shared auth UI components for SmartAuth (LoginForm, MfaChallenge, SocialButtons)",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/auth",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/backend-config",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"description": "Shared Zod config schema base for Fastify product backends",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/backend-flags",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"description": "In-memory feature flag registry for Fastify product backends",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/backend-telemetry",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"description": "In-memory telemetry event buffer for Fastify product backends",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/blob-client",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"description": "Browser/React Native-safe blob storage client — SAS URL upload/download via platform-service",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/blob",
|
||||
"version": "0.2.2",
|
||||
"version": "0.2.5",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/broadcast-client",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"description": "Browser/React Native-safe broadcast messaging client for platform-service",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/celebrations",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/client-encrypt",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/config",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/cosmos",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/create-app",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.3",
|
||||
"description": "CLI tools for scaffolding ByteLyst product repos and code",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/dashboard-components",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"description": "Shared React components for ByteLyst dashboards",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/dashboard-shell",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"description": "Configurable Next.js dashboard layout with sidebar, profile, billing, and settings pages",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/datastore",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/design-tokens",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/diagnostics-client",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"description": "TypeScript client for remote diagnostics and debug tracing",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/errors",
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.6",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/event-store",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"description": "Persistent event store with pluggable backends (in-memory, file, Cosmos) for ByteLyst product backends",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/events",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/extraction",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"description": "Shared types and client for the extraction service",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/fastify-auth",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"description": "JWT auth middleware + request context for Fastify product backends",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/fastify-core",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/fastify-sse",
|
||||
"version": "0.3.2",
|
||||
"version": "0.3.5",
|
||||
"description": "Fastify plugin for Server-Sent Events (SSE) — real-time push for ByteLyst product backends",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/feature-flag-client",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"description": "Browser/React Native-safe feature flag client for platform-service",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/feedback-client",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"description": "TypeScript client for submitting user feedback with screenshots",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/field-encrypt",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/gentle-notifications",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/kill-switch-client",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"description": "Browser/React Native-safe kill switch client for platform-service",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/llm-router",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"description": "Pure-code LLM router for free-tier API providers with round-robin, fallback, and health tracking",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/llm",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/logger",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"description": "Structured logger factory for Next.js dashboards and Node.js services",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/marketplace-client",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/monitoring",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"description": "Health-check aggregation utilities for ByteLyst services and dashboards",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/offline-queue",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"description": "Browser/React Native-safe persistent offline retry queue",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/ollama-client",
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.6",
|
||||
"description": "Shared Ollama API client — streaming chat, embeddings, model management, health checks",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/org-client",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/palace",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.4",
|
||||
"description": "Shared MemPalace primitives — types, cosine similarity, dedup, relevance decay, extraction prompts, KG helpers, wake-up context builder",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/platform-client",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"description": "Browser/React Native-safe typed fetch wrapper for platform-service",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/push",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/queue",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"description": "Durable job queue with pluggable stores and worker runtime",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/quick-actions",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/react-auth",
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.6",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/referral-client",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/secure-storage-web",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/speech",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"description": "Cloud-agnostic speech-to-text abstraction for the ByteLyst ecosystem",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/storage",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/subscription-client",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/survey-client",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"description": "Browser/React Native-safe survey client for platform-service",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/sync",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"description": "Offline-first sync engine with configurable storage adapters and conflict resolution",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/telemetry-client",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"description": "Browser/React Native-safe telemetry client for platform-service",
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/testing",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/time-references",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/ui",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"storybook": "storybook dev -p 6006",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/use-keyboard-shortcuts",
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.6",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/use-theme",
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.6",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bytelyst/webhook-dispatch",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.5",
|
||||
"description": "Reusable webhook dispatch with HMAC-SHA256 signing, exponential backoff retry, and delivery tracking for ByteLyst product backends",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
307
scripts/gitea/.publish-manifest.json
Normal file
307
scripts/gitea/.publish-manifest.json
Normal file
@ -0,0 +1,307 @@
|
||||
{
|
||||
"@bytelyst/accessibility": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "1298db3c803a8e338599967527b1af76d41e6ca60afb1566ef8346314845f094",
|
||||
"publishedAt": "2026-04-13T08:44:02.743Z"
|
||||
},
|
||||
"@bytelyst/api-client": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "60958fa143ab6ff3aa6225779f162fe3a24744fb268f01bdff544b9a69ea0bdd",
|
||||
"publishedAt": "2026-04-13T08:44:04.429Z"
|
||||
},
|
||||
"@bytelyst/auth": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "97f8e1ca0a609075e82751091a4a995740a5b06b513c14b55ee57ce6a9de7309",
|
||||
"publishedAt": "2026-04-13T08:44:09.341Z"
|
||||
},
|
||||
"@bytelyst/auth-client": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "0155230525c853d8a18a6861078a5fecb2769962fd0f4102c759ead25c245296",
|
||||
"publishedAt": "2026-04-13T08:44:06.085Z"
|
||||
},
|
||||
"@bytelyst/auth-ui": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "82bcd4ff0f8dea680c393b2f03470ce17bd1770baf3f9aca40dc1f18f2a82ad9",
|
||||
"publishedAt": "2026-04-13T08:44:07.686Z"
|
||||
},
|
||||
"@bytelyst/backend-config": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "37808dd0b3280b730122ed0171811ac92dc7fd79e10a78f3c14daef911478149",
|
||||
"publishedAt": "2026-04-13T08:44:11.057Z"
|
||||
},
|
||||
"@bytelyst/backend-flags": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "f79b89e172df28a296bd343883798bd761685599d27adfd94f88e09ef495df17",
|
||||
"publishedAt": "2026-04-13T08:44:12.606Z"
|
||||
},
|
||||
"@bytelyst/backend-telemetry": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "34ead309860862742b7bafa60a85b95e5f1ccbd187cf7d849064e039ca1e336a",
|
||||
"publishedAt": "2026-04-13T08:44:14.003Z"
|
||||
},
|
||||
"@bytelyst/blob": {
|
||||
"version": "0.2.5",
|
||||
"contentHash": "62b14ea355c625e102c533e9327f281b13c6031cfc3055fb4a6022d8d7512c5f",
|
||||
"publishedAt": "2026-04-13T08:44:17.082Z"
|
||||
},
|
||||
"@bytelyst/blob-client": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "4b9e2a79ae68cba537026a861408afbd205f8d9da3f20bcab073d8f95881e6be",
|
||||
"publishedAt": "2026-04-13T08:44:15.555Z"
|
||||
},
|
||||
"@bytelyst/broadcast-client": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "e819ffca743f96cdeb725134a1692378a2dbb0b40c843721290841e33fa731b7",
|
||||
"publishedAt": "2026-04-13T08:44:18.467Z"
|
||||
},
|
||||
"@bytelyst/celebrations": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "84570ad46d99cada6b59512a81a5f1fbee2a74a982f9c8ffe1ca9577bc3e537b",
|
||||
"publishedAt": "2026-04-13T08:44:20.012Z"
|
||||
},
|
||||
"@bytelyst/client-encrypt": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "4cfcfbe8b253dedaccfad21e680c43244449b60d441599a63031d8e27fa11ed1",
|
||||
"publishedAt": "2026-04-13T08:44:21.557Z"
|
||||
},
|
||||
"@bytelyst/config": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "461d8646a67d0dfb4b27bbb62ee8751428d190c20ba9b55bea556806f55c0355",
|
||||
"publishedAt": "2026-04-13T08:44:23.220Z"
|
||||
},
|
||||
"@bytelyst/cosmos": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "b0ddd5441f4b15ca28453b6e4cd089fcd92f7b504132d03c43a9b869c111c108",
|
||||
"publishedAt": "2026-04-13T08:44:24.588Z"
|
||||
},
|
||||
"@bytelyst/create-app": {
|
||||
"version": "0.1.3",
|
||||
"contentHash": "e0439baca0c3850dc5714fcbb84b8b996549771740381fe5cf202a03b4e0c841",
|
||||
"publishedAt": "2026-04-13T08:44:26.178Z"
|
||||
},
|
||||
"@bytelyst/dashboard-components": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "7d1ab88cb6fc6093e66c7be89c1cdc6ef7031bf20783b04d4f05bbb9d2e2dd5c",
|
||||
"publishedAt": "2026-04-13T08:44:27.860Z"
|
||||
},
|
||||
"@bytelyst/dashboard-shell": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "e88743978d4d09a1a4047e5134469521ba8a9c0520ec04d0d3b7b5e4cb09f841",
|
||||
"publishedAt": "2026-04-13T08:44:29.385Z"
|
||||
},
|
||||
"@bytelyst/datastore": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "482bef2452f47fe4ca553f3a1c67eb4dbd159ca9b791a274e713fbe0e64a7a2b",
|
||||
"publishedAt": "2026-04-13T08:44:30.939Z"
|
||||
},
|
||||
"@bytelyst/design-tokens": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "46c2c7041807e52c965f08b8159b4cb17a4b752171f7d18cdb594f96d401792a",
|
||||
"publishedAt": "2026-04-13T08:44:32.598Z"
|
||||
},
|
||||
"@bytelyst/diagnostics-client": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "c52ebcb6674e3cc468461741c86298f5923e80ca8fa4fbb08d55fdfd39517e7f",
|
||||
"publishedAt": "2026-04-13T08:44:34.283Z"
|
||||
},
|
||||
"@bytelyst/errors": {
|
||||
"version": "0.1.6",
|
||||
"contentHash": "76443c39ff29478a483cb82439dcc44c5a25a1e87cf53eba3c1ba1e30b7947cf",
|
||||
"publishedAt": "2026-04-13T08:44:35.843Z"
|
||||
},
|
||||
"@bytelyst/event-store": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "8ecf328682c6b886d0ee2db85094b7d2c6f589fe56d7666319b197383d8ca2ff",
|
||||
"publishedAt": "2026-04-13T08:44:37.491Z"
|
||||
},
|
||||
"@bytelyst/events": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "ea584931f18cf682d3738545474ada10b67a775b7b549f4cc4862e145be8972f",
|
||||
"publishedAt": "2026-04-13T08:44:39.134Z"
|
||||
},
|
||||
"@bytelyst/extraction": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "0edce9563443f5daea8d5efb2481fedaad9746f4ee1b7b9fb29e9095c0fe9305",
|
||||
"publishedAt": "2026-04-13T08:44:40.758Z"
|
||||
},
|
||||
"@bytelyst/fastify-auth": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "d196ce76219aa420273d003781b83ecca11f11271dd2be9cfbe0c6b832d6d790",
|
||||
"publishedAt": "2026-04-13T08:44:42.446Z"
|
||||
},
|
||||
"@bytelyst/fastify-core": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "0140953510ee4cf2f584c6f2745e33817832a7848f13e4a26b805038238cba77",
|
||||
"publishedAt": "2026-04-13T08:44:44.114Z"
|
||||
},
|
||||
"@bytelyst/fastify-sse": {
|
||||
"version": "0.3.5",
|
||||
"contentHash": "1ef6fc1053ec6108af6faae1b6669fed4dc659660b6fbcc96474f7dff5c2d209",
|
||||
"publishedAt": "2026-04-13T08:44:45.648Z"
|
||||
},
|
||||
"@bytelyst/feature-flag-client": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "81bbef1e411bdf9c38e59f82b6b7427b653aa7f36b304a32202332d260529ba3",
|
||||
"publishedAt": "2026-04-13T08:44:47.385Z"
|
||||
},
|
||||
"@bytelyst/feedback-client": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "a9e11aa31ae7d576b0502fd6aefdfc93028863ae3e076e39c0accb4d2f78e524",
|
||||
"publishedAt": "2026-04-13T08:44:49.075Z"
|
||||
},
|
||||
"@bytelyst/field-encrypt": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "3d8a01f2421fa077bf0f149b529f1841ec0f54a84b290b8535ca498e9c714c76",
|
||||
"publishedAt": "2026-04-13T08:44:50.633Z"
|
||||
},
|
||||
"@bytelyst/gentle-notifications": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "00e49456bba81458c7d0129880207cc4e631ccd1037770ecddbfa9f7fbde8387",
|
||||
"publishedAt": "2026-04-13T08:44:51.924Z"
|
||||
},
|
||||
"@bytelyst/kill-switch-client": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "0a6a46bcac5eb8d5723dd44458f533b8ef203b796939fb66cf66f2e6223c07fd",
|
||||
"publishedAt": "2026-04-13T08:44:53.517Z"
|
||||
},
|
||||
"@bytelyst/llm": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "7985c82f98990adf7aa70aa55676c1fdd08e2100644d1b42a786758f7e0bb89c",
|
||||
"publishedAt": "2026-04-13T08:44:56.327Z"
|
||||
},
|
||||
"@bytelyst/llm-router": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "5cc32aec6c0dd8bff4b4206ff55937663ba2995926d498510e49747a3fc12183",
|
||||
"publishedAt": "2026-04-13T08:44:54.935Z"
|
||||
},
|
||||
"@bytelyst/logger": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "3ad702d6f0731621499916049049cf8de38a53e4c005095a2a14ca8b0aff1bbd",
|
||||
"publishedAt": "2026-04-13T08:44:57.723Z"
|
||||
},
|
||||
"@bytelyst/marketplace-client": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "f44881256419432284b40dbde7d677a109579d94a3b9df9f3b9f40641ee30085",
|
||||
"publishedAt": "2026-04-13T08:44:59.204Z"
|
||||
},
|
||||
"@bytelyst/monitoring": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "08840748c02e326e7cd2c410d80c17c1fcaeb5c48c57f3bbc5a5069926e660da",
|
||||
"publishedAt": "2026-04-13T08:45:00.504Z"
|
||||
},
|
||||
"@bytelyst/offline-queue": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "1c25e355ec6a6f7c7e74e77b8c53aca94f0342eda049d535e31b56c6632d5101",
|
||||
"publishedAt": "2026-04-13T08:45:02.179Z"
|
||||
},
|
||||
"@bytelyst/ollama-client": {
|
||||
"version": "0.1.6",
|
||||
"contentHash": "fa08340465aba0e866f8c5bb2839425ce46c694a5ad0839283fdbb8037a39121",
|
||||
"publishedAt": "2026-04-13T08:45:03.855Z"
|
||||
},
|
||||
"@bytelyst/org-client": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "e0b8eb1bce5047e9bfcf11db8f77d8495f403cd08f74bb3d4a0dc37183a9ef29",
|
||||
"publishedAt": "2026-04-13T08:45:05.581Z"
|
||||
},
|
||||
"@bytelyst/palace": {
|
||||
"version": "0.1.4",
|
||||
"contentHash": "8e47ae7ed300b1edd2f2058b5c3358f2d917d7b91ab4218357ad7cc3d20ed085",
|
||||
"publishedAt": "2026-04-13T08:45:07.168Z"
|
||||
},
|
||||
"@bytelyst/platform-client": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "a5d90ea537a55ea295d5c9933f4ccab2b152d57666db623f7e6bcc11f403025a",
|
||||
"publishedAt": "2026-04-13T08:45:08.836Z"
|
||||
},
|
||||
"@bytelyst/push": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "8fea33b73c0e4dc758a77b0dc80f49a1ea3a15b51a216dbc875b3f56c260685a",
|
||||
"publishedAt": "2026-04-13T08:45:10.487Z"
|
||||
},
|
||||
"@bytelyst/queue": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "f3ea3cdf536c117e04f393bf1bfc5eda24117973aad3be15e687513b444f6bdb",
|
||||
"publishedAt": "2026-04-13T08:45:12.106Z"
|
||||
},
|
||||
"@bytelyst/quick-actions": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "c1daf30dec2eda0bbec55a73e8c0cdb98d7c3c43dbcb5791bb9ef6097e3f4599",
|
||||
"publishedAt": "2026-04-13T08:45:13.687Z"
|
||||
},
|
||||
"@bytelyst/react-auth": {
|
||||
"version": "0.1.6",
|
||||
"contentHash": "c4e4e86ed03b93ea6d1cb40e1a67315685cdb2a4e262858dfd29850a18a16a72",
|
||||
"publishedAt": "2026-04-13T08:45:15.275Z"
|
||||
},
|
||||
"@bytelyst/referral-client": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "d519fab34d2e41c54951f02e38e1ce7f513aa4f4610f52947737bafb2b52dfae",
|
||||
"publishedAt": "2026-04-13T08:45:16.758Z"
|
||||
},
|
||||
"@bytelyst/secure-storage-web": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "339d7122c0ec40bb1e84e99f74468b18cffde7600217fc7b0f91c89cf323f68c",
|
||||
"publishedAt": "2026-04-13T08:45:18.264Z"
|
||||
},
|
||||
"@bytelyst/speech": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "5dc93cd396b7a61d24ad28d5e27d9873cea9d9dd086b2ba51c644863a5134938",
|
||||
"publishedAt": "2026-04-13T08:45:19.842Z"
|
||||
},
|
||||
"@bytelyst/storage": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "65fb1ec119905bd862fb5ba1cc92cf88098067e162d4e8e058c565af9b7fae7b",
|
||||
"publishedAt": "2026-04-13T08:45:21.411Z"
|
||||
},
|
||||
"@bytelyst/subscription-client": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "881ff18db9b61f715b0b995720d5defdb2ad5d7b44e17aa0f2bfd4e8ad6729fa",
|
||||
"publishedAt": "2026-04-13T08:45:23.046Z"
|
||||
},
|
||||
"@bytelyst/survey-client": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "7d31d407924274dc4b1e4f6a06fce2b79b19f18e11270aa7a505a9bcefc2f8f9",
|
||||
"publishedAt": "2026-04-13T08:45:24.602Z"
|
||||
},
|
||||
"@bytelyst/sync": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "7bcc6c6e7df33f966a5c4ee240b31dba8a286dbcfdebaad3dfdcefdb0fccfc2c",
|
||||
"publishedAt": "2026-04-13T08:45:26.173Z"
|
||||
},
|
||||
"@bytelyst/telemetry-client": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "014acc903c05375e8decffcda698ba33a7993aed35916f48210546e8f4058138",
|
||||
"publishedAt": "2026-04-13T08:45:27.699Z"
|
||||
},
|
||||
"@bytelyst/testing": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "478bdf04d9b2c54f8778d9a6987ba63b6f4f728bb2c7fc8b138cf8d3e5035c20",
|
||||
"publishedAt": "2026-04-13T08:45:29.298Z"
|
||||
},
|
||||
"@bytelyst/time-references": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "70c04eeb491cf24ccb7cded95c4f213aff492c0f6b3b4d8be1af6395a266db59",
|
||||
"publishedAt": "2026-04-13T08:45:30.916Z"
|
||||
},
|
||||
"@bytelyst/ui": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "3ed0e0c895a9fc86a016330b82f13df2c2ced4957e144a1a64c7d8c6e28e2282",
|
||||
"publishedAt": "2026-04-13T08:45:32.412Z"
|
||||
},
|
||||
"@bytelyst/use-keyboard-shortcuts": {
|
||||
"version": "0.1.6",
|
||||
"contentHash": "04b917d4913f66247bfcfea53a871fac128e4b8d20bcdff6c2374e7f25aa8eee",
|
||||
"publishedAt": "2026-04-13T08:45:33.972Z"
|
||||
},
|
||||
"@bytelyst/use-theme": {
|
||||
"version": "0.1.6",
|
||||
"contentHash": "1767e51d2352224ee2ef36d40e6261afcf70bb643b984d0378874a35a458cc26",
|
||||
"publishedAt": "2026-04-13T08:45:35.655Z"
|
||||
},
|
||||
"@bytelyst/webhook-dispatch": {
|
||||
"version": "0.1.5",
|
||||
"contentHash": "e7afbed1158c657b1737716554cfc39f8d1263f03ee8c9774865e95622fadf8d",
|
||||
"publishedAt": "2026-04-13T08:45:37.234Z"
|
||||
}
|
||||
}
|
||||
@ -2,25 +2,33 @@
|
||||
set -euo pipefail
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# Publish only OUTDATED @bytelyst/* packages to Gitea registry
|
||||
# Publish OUTDATED @bytelyst/* packages to the Gitea npm registry.
|
||||
#
|
||||
# Compares local built content against what's in the registry.
|
||||
# Only publishes packages where the content has actually changed.
|
||||
# Uses a local manifest (.publish-manifest.json) to track content hashes
|
||||
# of the last-published version. Only packages whose built content has
|
||||
# actually changed since the last publish are bumped and republished.
|
||||
#
|
||||
# Improvements over the previous version:
|
||||
# - Manifest-based comparison (no registry tarball downloads)
|
||||
# - Single pack per package (not double-pack)
|
||||
# - Single metadata fetch per package (cached in-process)
|
||||
# - No false-positive "OUTDATED" from pnpm-vs-npm pack differences
|
||||
# - No .npmrc overwrite bug
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/gitea/publish-outdated-packages.sh # detect + publish
|
||||
# ./scripts/gitea/publish-outdated-packages.sh --dry-run # detect only
|
||||
# ./scripts/gitea/publish-outdated-packages.sh --filter @bytelyst/errors
|
||||
# scripts/gitea/publish-outdated-packages.sh # build + detect + publish
|
||||
# scripts/gitea/publish-outdated-packages.sh --dry-run # build + detect only
|
||||
# scripts/gitea/publish-outdated-packages.sh --skip-build # skip pnpm build
|
||||
# scripts/gitea/publish-outdated-packages.sh --filter @bytelyst/errors
|
||||
#
|
||||
# Requires: GITEA_NPM_TOKEN env var (or ~/.gitea_npm_token)
|
||||
# Requires: GITEA_NPM_TOKEN (env var or ~/.gitea_npm_token)
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
PACKAGES_DIR="$REPO_ROOT/packages"
|
||||
MANIFEST_FILE="$REPO_ROOT/scripts/gitea/.publish-manifest.json"
|
||||
|
||||
# ── Network-aware Gitea resolution ─────────────────────────
|
||||
# NETWORK=corp -> localhost:3300 (SSH tunnel to Azure VM)
|
||||
# NETWORK=home -> Azure VM directly (gitea.bytelyst.com or ~/.gitea_vm_host)
|
||||
NETWORK_MODE="${NETWORK:-home}"
|
||||
|
||||
if [ "$NETWORK_MODE" = "corp" ]; then
|
||||
@ -29,7 +37,6 @@ if [ "$NETWORK_MODE" = "corp" ]; then
|
||||
GITEA_BASE="http://${GITEA_HOST}:${GITEA_PORT}"
|
||||
IS_CORP=true
|
||||
else
|
||||
# Home network: use Azure VM host from ~/.gitea_vm_host or GITEA_NPM_HOST
|
||||
if [ -n "${GITEA_NPM_HOST:-}" ] && [ "${GITEA_NPM_HOST}" != "localhost" ]; then
|
||||
GITEA_HOST="$GITEA_NPM_HOST"
|
||||
elif [ -f "$HOME/.gitea_vm_host" ]; then
|
||||
@ -44,7 +51,7 @@ fi
|
||||
|
||||
REGISTRY_URL="${GITEA_NPM_REGISTRY_URL:-${GITEA_BASE}/api/packages/ByteLyst/npm/}"
|
||||
TOKEN="${GITEA_NPM_TOKEN:-}"
|
||||
WORK_DIR="${TMPDIR:-/tmp}/bytelyst-outdated-check-$$"
|
||||
WORK_DIR="${TMPDIR:-/tmp}/bytelyst-publish-$$"
|
||||
DRY_RUN=false
|
||||
PACKAGE_FILTER=""
|
||||
SKIP_BUILD=false
|
||||
@ -67,35 +74,32 @@ while [[ $# -gt 0 ]]; do
|
||||
esac
|
||||
done
|
||||
|
||||
# Resolve token from file if not in env
|
||||
# Resolve token
|
||||
if [ -z "$TOKEN" ] && [ -f "$HOME/.gitea_npm_token" ]; then
|
||||
TOKEN="$(cat "$HOME/.gitea_npm_token")"
|
||||
fi
|
||||
|
||||
if [ -z "$TOKEN" ]; then
|
||||
echo "ERROR: GITEA_NPM_TOKEN is required (env var or ~/.gitea_npm_token)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Auth target for npm publish
|
||||
# Auth target for .npmrc
|
||||
AUTH_TARGET="${REGISTRY_URL#http://}"
|
||||
AUTH_TARGET="${AUTH_TARGET#https://}"
|
||||
|
||||
# Skip non-npm packages (native SDKs)
|
||||
# Non-npm packages to skip
|
||||
SKIP_DIRS="swift-platform-sdk swift-diagnostics kotlin-platform-sdk react-native-platform-sdk"
|
||||
|
||||
# Cleanup on exit
|
||||
# Cleanup temp dir on exit
|
||||
trap 'rm -rf "$WORK_DIR"' EXIT
|
||||
mkdir -p "$WORK_DIR"
|
||||
|
||||
# Write .npmrc with auth token + scoped registry so npm publish bypasses publishConfig
|
||||
# Single .npmrc for all npm operations (auth + scoped registry + proxy override)
|
||||
NPMRC_FILE="$WORK_DIR/.npmrc"
|
||||
{
|
||||
printf '//%s:_authToken=%s\n' "$AUTH_TARGET" "$TOKEN"
|
||||
# Override publishConfig.registry in package.json (npm uses scoped registry first)
|
||||
printf '@bytelyst:registry=%s\n' "$REGISTRY_URL"
|
||||
if [ "$IS_CORP" = true ]; then
|
||||
# Disable proxy for localhost (global ~/.npmrc has corp proxy)
|
||||
printf 'proxy=false\nhttps-proxy=false\n'
|
||||
fi
|
||||
} > "$NPMRC_FILE"
|
||||
@ -103,184 +107,142 @@ NPMRC_FILE="$WORK_DIR/.npmrc"
|
||||
# ── Helpers ────────────────────────────────────────────────
|
||||
|
||||
pkg_field() {
|
||||
node -e "process.stdout.write(JSON.parse(require('fs').readFileSync(process.argv[1],'utf8')).$1||'')" "$2"
|
||||
node -e "process.stdout.write(String(JSON.parse(require('fs').readFileSync(process.argv[1],'utf8'))['$1']||''))" "$2"
|
||||
}
|
||||
|
||||
# Compute a content fingerprint of all files under a directory.
|
||||
# Sorts file paths, hashes each file, then hashes the combined result.
|
||||
# This is metadata-independent (ignores tar headers, timestamps, etc.)
|
||||
content_fingerprint() {
|
||||
local dir="$1"
|
||||
find "$dir" -type f -print0 | sort -z | xargs -0 shasum -a 256 | shasum -a 256 | cut -d' ' -f1
|
||||
}
|
||||
# Compute a deterministic content hash from an extracted tarball.
|
||||
# Normalizes package.json (version→0.0.0, strips publishConfig) so that
|
||||
# version bumps alone don't trigger re-publish.
|
||||
# Uses relative paths and stdin hashing to ensure determinism across runs.
|
||||
content_hash() {
|
||||
local extracted_dir="$1" # contains package/ subdirectory
|
||||
local pkg_json="$extracted_dir/package/package.json"
|
||||
local norm; norm=$(mktemp)
|
||||
|
||||
# Check if a package version exists in the registry.
|
||||
# Gitea npm API: GET /{encoded_name} returns all versions.
|
||||
registry_version_exists() {
|
||||
local name="$1" version="$2"
|
||||
local encoded_name="${name/@/%40}"
|
||||
encoded_name="${encoded_name//\//%2F}"
|
||||
local meta
|
||||
meta=$(curl -s -H "Authorization: token $TOKEN" \
|
||||
"${REGISTRY_URL}${encoded_name}" 2>/dev/null) || return 1
|
||||
echo "$meta" | node -e "
|
||||
let d='';process.stdin.on('data',c=>d+=c);
|
||||
process.stdin.on('end',()=>{
|
||||
try{const p=JSON.parse(d);process.exit(p.versions&&p.versions['$version']?0:1)}
|
||||
catch(e){process.exit(1)}
|
||||
})" 2>/dev/null
|
||||
}
|
||||
|
||||
# Download a package tarball from the registry.
|
||||
# Gitea npm API: GET /{encoded_name} → versions.{version}.dist.tarball
|
||||
download_registry_tarball() {
|
||||
local name="$1" version="$2" dest_dir="$3"
|
||||
local encoded_name="${name/@/%40}"
|
||||
encoded_name="${encoded_name//\//%2F}"
|
||||
|
||||
# Fetch the full package metadata (all versions)
|
||||
local meta
|
||||
meta=$(curl -s -H "Authorization: token $TOKEN" \
|
||||
"${REGISTRY_URL}${encoded_name}" 2>/dev/null) || return 1
|
||||
|
||||
local tarball_url
|
||||
tarball_url=$(echo "$meta" | node -e "
|
||||
let d='';process.stdin.on('data',c=>d+=c);
|
||||
process.stdin.on('end',()=>{
|
||||
try{
|
||||
const p=JSON.parse(d);
|
||||
const v=p.versions&&p.versions['$version'];
|
||||
if(!v||!v.dist||!v.dist.tarball){process.exit(1)}
|
||||
process.stdout.write(v.dist.tarball)
|
||||
}catch(e){process.exit(1)}
|
||||
})" 2>/dev/null) || return 1
|
||||
|
||||
if [ -z "$tarball_url" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
curl -s -H "Authorization: token $TOKEN" \
|
||||
-o "$dest_dir/registry.tgz" \
|
||||
"$tarball_url" 2>/dev/null || return 1
|
||||
|
||||
[ -f "$dest_dir/registry.tgz" ] && [ -s "$dest_dir/registry.tgz" ]
|
||||
}
|
||||
|
||||
# Bump the patch version of a package.json (e.g., 0.1.0 → 0.1.1, 0.1.1 → 0.1.2).
|
||||
# Also finds the next available version not yet in the registry.
|
||||
bump_patch_version() {
|
||||
local pkg_json="$1" pkg_name="$2"
|
||||
local encoded_name="${pkg_name/@/%40}"
|
||||
encoded_name="${encoded_name//\//%2F}"
|
||||
|
||||
# Get all published versions from registry
|
||||
local published_versions
|
||||
published_versions=$(curl -s -H "Authorization: token $TOKEN" \
|
||||
"${REGISTRY_URL}${encoded_name}" 2>/dev/null | node -e "
|
||||
let d='';process.stdin.on('data',c=>d+=c);
|
||||
process.stdin.on('end',()=>{
|
||||
try{const p=JSON.parse(d);process.stdout.write(Object.keys(p.versions||{}).join(','))}
|
||||
catch(e){process.stdout.write('')}
|
||||
})" 2>/dev/null) || true
|
||||
|
||||
# Compute next available patch version
|
||||
node -e "
|
||||
const fs=require('fs');
|
||||
const pkg=JSON.parse(fs.readFileSync(process.argv[1],'utf8'));
|
||||
const published=new Set((process.argv[2]||'').split(',').filter(Boolean));
|
||||
const parts=pkg.version.split('.').map(Number);
|
||||
// Start from current patch+1 and find first unpublished
|
||||
parts[2]++;
|
||||
while(published.has(parts.join('.'))){parts[2]++}
|
||||
pkg.version=parts.join('.');
|
||||
fs.writeFileSync(process.argv[1],JSON.stringify(pkg,null,2)+'\n');
|
||||
process.stdout.write(pkg.version);
|
||||
" "$pkg_json" "$published_versions"
|
||||
const p=JSON.parse(fs.readFileSync(process.argv[1],'utf8'));
|
||||
p.version='0.0.0'; delete p.publishConfig;
|
||||
// Normalize @bytelyst/* dep versions (pnpm resolves workspace:* to exact versions
|
||||
// which change on every bump — these shouldn't trigger re-publish)
|
||||
for(const s of ['dependencies','devDependencies','peerDependencies']){
|
||||
if(!p[s])continue;
|
||||
for(const [n]of Object.entries(p[s])){
|
||||
if(n.startsWith('@bytelyst/'))p[s][n]='*';
|
||||
}
|
||||
}
|
||||
fs.writeFileSync(process.argv[2],JSON.stringify(p));
|
||||
" "$pkg_json" "$norm"
|
||||
|
||||
# Hash normalized package.json (via stdin — no path in output)
|
||||
# + all other files using relative paths (cd into package/ first)
|
||||
{
|
||||
echo "PKG $(shasum -a 256 < "$norm" | cut -d' ' -f1)"
|
||||
(cd "$extracted_dir/package" && find . -type f ! -name package.json -print0 \
|
||||
| sort -z | xargs -0 shasum -a 256 2>/dev/null) || true
|
||||
} | shasum -a 256 | cut -d' ' -f1
|
||||
rm -f "$norm"
|
||||
}
|
||||
|
||||
# Publish a package using the same double-pack pattern as publish-local-packages.sh.
|
||||
publish_package() {
|
||||
local pkg_dir="$1"
|
||||
local pkg_name pkg_version safe_name
|
||||
pkg_name="$(pkg_field name "$pkg_dir/package.json")"
|
||||
pkg_version="$(pkg_field version "$pkg_dir/package.json")"
|
||||
safe_name="${pkg_name//@/}"
|
||||
safe_name="${safe_name//\//-}"
|
||||
# ── Manifest Operations ───────────────────────────────────
|
||||
|
||||
local pub_dir="$WORK_DIR/publish-$safe_name"
|
||||
rm -rf "$pub_dir"
|
||||
mkdir -p "$pub_dir"
|
||||
|
||||
# Step 1: pnpm pack
|
||||
(cd "$pkg_dir" && pnpm pack --pack-destination "$pub_dir" >/dev/null 2>&1)
|
||||
local packed_tgz
|
||||
packed_tgz="$(find "$pub_dir" -maxdepth 1 -name '*.tgz' | head -1)"
|
||||
if [ -z "$packed_tgz" ]; then
|
||||
echo " ERROR: pnpm pack failed for $pkg_name"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Step 2: extract, strip publishConfig (so --registry wins), then npm repack
|
||||
mkdir -p "$pub_dir/unpacked"
|
||||
tar -xzf "$packed_tgz" -C "$pub_dir/unpacked"
|
||||
rm -f "$packed_tgz" # remove pnpm tgz so only npm-repacked tgz remains
|
||||
manifest_get_hash() {
|
||||
local name="$1"
|
||||
[ -f "$MANIFEST_FILE" ] || { echo ""; return; }
|
||||
node -e "
|
||||
const fs=require('fs'),f=process.argv[1];
|
||||
const p=JSON.parse(fs.readFileSync(f,'utf8'));
|
||||
delete p.publishConfig;
|
||||
fs.writeFileSync(f,JSON.stringify(p,null,2)+'\n');
|
||||
" "$pub_dir/unpacked/package/package.json"
|
||||
(cd "$pub_dir/unpacked/package" && npm pack --pack-destination "$pub_dir" >/dev/null 2>&1)
|
||||
try{const m=JSON.parse(require('fs').readFileSync(process.argv[1],'utf8'));
|
||||
process.stdout.write(m[process.argv[2]]?.contentHash||'')}
|
||||
catch(e){process.stdout.write('')}
|
||||
" "$MANIFEST_FILE" "$name"
|
||||
}
|
||||
|
||||
local final_tgz
|
||||
final_tgz="$(find "$pub_dir" -maxdepth 1 -name '*.tgz' | head -1)"
|
||||
if [ -z "$final_tgz" ]; then
|
||||
echo " ERROR: npm repack failed for $pkg_name"
|
||||
return 1
|
||||
fi
|
||||
manifest_set() {
|
||||
local name="$1" version="$2" hash="$3"
|
||||
node -e "
|
||||
const fs=require('fs');
|
||||
let m={};try{m=JSON.parse(fs.readFileSync(process.argv[1],'utf8'))}catch(e){}
|
||||
m[process.argv[2]]={version:process.argv[3],contentHash:process.argv[4],
|
||||
publishedAt:new Date().toISOString()};
|
||||
const s=Object.fromEntries(Object.entries(m).sort(([a],[b])=>a.localeCompare(b)));
|
||||
fs.writeFileSync(process.argv[1],JSON.stringify(s,null,2)+'\n');
|
||||
" "$MANIFEST_FILE" "$name" "$version" "$hash"
|
||||
}
|
||||
|
||||
# Step 3: publish to Gitea registry.
|
||||
# Run from WORK_DIR (in /tmp with .npmrc for auth) so npm won't find
|
||||
# the repo's .npmrc which has @bytelyst:registry pointing externally.
|
||||
# Publish using shared .npmrc (has auth, scoped registry, and proxy=false on corp)
|
||||
# Strip all proxy/registry env vars so only .npmrc settings apply
|
||||
if ! (cd "$WORK_DIR" && env \
|
||||
# ── Registry Helpers (single fetch, cached) ───────────────
|
||||
|
||||
# Cache file: one line per package = "name:ver1,ver2,ver3"
|
||||
REGISTRY_CACHE_FILE="$WORK_DIR/.registry-cache"
|
||||
: > "$REGISTRY_CACHE_FILE"
|
||||
|
||||
registry_versions() {
|
||||
local name="$1"
|
||||
# Check cache first
|
||||
local cached
|
||||
cached=$(grep "^${name}:" "$REGISTRY_CACHE_FILE" 2>/dev/null | cut -d: -f2-) || true
|
||||
if [ -n "$cached" ]; then echo "$cached"; return; fi
|
||||
|
||||
local encoded="${name/@/%40}"; encoded="${encoded//\//%2F}"
|
||||
local versions
|
||||
versions=$(curl -s -H "Authorization: token $TOKEN" \
|
||||
"${REGISTRY_URL}${encoded}" 2>/dev/null \
|
||||
| node -e "let d='';process.stdin.on('data',c=>d+=c);
|
||||
process.stdin.on('end',()=>{try{
|
||||
process.stdout.write(Object.keys(JSON.parse(d).versions||{}).join(','))
|
||||
}catch(e){process.stdout.write('')}})" 2>/dev/null) || true
|
||||
echo "${name}:${versions}" >> "$REGISTRY_CACHE_FILE"
|
||||
echo "$versions"
|
||||
}
|
||||
|
||||
next_version() {
|
||||
local name="$1" current="$2"
|
||||
local versions; versions=$(registry_versions "$name")
|
||||
node -e "
|
||||
const pub=new Set((process.argv[1]||'').split(',').filter(Boolean));
|
||||
const p=process.argv[2].split('.').map(Number);
|
||||
p[2]++;while(pub.has(p.join('.'))){p[2]++}
|
||||
process.stdout.write(p.join('.'));
|
||||
" "$versions" "$current"
|
||||
}
|
||||
|
||||
version_exists() {
|
||||
local name="$1" version="$2"
|
||||
local versions; versions=$(registry_versions "$name")
|
||||
echo ",$versions," | grep -q ",$version,"
|
||||
}
|
||||
|
||||
# Run npm commands with proxy/env stripping for reliable localhost access
|
||||
npm_clean() {
|
||||
(cd "$WORK_DIR" && env \
|
||||
-u http_proxy -u https_proxy -u HTTP_PROXY -u HTTPS_PROXY \
|
||||
-u npm_config_proxy -u npm_config_https_proxy \
|
||||
-u NPM_CONFIG_PROXY -u NPM_CONFIG_HTTPS_PROXY \
|
||||
-u NPM_CONFIG_REGISTRY -u NPM_CONFIG_STRICT_SSL \
|
||||
-u NPM_CONFIG_NOPROXY \
|
||||
-u NODE_TLS_REJECT_UNAUTHORIZED \
|
||||
npm publish "$final_tgz" \
|
||||
--registry "$REGISTRY_URL" \
|
||||
--userconfig "$NPMRC_FILE" 2>&1); then
|
||||
echo " ERROR: publish failed for $pkg_name@$pkg_version"
|
||||
return 1
|
||||
fi
|
||||
-u NPM_CONFIG_NOPROXY -u NODE_TLS_REJECT_UNAUTHORIZED \
|
||||
"$@")
|
||||
}
|
||||
|
||||
# ── Main ───────────────────────────────────────────────────
|
||||
|
||||
# Show resolved config
|
||||
echo "==> Network: $NETWORK_MODE ($( [ "$IS_CORP" = true ] && echo "corp — localhost tunnel" || echo "home — Azure VM" ))"
|
||||
echo " Registry: $REGISTRY_URL"
|
||||
echo ""
|
||||
|
||||
# Step 1: Build all packages
|
||||
# Phase 1: Build
|
||||
if [ "$SKIP_BUILD" = false ]; then
|
||||
echo "==> Building all packages..."
|
||||
(cd "$REPO_ROOT" && pnpm build 2>&1 | tail -5)
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Step 2: Check each package
|
||||
echo "==> Checking packages against registry..."
|
||||
# Phase 2: Check each package against manifest
|
||||
echo "==> Checking packages (manifest-based)..."
|
||||
echo ""
|
||||
|
||||
# Arrays for tracking results
|
||||
outdated_dirs=()
|
||||
outdated_names=()
|
||||
outdated_hashes=() # content hash per outdated package (for manifest update after publish)
|
||||
up_to_date=0
|
||||
not_found=0
|
||||
changed=0
|
||||
skipped=0
|
||||
errors=0
|
||||
@ -291,76 +253,66 @@ for pkg_json in "$PACKAGES_DIR"/*/package.json; do
|
||||
|
||||
# Skip native SDKs
|
||||
if echo "$SKIP_DIRS" | grep -qw "$dir_name"; then
|
||||
((skipped++))
|
||||
continue
|
||||
((skipped++)); continue
|
||||
fi
|
||||
|
||||
pkg_name="$(pkg_field name "$pkg_json")"
|
||||
pkg_version="$(pkg_field version "$pkg_json")"
|
||||
|
||||
# Skip private packages
|
||||
private_flag="$(pkg_field private "$pkg_json")"
|
||||
if [ "$private_flag" = "true" ]; then
|
||||
((skipped++)); continue
|
||||
fi
|
||||
|
||||
# Apply filter
|
||||
if [ -n "$PACKAGE_FILTER" ] && [ "$pkg_name" != "$PACKAGE_FILTER" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Check if dist/ exists (package must be built)
|
||||
# Must have built output
|
||||
if [ ! -d "$pkg_dir/dist" ] && [ ! -d "$pkg_dir/generated" ]; then
|
||||
echo " SKIP (no dist/): $pkg_name"
|
||||
((skipped++))
|
||||
continue
|
||||
((skipped++)); continue
|
||||
fi
|
||||
|
||||
# Prepare work dirs
|
||||
local_work="$WORK_DIR/check-$dir_name/local"
|
||||
registry_work="$WORK_DIR/check-$dir_name/registry"
|
||||
rm -rf "$WORK_DIR/check-$dir_name"
|
||||
mkdir -p "$local_work" "$registry_work"
|
||||
# Pack locally (single pack — reused for publish if needed)
|
||||
safe_name="${pkg_name//@/}"; safe_name="${safe_name//\//-}"
|
||||
pack_dir="$WORK_DIR/$safe_name"
|
||||
rm -rf "$pack_dir"; mkdir -p "$pack_dir/extracted"
|
||||
|
||||
# Pack locally
|
||||
if ! (cd "$pkg_dir" && pnpm pack --pack-destination "$local_work" >/dev/null 2>&1); then
|
||||
echo " ERROR (pack failed): $pkg_name"
|
||||
((errors++))
|
||||
continue
|
||||
if ! (cd "$pkg_dir" && pnpm pack --pack-destination "$pack_dir" >/dev/null 2>&1); then
|
||||
echo " ERROR (pack): $pkg_name"
|
||||
((errors++)); continue
|
||||
fi
|
||||
local_tgz="$(find "$local_work" -maxdepth 1 -name '*.tgz' | head -1)"
|
||||
local_tgz="$(find "$pack_dir" -maxdepth 1 -name '*.tgz' | head -1)"
|
||||
if [ -z "$local_tgz" ]; then
|
||||
echo " ERROR (no tgz): $pkg_name"
|
||||
((errors++))
|
||||
continue
|
||||
((errors++)); continue
|
||||
fi
|
||||
|
||||
# Extract local tarball
|
||||
mkdir -p "$local_work/extracted"
|
||||
tar xzf "$local_tgz" -C "$local_work/extracted" 2>/dev/null
|
||||
# Extract for content hashing (keep around for publish)
|
||||
tar xzf "$local_tgz" -C "$pack_dir/extracted" 2>/dev/null
|
||||
|
||||
# Try to download registry tarball
|
||||
if download_registry_tarball "$pkg_name" "$pkg_version" "$registry_work"; then
|
||||
# Extract registry tarball
|
||||
mkdir -p "$registry_work/extracted"
|
||||
tar xzf "$registry_work/registry.tgz" -C "$registry_work/extracted" 2>/dev/null
|
||||
# Compute content hash
|
||||
local_hash="$(content_hash "$pack_dir/extracted")"
|
||||
manifest_hash="$(manifest_get_hash "$pkg_name")"
|
||||
|
||||
# Compare content fingerprints
|
||||
local_fp="$(content_fingerprint "$local_work/extracted")"
|
||||
registry_fp="$(content_fingerprint "$registry_work/extracted")"
|
||||
|
||||
if [ "$local_fp" = "$registry_fp" ]; then
|
||||
if [ "$local_hash" = "$manifest_hash" ]; then
|
||||
echo " UP-TO-DATE: $pkg_name@$pkg_version"
|
||||
((up_to_date++))
|
||||
rm -rf "$pack_dir" # free disk
|
||||
else
|
||||
echo " OUTDATED: $pkg_name@$pkg_version"
|
||||
if [ -z "$manifest_hash" ]; then
|
||||
echo " NEW: $pkg_name@$pkg_version"
|
||||
else
|
||||
echo " CHANGED: $pkg_name@$pkg_version"
|
||||
fi
|
||||
outdated_dirs+=("$pkg_dir")
|
||||
outdated_names+=("$pkg_name@$pkg_version")
|
||||
outdated_names+=("$pkg_name")
|
||||
outdated_hashes+=("$local_hash")
|
||||
((changed++))
|
||||
fi
|
||||
else
|
||||
echo " NOT FOUND: $pkg_name@$pkg_version (will publish)"
|
||||
outdated_dirs+=("$pkg_dir")
|
||||
outdated_names+=("$pkg_name@$pkg_version")
|
||||
((not_found++))
|
||||
fi
|
||||
|
||||
# Cleanup check dir to save disk space
|
||||
rm -rf "$WORK_DIR/check-$dir_name"
|
||||
done
|
||||
|
||||
# ── Summary ────────────────────────────────────────────────
|
||||
@ -368,8 +320,7 @@ done
|
||||
echo ""
|
||||
echo "==> Summary"
|
||||
echo " Up-to-date: $up_to_date"
|
||||
echo " Outdated: $changed"
|
||||
echo " Not found: $not_found"
|
||||
echo " Changed: $changed"
|
||||
echo " Skipped: $skipped"
|
||||
echo " Errors: $errors"
|
||||
echo ""
|
||||
@ -390,59 +341,97 @@ if [ "$DRY_RUN" = true ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Step 3: Publish outdated packages
|
||||
# Phase 3: Publish changed packages
|
||||
echo "==> Publishing ${#outdated_dirs[@]} package(s)..."
|
||||
echo ""
|
||||
|
||||
# Write .npmrc into WORK_DIR for auth (npm reads .npmrc from cwd)
|
||||
cat > "$WORK_DIR/.npmrc" <<EOF
|
||||
//${AUTH_TARGET}:_authToken=${TOKEN}
|
||||
EOF
|
||||
|
||||
published=0
|
||||
pub_errors=0
|
||||
bumped_packages=()
|
||||
|
||||
for i in "${!outdated_dirs[@]}"; do
|
||||
pkg_dir="${outdated_dirs[$i]}"
|
||||
pkg_name="$(pkg_field name "$pkg_dir/package.json")"
|
||||
pkg_name="${outdated_names[$i]}"
|
||||
local_hash="${outdated_hashes[$i]}"
|
||||
pkg_version="$(pkg_field version "$pkg_dir/package.json")"
|
||||
safe_name="${pkg_name//@/}"; safe_name="${safe_name//\//-}"
|
||||
pack_dir="$WORK_DIR/$safe_name"
|
||||
|
||||
echo " [$((i+1))/${#outdated_dirs[@]}] $pkg_name@$pkg_version"
|
||||
|
||||
# If version already exists in registry, bump patch version
|
||||
if registry_version_exists "$pkg_name" "$pkg_version"; then
|
||||
echo " Version $pkg_version exists in registry, bumping patch..."
|
||||
new_version="$(bump_patch_version "$pkg_dir/package.json" "$pkg_name")"
|
||||
echo " Bumped to $new_version"
|
||||
bumped_packages+=("$pkg_dir")
|
||||
# Find next available version if current already exists
|
||||
if version_exists "$pkg_name" "$pkg_version"; then
|
||||
new_version="$(next_version "$pkg_name" "$pkg_version")"
|
||||
echo " Version $pkg_version exists, bumping to $new_version"
|
||||
|
||||
# Update source package.json
|
||||
node -e "
|
||||
const fs=require('fs'),f=process.argv[1];
|
||||
const p=JSON.parse(fs.readFileSync(f,'utf8'));
|
||||
p.version=process.argv[2];
|
||||
fs.writeFileSync(f,JSON.stringify(p,null,2)+'\n');
|
||||
" "$pkg_dir/package.json" "$new_version"
|
||||
bumped_packages+=("$pkg_dir/package.json")
|
||||
pkg_version="$new_version"
|
||||
|
||||
# Also update the extracted tarball's package.json (for repack)
|
||||
node -e "
|
||||
const fs=require('fs'),f=process.argv[1];
|
||||
const p=JSON.parse(fs.readFileSync(f,'utf8'));
|
||||
p.version=process.argv[2];
|
||||
fs.writeFileSync(f,JSON.stringify(p,null,2)+'\n');
|
||||
" "$pack_dir/extracted/package/package.json" "$new_version"
|
||||
fi
|
||||
|
||||
# Re-read version after potential bump
|
||||
pkg_version="$(pkg_field version "$pkg_dir/package.json")"
|
||||
# Strip publishConfig from extracted package.json (for npm repack)
|
||||
node -e "
|
||||
const fs=require('fs'),f=process.argv[1];
|
||||
const p=JSON.parse(fs.readFileSync(f,'utf8'));
|
||||
delete p.publishConfig;
|
||||
fs.writeFileSync(f,JSON.stringify(p,null,2)+'\n');
|
||||
" "$pack_dir/extracted/package/package.json"
|
||||
|
||||
# Repack with npm (from already-extracted content — no second pnpm pack)
|
||||
rm -f "$pack_dir"/*.tgz
|
||||
if ! (cd "$pack_dir/extracted/package" && npm pack --pack-destination "$pack_dir" >/dev/null 2>&1); then
|
||||
echo " ERROR: npm repack failed"
|
||||
((pub_errors++)); continue
|
||||
fi
|
||||
|
||||
final_tgz="$(find "$pack_dir" -maxdepth 1 -name '*.tgz' | head -1)"
|
||||
if [ -z "$final_tgz" ]; then
|
||||
echo " ERROR: no tarball after repack"
|
||||
((pub_errors++)); continue
|
||||
fi
|
||||
|
||||
# Publish
|
||||
echo " Publishing $pkg_name@$pkg_version..."
|
||||
if publish_package "$pkg_dir"; then
|
||||
if npm_clean npm publish "$final_tgz" \
|
||||
--registry "$REGISTRY_URL" \
|
||||
--userconfig "$NPMRC_FILE" 2>&1; then
|
||||
echo " Published $pkg_name@$pkg_version"
|
||||
manifest_set "$pkg_name" "$pkg_version" "$local_hash"
|
||||
((published++))
|
||||
else
|
||||
echo " FAILED to publish $pkg_name@$pkg_version"
|
||||
((pub_errors++))
|
||||
fi
|
||||
|
||||
# Free disk
|
||||
rm -rf "$pack_dir"
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo "==> Done: $published published, $pub_errors failed"
|
||||
|
||||
# Show bumped packages so the user knows which package.json files changed
|
||||
if [ ${#bumped_packages[@]} -gt 0 ]; then
|
||||
echo ""
|
||||
echo "NOTE: ${#bumped_packages[@]} package(s) had their patch version bumped."
|
||||
echo " These package.json changes are local — commit them when ready:"
|
||||
for d in "${bumped_packages[@]}"; do
|
||||
echo " $d/package.json"
|
||||
echo "NOTE: ${#bumped_packages[@]} package(s) had their version bumped."
|
||||
echo " Commit these + the manifest when ready:"
|
||||
for f in "${bumped_packages[@]}"; do
|
||||
echo " $f"
|
||||
done
|
||||
echo " $MANIFEST_FILE"
|
||||
fi
|
||||
|
||||
exit $((pub_errors > 0 ? 1 : 0))
|
||||
|
||||
@ -97,14 +97,20 @@ is_skip_package() {
|
||||
return 1
|
||||
}
|
||||
|
||||
# Check registry using shared npmrc (reliable auth for both GET and PUT)
|
||||
# Check registry using shared npmrc (reliable auth, proxy stripped)
|
||||
version_on_registry() {
|
||||
local name="$1" version="$2"
|
||||
(cd "$TMP_DIR" && env \
|
||||
-u http_proxy -u https_proxy -u HTTP_PROXY -u HTTPS_PROXY \
|
||||
-u npm_config_proxy -u npm_config_https_proxy \
|
||||
-u NPM_CONFIG_PROXY -u NPM_CONFIG_HTTPS_PROXY \
|
||||
-u NPM_CONFIG_REGISTRY -u NPM_CONFIG_STRICT_SSL \
|
||||
-u NPM_CONFIG_NOPROXY -u NODE_TLS_REJECT_UNAUTHORIZED \
|
||||
npm view "${name}@${version}" version \
|
||||
--registry "$REGISTRY_URL" \
|
||||
--userconfig "$NPMRC_FILE" \
|
||||
--silent \
|
||||
2>/dev/null || true
|
||||
2>/dev/null) || true
|
||||
}
|
||||
|
||||
# ── Preflight ──────────────────────────────────────────────────────────────────
|
||||
@ -123,7 +129,13 @@ command -v node >/dev/null 2>&1 || fail "node not found in PATH"
|
||||
# Create shared tmp dir + npmrc early so version checks work before publishing
|
||||
mkdir -p "$TMP_DIR"
|
||||
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||
printf '//%s:_authToken=%s\n' "$AUTH_TARGET" "$TOKEN" > "$NPMRC_FILE"
|
||||
{
|
||||
printf '//%s:_authToken=%s\n' "$AUTH_TARGET" "$TOKEN"
|
||||
printf '@bytelyst:registry=%s\n' "$REGISTRY_URL"
|
||||
if [ "$IS_CORP" = true ]; then
|
||||
printf 'proxy=false\nhttps-proxy=false\n'
|
||||
fi
|
||||
} > "$NPMRC_FILE"
|
||||
|
||||
# Show resolved config
|
||||
log "Network: $NETWORK_MODE ($( [ "$IS_CORP" = true ] && echo "corp — localhost tunnel" || echo "home — Azure VM" ))"
|
||||
@ -131,11 +143,17 @@ info "Registry: $REGISTRY_URL"
|
||||
|
||||
# Verify token can read from registry
|
||||
log "Verifying registry credentials..."
|
||||
if ! npm view "@bytelyst/errors" version \
|
||||
if ! (cd "$TMP_DIR" && env \
|
||||
-u http_proxy -u https_proxy -u HTTP_PROXY -u HTTPS_PROXY \
|
||||
-u npm_config_proxy -u npm_config_https_proxy \
|
||||
-u NPM_CONFIG_PROXY -u NPM_CONFIG_HTTPS_PROXY \
|
||||
-u NPM_CONFIG_REGISTRY -u NPM_CONFIG_STRICT_SSL \
|
||||
-u NPM_CONFIG_NOPROXY -u NODE_TLS_REJECT_UNAUTHORIZED \
|
||||
npm view "@bytelyst/errors" version \
|
||||
--registry "$REGISTRY_URL" \
|
||||
--userconfig "$NPMRC_FILE" \
|
||||
--silent 2>/dev/null; then
|
||||
fail "Registry auth failed — check GITEA_NPM_TOKEN has read:package scope"
|
||||
--silent 2>/dev/null); then
|
||||
fail "Registry auth failed — check GITEA_NPM_TOKEN has read+write:package scope"
|
||||
fi
|
||||
ok "Registry credentials verified"
|
||||
|
||||
@ -324,31 +342,21 @@ publish_package() {
|
||||
return
|
||||
fi
|
||||
|
||||
# Publish using shared npmrc (corp: strip proxy env so npm reaches localhost directly)
|
||||
# Publish using shared npmrc (strip proxy env so npm reaches localhost/VM directly)
|
||||
local publish_log="$work_dir/publish.log"
|
||||
local publish_ok=false
|
||||
if [ "$IS_CORP" = true ]; then
|
||||
if (cd "$work_dir" && env \
|
||||
if (cd "$TMP_DIR" && env \
|
||||
-u http_proxy -u https_proxy -u HTTP_PROXY -u HTTPS_PROXY \
|
||||
-u npm_config_proxy -u npm_config_https_proxy \
|
||||
-u NPM_CONFIG_PROXY -u NPM_CONFIG_HTTPS_PROXY \
|
||||
-u npm_config_noproxy -u NPM_CONFIG_NOPROXY \
|
||||
-u NODE_TLS_REJECT_UNAUTHORIZED \
|
||||
-u NPM_CONFIG_REGISTRY -u NPM_CONFIG_STRICT_SSL \
|
||||
-u NPM_CONFIG_NOPROXY -u NODE_TLS_REJECT_UNAUTHORIZED \
|
||||
npm publish "$final_tgz" \
|
||||
--registry "$REGISTRY_URL" \
|
||||
--userconfig "$NPMRC_FILE" \
|
||||
--silent 2>"$publish_log"); then
|
||||
publish_ok=true
|
||||
fi
|
||||
else
|
||||
if npm publish "$final_tgz" \
|
||||
--registry "$REGISTRY_URL" \
|
||||
--userconfig "$NPMRC_FILE" \
|
||||
--silent \
|
||||
2>"$publish_log"; then
|
||||
publish_ok=true
|
||||
fi
|
||||
fi
|
||||
if [ "$publish_ok" = true ]; then
|
||||
ok " ✅ $name@$version published"
|
||||
PUBLISHED+=("$name@$version")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user