diff --git a/.mokogitea/workflows/npm-publish.yml b/.mokogitea/workflows/npm-publish.yml new file mode 100644 index 0000000..87ffc3b --- /dev/null +++ b/.mokogitea/workflows/npm-publish.yml @@ -0,0 +1,113 @@ +# Copyright (C) 2026 Moko Consulting +# SPDX-License-Identifier: GPL-3.0-or-later + +name: "Publish to npm" + +on: + push: + branches: + - main + workflow_dispatch: + +env: + GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} + GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }} + GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }} + +jobs: + publish: + runs-on: ubuntu-latest + if: >- + !contains(github.event.head_commit.message, '[skip ci]') && + !contains(github.event.head_commit.message, '[skip publish]') + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + registry-url: 'https://registry.npmjs.org' + + - name: Install dependencies + run: npm install + + - name: Build + run: npm run build + + - name: Auto-bump patch version + run: | + API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" + TOKEN="${{ secrets.MOKOGITEA_TOKEN }}" + + PKG_NAME=$(node -p "require('./package.json').name") + CURRENT=$(node -p "require('./package.json').version") + PUBLISHED=$(npm view "${PKG_NAME}@latest" version 2>/dev/null || echo "0.0.0") + + if [ "$CURRENT" != "$PUBLISHED" ]; then + echo "Version ${CURRENT} not yet published, using as-is." + exit 0 + fi + + # Bump locally to get the new version + npm version patch --no-git-tag-version + NEW_VER=$(node -p "require('./package.json').version") + echo "Bumping ${CURRENT} -> ${NEW_VER}" + + # Push via Gitea API: branch + PR + merge + BRANCH="chore/npm-version-bump" + FILEPATH="package.json" + CONTENT=$(base64 -w 0 < package.json) + COMMIT_MSG="chore: bump to ${NEW_VER} [skip ci]" + + # Get current file SHA on main + FILE_SHA=$(curl -sf -H "Authorization: token ${TOKEN}" \ + "${API_BASE}/contents/${FILEPATH}?ref=main" \ + | python3 -c "import json,sys; print(json.load(sys.stdin).get('sha',''))" 2>/dev/null || true) + + # Create chore branch from main + curl -sf -X POST -H "Authorization: token ${TOKEN}" \ + -H "Content-Type: application/json" \ + "${API_BASE}/branches" \ + -d "{\"new_branch_name\":\"${BRANCH}\",\"old_branch_name\":\"main\"}" 2>/dev/null || true + + # Get file SHA on chore branch (may differ if branch already existed) + BRANCH_SHA=$(curl -sf -H "Authorization: token ${TOKEN}" \ + "${API_BASE}/contents/${FILEPATH}?ref=${BRANCH}" \ + | python3 -c "import json,sys; print(json.load(sys.stdin).get('sha',''))" 2>/dev/null || true) + [ -n "$BRANCH_SHA" ] && FILE_SHA="$BRANCH_SHA" + + # Push package.json to chore branch + PAYLOAD="{\"content\":\"${CONTENT}\",\"message\":\"${COMMIT_MSG}\",\"branch\":\"${BRANCH}\",\"sha\":\"${FILE_SHA}\"}" + HTTP=$(curl -sf -o /dev/null -w "%{http_code}" -X PUT \ + -H "Authorization: token ${TOKEN}" \ + -H "Content-Type: application/json" \ + -d "$PAYLOAD" \ + "${API_BASE}/contents/${FILEPATH}" 2>/dev/null || echo "ERR") + echo "File push: HTTP ${HTTP}" + + # Create PR + PR_NUM=$(curl -sf -X POST -H "Authorization: token ${TOKEN}" \ + -H "Content-Type: application/json" \ + "${API_BASE}/pulls" \ + -d "{\"title\":\"${COMMIT_MSG}\",\"head\":\"${BRANCH}\",\"base\":\"main\"}" \ + | python3 -c "import json,sys; print(json.load(sys.stdin).get('number',''))" 2>/dev/null || true) + + if [ -n "$PR_NUM" ]; then + # Merge PR + curl -sf -X POST -H "Authorization: token ${TOKEN}" \ + -H "Content-Type: application/json" \ + "${API_BASE}/pulls/${PR_NUM}/merge" \ + -d "{\"Do\":\"merge\",\"merge_message_field\":\"${COMMIT_MSG}\"}" 2>/dev/null + echo "Version bumped via PR #${PR_NUM} (merged)" + else + echo "::warning::Could not create PR for version bump — publishing with current version" + fi + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Publish + run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}