Publish New Package Version #57
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| name: Publish New Package Version | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| package: | |
| type: choice | |
| description: Package name | |
| options: | |
| - offchain-manager | |
| - addresses | |
| - indexer | |
| - mint-manager | |
| version: | |
| type: string | |
| description: "version" | |
| publish: | |
| type: boolean | |
| description: Publish to npm | |
| default: false | |
| changelog: | |
| type: string | |
| description: "Changelog (required if publishing, markdown format, do NOT include version or date header. Use sections like ### Added, ### Changed, etc.)" | |
| default: "" | |
| discord_notify: | |
| type: boolean | |
| description: "If checked, the release will notify on discord" | |
| default: false | |
| jobs: | |
| build-and-publish: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| id-token: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Use Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| registry-url: "https://registry.npmjs.org/" | |
| - name: Read previous version from package.json | |
| id: previous-version | |
| working-directory: packages/${{ inputs.package }} | |
| run: | | |
| version=$(jq -r '.version' package.json) | |
| echo "Previous version: $version" | |
| echo "version=$version" >> $GITHUB_OUTPUT | |
| - name: Extract new version from input | |
| id: current-version | |
| env: | |
| INPUT_VERSION: ${{ inputs.version }} | |
| run: | | |
| # Ensure semver format | |
| if [[ ! "$INPUT_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?$ ]]; then | |
| echo "❌ Invalid version format. Must follow semantic versioning (e.g., 1.2.3 or 1.2.3-suffix)" | |
| exit 1 | |
| fi | |
| version="${{ inputs.version }}" | |
| echo "Current version: $version" | |
| echo "version=$version" >> $GITHUB_OUTPUT | |
| - name: Check valid version increase | |
| uses: aleoyakas/check-semver-increased-action@v1 | |
| id: check-version | |
| with: | |
| current-version: ${{ steps.current-version.outputs.version }} | |
| previous-version: ${{ steps.previous-version.outputs.version }} | |
| - name: Fail if version not increased | |
| if: steps.check-version.outputs.is-version-increased != 'true' | |
| run: | | |
| echo "❌ Version has not increased. Please bump the version above ${{ steps.previous-version.outputs.version }}" | |
| exit 1 | |
| - name: Install dependencies | |
| run: npm ci | |
| # Build workspace dependencies first (in dependency order) | |
| - name: Build workspace dependencies | |
| run: | | |
| # Build addresses package first since mint-manager depends on it | |
| if [ "${{ inputs.package }}" = "mint-manager" ]; then | |
| echo "Building @thenamespace/addresses dependency..." | |
| npm run -w @thenamespace/addresses build | |
| fi | |
| # Add other workspace dependencies here as needed | |
| # Example: if a package depends on indexer, add: | |
| # if [ "${{ inputs.package }}" = "some-package" ]; then | |
| # echo "Building @thenamespace/indexer dependency..." | |
| # npm run -w @thenamespace/indexer build | |
| # fi | |
| # Future-proof: Check for any @thenamespace/* dependencies in package.json | |
| # and build them if they exist as workspace packages | |
| echo "Checking for other workspace dependencies..." | |
| WORKSPACE_DEPS=$(jq -r '.dependencies | keys[] | select(startswith("@thenamespace/"))' packages/${{ inputs.package }}/package.json 2>/dev/null || echo "") | |
| for dep in $WORKSPACE_DEPS; do | |
| if [ "$dep" != "@thenamespace/${{ inputs.package }}" ] && [ -d "packages/${dep#@thenamespace/}" ]; then | |
| echo "Building workspace dependency: $dep" | |
| npm run -w "$dep" build | |
| fi | |
| done | |
| - name: Build selected package | |
| working-directory: packages/${{ inputs.package }} | |
| run: npm run build | |
| - name: Update package version in package.json | |
| working-directory: packages/${{ inputs.package }} | |
| run: | | |
| npm version ${{ inputs.version }} --no-git-tag-version | |
| - name: Validate changelog if publishing | |
| if: ${{ inputs.publish == true }} | |
| run: | | |
| if [ -z "${{ inputs.changelog }}" ]; then | |
| echo "❌ Changelog is required when publishing." | |
| exit 1 | |
| fi | |
| - name: Publish package to npm registry | |
| if: ${{ inputs.publish == true }} | |
| working-directory: packages/${{ inputs.package }} | |
| run: npm publish --provenance --access public | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| - name: Commit and push version bump and tag | |
| if: ${{ inputs.publish == true }} | |
| env: | |
| VERSION: ${{ inputs.version }} | |
| CHANGELOG: ${{ inputs.changelog }} | |
| PACKAGE: ${{ inputs.package }} | |
| GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| echo "📝 Inserting changelog for $VERSION" | |
| FILE="changelog/${PACKAGE}-changelog.md" | |
| TEMP_FILE="${FILE}.tmp" | |
| DATE=$(date +'%Y-%m-%d') | |
| HEADER="## [${VERSION}] - ${DATE}" | |
| if [ ! -f "$FILE" ]; then | |
| echo -e "# Changelog\n" > "$FILE" | |
| fi | |
| # Find the line number of the "# Changelog" header | |
| HEADER_LINE=$(grep -n "^# Changelog" "$FILE" | cut -d: -f1) | |
| if [ -z "$HEADER_LINE" ]; then | |
| # If not found, just prepend | |
| HEADER_LINE=0 | |
| fi | |
| # Find the line number after the intro section (after the first blank line following '# Changelog') | |
| INTRO_END_LINE=$(awk '/^# Changelog/{flag=1; next} flag && /^$/{print NR; exit}' "$FILE") | |
| if [ -z "$INTRO_END_LINE" ]; then | |
| # Fallback: if not found, use header line | |
| HEADER_LINE=$(grep -n "^# Changelog" "$FILE" | cut -d: -f1) | |
| if [ -z "$HEADER_LINE" ]; then | |
| HEADER_LINE=0 | |
| fi | |
| INTRO_END_LINE=$((HEADER_LINE + 1)) | |
| fi | |
| # Process the changelog input to ensure proper formatting | |
| # Handle both multi-line and single-line input from GitHub UI | |
| PRETTY_CHANGELOG=$(echo "$CHANGELOG" | sed -E 's/\\n/\n/g' | sed -E 's/\\1/\n/g' | sed -E 's/^[[:space:]]*//' | sed -E 's/[[:space:]]*$//') | |
| # Write up to and including the intro | |
| if [ "$INTRO_END_LINE" -gt 0 ]; then | |
| head -n "$INTRO_END_LINE" "$FILE" > "$TEMP_FILE" | |
| fi | |
| # Add the new entry | |
| echo -e "\n${HEADER}\n\n${PRETTY_CHANGELOG}\n" >> "$TEMP_FILE" | |
| # Add the rest of the file | |
| if [ "$INTRO_END_LINE" -gt 0 ]; then | |
| tail -n "+$((INTRO_END_LINE + 1))" "$FILE" >> "$TEMP_FILE" | |
| fi | |
| mv "$TEMP_FILE" "$FILE" | |
| # Commit the updated package.json with new version | |
| git add packages/$PACKAGE/package.json | |
| git add changelog/* | |
| git commit -m "chore($PACKAGE): bump version to $VERSION" | |
| # Create a tag with the version | |
| TAG="${PACKAGE}-${VERSION}" | |
| git tag -a "$TAG" -m "Release $TAG" | |
| # Push commit and tag | |
| git push origin HEAD | |
| git push origin "$TAG" | |
| - name: Post update to Discord | |
| if: ${{ inputs.discord_notify == true }} | |
| env: | |
| DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK }} | |
| VERSION: ${{ inputs.version }} | |
| CHANGELOG: ${{ inputs.changelog }} | |
| PACKAGE: ${{ inputs.package }} | |
| run: | | |
| MESSAGE="Published a new version of *@thenamespace/${PACKAGE}*, version: \`${VERSION}\`!\n\n📝 ${CHANGELOG}" | |
| curl -X POST -H "Content-Type: application/json" \ | |
| -d "{\"content\": \"$MESSAGE\"}" \ | |
| "$DISCORD_WEBHOOK_URL" |