--- kind: pipeline type: docker name: build-and-publish-npm platform: os: linux arch: arm64 workspace: path: /drone/src steps: - name: check-version image: node:22-alpine environment: NPM_REPO_URL: from_secret: NPM_REPO_URL NPM_USERNAME: from_secret: NPM_USERNAME NPM_PASSWORD: from_secret: NPM_PASSWORD commands: - apk add --no-cache curl - | PACKAGE_NAME=$(node -p "require('./package.json').name") VERSION=$(node -p "require('./package.json').version") if [ "$DRONE_TAG" != "$VERSION" ]; then echo "Tag '$DRONE_TAG' does not match package.json version '$VERSION'; refusing to publish." exit 1 fi NPM_HOST=$(echo "$NPM_REPO_URL" | sed -E 's|^[a-z]+://||; s|/*$||') NPM_SCOPE="@$(node -p "require('./package.json').name.split('/')[0].replace(/^@/,'')")" echo "$NPM_SCOPE:registry=$NPM_REPO_URL" > /tmp/.npmrc echo "//$NPM_HOST/:_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> /tmp/.npmrc echo "Checking if $PACKAGE_NAME@$VERSION exists on $NPM_REPO_URL ..." if npm view "$PACKAGE_NAME@$VERSION" version --userconfig /tmp/.npmrc >/dev/null 2>&1; then echo "$PACKAGE_NAME@$VERSION already exists; skipping build." exit 78 else echo "New version detected: $PACKAGE_NAME@$VERSION" fi - name: quality-gate image: node:22-alpine environment: NPM_REPO_URL: from_secret: NPM_REPO_URL NPM_USERNAME: from_secret: NPM_USERNAME NPM_PASSWORD: from_secret: NPM_PASSWORD commands: - | if [ -z "$NPM_REPO_URL" ] || [ -z "$NPM_USERNAME" ] || [ -z "$NPM_PASSWORD" ]; then echo "NPM_REPO_URL / NPM_USERNAME / NPM_PASSWORD are not set" >&2 exit 1 fi NPM_HOST=$(echo "$NPM_REPO_URL" | sed -E 's|^[a-z]+://||; s|/*$||') NPM_SCOPE="@$(node -p "require('./package.json').name.split('/')[0].replace(/^@/,'')")" echo "$NPM_SCOPE:registry=$NPM_REPO_URL" > .npmrc echo "//$NPM_HOST/:_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> .npmrc - npm install - echo "Running quality gate..." - npm run quality-gate - name: build-package image: node:22-alpine commands: - npm install - echo "Building npm package..." - npm run build - ls -l dist - name: publish-to-private-npm image: node:22-alpine environment: NPM_REPO_URL: from_secret: NPM_REPO_URL NPM_USERNAME: from_secret: NPM_USERNAME NPM_PASSWORD: from_secret: NPM_PASSWORD commands: - | NPM_HOST=$(echo "$NPM_REPO_URL" | sed -E 's|^[a-z]+://||; s|/*$||') NPM_SCOPE="@$(node -p "require('./package.json').name.split('/')[0].replace(/^@/,'')")" echo "$NPM_SCOPE:registry=$NPM_REPO_URL" > .npmrc echo "//$NPM_HOST/:_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> .npmrc - echo "Publishing to private npm at $NPM_REPO_URL ..." - npm publish --access restricted trigger: event: - tag --- kind: pipeline type: docker name: backfill-npm-from-tags platform: os: linux arch: arm64 workspace: path: /drone/src steps: - name: fetch-tags image: alpine/git commands: - git fetch --tags --force - name: build-and-publish-missing image: node:22-alpine environment: NPM_REPO_URL: from_secret: NPM_REPO_URL NPM_USERNAME: from_secret: NPM_USERNAME NPM_PASSWORD: from_secret: NPM_PASSWORD commands: - apk add --no-cache git - | NPM_HOST=$(echo "$NPM_REPO_URL" | sed -E 's|^[a-z]+://||; s|/*$||') NPM_SCOPE="@$(node -p "require('./package.json').name.split('/')[0].replace(/^@/,'')")" echo "$NPM_SCOPE:registry=$NPM_REPO_URL" > /tmp/.npmrc echo "//$NPM_HOST/:_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> /tmp/.npmrc - | set -e PACKAGE_NAME=$(node -p "require('./package.json').name") echo "Package: $PACKAGE_NAME" for TAG in $(git tag --sort=version:refname); do VERSION="$TAG" echo "Version: $VERSION" if npm view "$PACKAGE_NAME@$VERSION" version --userconfig /tmp/.npmrc >/dev/null 2>&1; then echo "Exists, skipping" continue fi git checkout --force "$TAG" TAG_VERSION=$(node -p "require('./package.json').version") if [ "$TAG" != "$TAG_VERSION" ]; then echo "Tag $TAG != package.json version $TAG_VERSION at that commit; skipping" continue fi echo "Building $VERSION" rm -rf dist npm install npm run build echo "Publishing $VERSION" npm publish --access restricted --userconfig /tmp/.npmrc done trigger: event: - custom