From 501f6fd0a259effe6fcce38c3c5e8da6b88b00fd Mon Sep 17 00:00:00 2001 From: Lembot Date: Sat, 13 Dec 2025 00:32:05 -0500 Subject: [PATCH 1/2] feat: add Verdaccio local npm registry for development MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds Verdaccio service for local npm package development, allowing packages like ai-delegate to be published and consumed locally without going through the GitLab registry. Usage: 1. Start Verdaccio: docker compose up -d verdaccio 2. Access web UI: http://localhost:4873 3. Publish packages: npm publish --registry http://localhost:4873 Related to #1 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- compose.override.yml | 51 +++++++++++++++++++++++++++++++++++++++++++ verdaccio/config.yaml | 32 +++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 compose.override.yml create mode 100644 verdaccio/config.yaml diff --git a/compose.override.yml b/compose.override.yml new file mode 100644 index 0000000..bcf0def --- /dev/null +++ b/compose.override.yml @@ -0,0 +1,51 @@ +services: + db: + image: registry.gitlab.syncad.com/peerverity/ratings/db:local + build: + context: ../ratings + dockerfile: docker/db/Dockerfile + flyway: + image: registry.gitlab.syncad.com/peerverity/ratings/flyway:local + build: + context: ../ratings + dockerfile: docker/flyway/Dockerfile + ui: + image: registry.gitlab.syncad.com/peerverity/ratings/ui:local + build: + context: ../ratings + dockerfile: docker/ui/Dockerfile + api: + image: registry.gitlab.syncad.com/peerverity/ratings/api:local + build: + context: ../ratings + dockerfile: docker/api/Dockerfile + caddy: + image: registry.gitlab.syncad.com/peerverity/ratings-stack/caddy:local + build: + context: ./caddy + dockerfile: Dockerfile + data-generator: + image: registry.gitlab.syncad.com/peerverity/data-generator/data-generator:local + build: + context: ../data-generator + dockerfile: docker/data-generator/Dockerfile + ai-delegate: + image: registry.gitlab.syncad.com/peerverity/ai-delegate/ai-delegate:local + build: + context: ../ai-delegate + dockerfile: docker/ai-delegate/Dockerfile + verdaccio: + image: verdaccio/verdaccio:5 + volumes: + - ./verdaccio/config.yaml:/verdaccio/conf/config.yaml:ro + - verdaccio-storage:/verdaccio/storage + ports: + - "4873:4873" + healthcheck: + test: ["CMD", "wget", "-q", "--spider", "http://localhost:4873/-/ping"] + interval: 10s + timeout: 5s + retries: 3 + +volumes: + verdaccio-storage: diff --git a/verdaccio/config.yaml b/verdaccio/config.yaml new file mode 100644 index 0000000..ed563d4 --- /dev/null +++ b/verdaccio/config.yaml @@ -0,0 +1,32 @@ +# Verdaccio configuration for local npm package development +storage: /verdaccio/storage/data +plugins: /verdaccio/plugins + +web: + title: PeerVerity Local Registry + +# Disable authentication requirement for local dev +auth: + htpasswd: + file: /verdaccio/storage/htpasswd + max_users: -1 + +uplinks: + npmjs: + url: https://registry.npmjs.org/ + +packages: + # PeerVerity packages - allow anonymous publish for local dev + '@peerverity/*': + access: $anonymous + publish: $anonymous + unpublish: $anonymous + proxy: npmjs + + # All other packages - proxy to npmjs + '**': + access: $all + publish: $authenticated + proxy: npmjs + +log: { type: stdout, format: pretty, level: info } -- GitLab From ef42425a0b99da02d8d0502cf158b81756ca3119 Mon Sep 17 00:00:00 2001 From: Lembot Date: Sun, 14 Dec 2025 20:08:47 -0500 Subject: [PATCH 2/2] Integrate Verdaccio into local/upstream mode scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of committing a static compose.override.yml, integrate Verdaccio into the existing mode:local/mode:upstream tooling: - config-local.js now adds Verdaccio service when verdaccio/config.yaml exists - config-upstream.js now removes Verdaccio service and volume when cleaning up - Removed static compose.override.yml from version control This approach follows the existing pattern where compose.override.yml is dynamically generated based on local development needs. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- compose.override.yml | 51 ------------------------ scripts/config-local.js | 79 +++++++++++++++++++++++++++++++------- scripts/config-upstream.js | 54 ++++++++++++++++++++++---- 3 files changed, 112 insertions(+), 72 deletions(-) delete mode 100644 compose.override.yml diff --git a/compose.override.yml b/compose.override.yml deleted file mode 100644 index bcf0def..0000000 --- a/compose.override.yml +++ /dev/null @@ -1,51 +0,0 @@ -services: - db: - image: registry.gitlab.syncad.com/peerverity/ratings/db:local - build: - context: ../ratings - dockerfile: docker/db/Dockerfile - flyway: - image: registry.gitlab.syncad.com/peerverity/ratings/flyway:local - build: - context: ../ratings - dockerfile: docker/flyway/Dockerfile - ui: - image: registry.gitlab.syncad.com/peerverity/ratings/ui:local - build: - context: ../ratings - dockerfile: docker/ui/Dockerfile - api: - image: registry.gitlab.syncad.com/peerverity/ratings/api:local - build: - context: ../ratings - dockerfile: docker/api/Dockerfile - caddy: - image: registry.gitlab.syncad.com/peerverity/ratings-stack/caddy:local - build: - context: ./caddy - dockerfile: Dockerfile - data-generator: - image: registry.gitlab.syncad.com/peerverity/data-generator/data-generator:local - build: - context: ../data-generator - dockerfile: docker/data-generator/Dockerfile - ai-delegate: - image: registry.gitlab.syncad.com/peerverity/ai-delegate/ai-delegate:local - build: - context: ../ai-delegate - dockerfile: docker/ai-delegate/Dockerfile - verdaccio: - image: verdaccio/verdaccio:5 - volumes: - - ./verdaccio/config.yaml:/verdaccio/conf/config.yaml:ro - - verdaccio-storage:/verdaccio/storage - ports: - - "4873:4873" - healthcheck: - test: ["CMD", "wget", "-q", "--spider", "http://localhost:4873/-/ping"] - interval: 10s - timeout: 5s - retries: 3 - -volumes: - verdaccio-storage: diff --git a/scripts/config-local.js b/scripts/config-local.js index 89b8919..debc7d0 100644 --- a/scripts/config-local.js +++ b/scripts/config-local.js @@ -3,8 +3,11 @@ * Add local build overrides to compose.override.yml * Automatically discovers services with Dockerfiles in the workspace * Preserves any existing user customizations + * Also adds Verdaccio for local npm package development */ +const fs = require('fs'); +const path = require('path'); const { OVERRIDE_FILE, readYamlFile, @@ -13,12 +16,59 @@ const { discoverLocalBuilds } = require('./compose-utils'); +/** + * Get Verdaccio service configuration for local development + */ +function getVerdaccioConfig() { + const configPath = path.join(__dirname, '..', 'verdaccio', 'config.yaml'); + if (!fs.existsSync(configPath)) { + return null; + } + + return { + services: { + verdaccio: { + image: 'verdaccio/verdaccio:5', + volumes: [ + './verdaccio/config.yaml:/verdaccio/conf/config.yaml:ro', + 'verdaccio-storage:/verdaccio/storage' + ], + ports: ['4873:4873'], + healthcheck: { + test: ['CMD', 'wget', '-q', '--spider', 'http://localhost:4873/-/ping'], + interval: '10s', + timeout: '5s', + retries: 3 + } + } + }, + volumes: { + 'verdaccio-storage': {} + } + }; +} + function main() { console.log('Discovering local build configurations...\n'); const { overrides, discovered, notFound } = discoverLocalBuilds(); - if (discovered.length === 0) { + // Read existing config (or empty if file doesn't exist) + const config = readYamlFile(OVERRIDE_FILE); + + // Deep merge local overrides into existing config + if (discovered.length > 0) { + deepMerge(config, overrides); + } + + // Add Verdaccio if config exists + const verdaccioConfig = getVerdaccioConfig(); + if (verdaccioConfig) { + deepMerge(config, verdaccioConfig); + console.log('Verdaccio local npm registry added.\n'); + } + + if (discovered.length === 0 && !verdaccioConfig) { console.log('No local Dockerfiles found for any services.'); if (notFound.length > 0) { console.log('\nServices without local Dockerfiles:'); @@ -29,22 +79,25 @@ function main() { return; } - // Read existing config (or empty if file doesn't exist) - const config = readYamlFile(OVERRIDE_FILE); - - // Deep merge local overrides into existing config - deepMerge(config, overrides); - // Write the result writeYamlFile(OVERRIDE_FILE, config); console.log('Local build configuration applied to compose.override.yml\n'); - console.log('Services configured for local build:'); - for (const service of discovered) { - const buildConfig = overrides.services[service].build; - console.log(` - ${service}`); - console.log(` context: ${buildConfig.context}`); - console.log(` dockerfile: ${buildConfig.dockerfile}`); + + if (discovered.length > 0) { + console.log('Services configured for local build:'); + for (const service of discovered) { + const buildConfig = overrides.services[service].build; + console.log(` - ${service}`); + console.log(` context: ${buildConfig.context}`); + console.log(` dockerfile: ${buildConfig.dockerfile}`); + } + } + + if (verdaccioConfig) { + console.log('\nVerdaccio local npm registry:'); + console.log(' - Web UI: http://localhost:4873'); + console.log(' - First time: npm adduser --registry http://localhost:4873'); } if (notFound.length > 0) { diff --git a/scripts/config-upstream.js b/scripts/config-upstream.js index 5915d04..b79d86c 100644 --- a/scripts/config-upstream.js +++ b/scripts/config-upstream.js @@ -3,6 +3,7 @@ * Remove local build overrides from compose.override.yml * Automatically discovers which services to clean up * Preserves any user customizations that are not part of local overrides + * Also removes Verdaccio local npm registry */ const fs = require('fs'); @@ -41,6 +42,34 @@ function removeLocalOverrides(config, managedServices) { return config; } +/** + * Remove Verdaccio service from config + */ +function removeVerdaccio(config) { + let removed = false; + + if (config.services && config.services.verdaccio) { + delete config.services.verdaccio; + removed = true; + + // If services object is now empty, remove it + if (Object.keys(config.services).length === 0) { + delete config.services; + } + } + + if (config.volumes && config.volumes['verdaccio-storage']) { + delete config.volumes['verdaccio-storage']; + + // If volumes object is now empty, remove it + if (Object.keys(config.volumes).length === 0) { + delete config.volumes; + } + } + + return removed; +} + function main() { console.log('Removing local build overrides...\n'); @@ -53,17 +82,20 @@ function main() { // Discover which services we manage const managedServices = getManagedServiceNames(); - if (managedServices.length === 0) { - console.log('No manageable services discovered.'); - return; - } - // Read existing config let config = readYamlFile(OVERRIDE_FILE); // Remove local overrides config = removeLocalOverrides(config, managedServices); + // Remove Verdaccio + const verdaccioRemoved = removeVerdaccio(config); + + if (managedServices.length === 0 && !verdaccioRemoved) { + console.log('No manageable services discovered.'); + return; + } + // Write result (or delete file if empty) const wasDeleted = writeYamlFile(OVERRIDE_FILE, config); @@ -76,9 +108,15 @@ function main() { console.log('User customizations preserved.'); } - console.log('\nServices switched to upstream images:'); - for (const service of managedServices) { - console.log(` - ${service}`); + if (managedServices.length > 0) { + console.log('\nServices switched to upstream images:'); + for (const service of managedServices) { + console.log(` - ${service}`); + } + } + + if (verdaccioRemoved) { + console.log('\nVerdaccio local npm registry removed.'); } console.log('\nRun "docker compose pull" to fetch upstream images.'); -- GitLab