chore: consolidate canary and release publish into single workflow (#… #1
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 TypeScript Packages | |
| on: | |
| push: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| inputs: | |
| publish-to-npm: | |
| description: 'Publish to npm registry' | |
| required: true | |
| default: true | |
| type: boolean | |
| create-github-release: | |
| description: 'Create GitHub release' | |
| required: true | |
| default: true | |
| type: boolean | |
| permissions: | |
| contents: write # Push tags, create releases | |
| id-token: write # npm provenance (OIDC) | |
| pull-requests: write # Comment on PRs | |
| # Prevent concurrent publishes | |
| concurrency: | |
| group: typescript-publish | |
| cancel-in-progress: false | |
| jobs: | |
| typescript-build: | |
| uses: ./.github/workflows/typescript-build.yml | |
| typescript-test: | |
| uses: ./.github/workflows/typescript-test.yml | |
| publish: | |
| name: Publish create-solana-dapp | |
| runs-on: ubuntu-latest | |
| needs: [typescript-build, typescript-test] | |
| env: | |
| NPM_CONFIG_PROVENANCE: true | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Setup Git user | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| - name: Install Dependencies | |
| uses: ./.github/workflows/actions/install-dependencies | |
| - name: Setup npm registry auth | |
| uses: actions/setup-node@v4 | |
| with: | |
| registry-url: 'https://registry.npmjs.org' | |
| - name: Determine publish type | |
| id: publish-type | |
| run: | | |
| if [ "${{ github.event_name }}" == "push" ]; then | |
| echo "type=canary" >> $GITHUB_OUTPUT | |
| echo "Publish type: canary (push to main)" | |
| else | |
| echo "type=release" >> $GITHUB_OUTPUT | |
| echo "Publish type: release (manual dispatch)" | |
| fi | |
| # --- Canary: snapshot version via changesets --- | |
| - name: Version as canary snapshot | |
| if: steps.publish-type.outputs.type == 'canary' | |
| run: pnpm changeset version --snapshot canary | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build | |
| run: pnpm build | |
| - name: Run type check | |
| run: pnpm test:types | |
| - name: Get version | |
| id: version | |
| run: | | |
| VERSION=$(node -p "require('./package.json').version") | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "Publishing version: $VERSION" | |
| - name: Determine npm tag | |
| id: npm-tag | |
| run: | | |
| TYPE="${{ steps.publish-type.outputs.type }}" | |
| VERSION="${{ steps.version.outputs.version }}" | |
| if [ "$TYPE" == "canary" ]; then | |
| echo "npm_tag=canary" >> $GITHUB_OUTPUT | |
| echo "is_prerelease=true" >> $GITHUB_OUTPUT | |
| elif [[ "$VERSION" == *"-"* ]]; then | |
| echo "npm_tag=beta" >> $GITHUB_OUTPUT | |
| echo "is_prerelease=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "npm_tag=latest" >> $GITHUB_OUTPUT | |
| echo "is_prerelease=false" >> $GITHUB_OUTPUT | |
| fi | |
| echo "npm tag: $(grep npm_tag $GITHUB_OUTPUT | tail -1)" | |
| - name: Pack tarball | |
| run: | | |
| mkdir -p .npm-pack | |
| pnpm pack --pack-destination .npm-pack | |
| echo "" | |
| echo "Packed tarball:" | |
| ls -la .npm-pack/ | |
| - name: 'Guard - Fail if tarball missing dist/ artifacts' | |
| run: | | |
| echo "Checking tarball for dist/ artifacts..." | |
| for tarball in .npm-pack/*.tgz; do | |
| CONTENTS=$(tar -tzf "$tarball") | |
| if ! echo "$CONTENTS" | grep -q "package/dist/index.mjs"; then | |
| echo "FAIL: ${tarball} is missing dist/index.mjs!" | |
| exit 1 | |
| fi | |
| if ! echo "$CONTENTS" | grep -q "package/dist/index.cjs"; then | |
| echo "FAIL: ${tarball} is missing dist/index.cjs!" | |
| exit 1 | |
| fi | |
| if ! echo "$CONTENTS" | grep -q "package/dist/index.d.ts"; then | |
| echo "FAIL: ${tarball} is missing dist/index.d.ts!" | |
| exit 1 | |
| fi | |
| if ! echo "$CONTENTS" | grep -q "package/dist/bin/index.cjs"; then | |
| echo "FAIL: ${tarball} is missing dist/bin/index.cjs (CLI entrypoint)!" | |
| exit 1 | |
| fi | |
| echo "All required dist/ artifacts present" | |
| done | |
| # --- Release only: tag + GitHub release --- | |
| - name: Create and push tag | |
| if: steps.publish-type.outputs.type == 'release' | |
| run: | | |
| TAG="v${{ steps.version.outputs.version }}" | |
| if git rev-parse "$TAG" >/dev/null 2>&1; then | |
| echo "Tag $TAG already exists, skipping" | |
| else | |
| git tag "$TAG" | |
| echo "Created tag $TAG" | |
| fi | |
| git push origin "$TAG" 2>/dev/null || echo "Tag already pushed" | |
| - name: Publish to npm | |
| if: steps.publish-type.outputs.type == 'canary' || github.event.inputs.publish-to-npm == 'true' | |
| run: | | |
| VERSION="${{ steps.version.outputs.version }}" | |
| NPM_TAG="${{ steps.npm-tag.outputs.npm_tag }}" | |
| TARBALL=$(ls .npm-pack/*.tgz | head -1) | |
| if [ -f "$TARBALL" ]; then | |
| echo "Publishing ${TARBALL} with tag '${NPM_TAG}'..." | |
| npm publish "$TARBALL" --access public --tag "$NPM_TAG" | |
| echo "Published successfully" | |
| else | |
| echo "Tarball not found. Available:" | |
| ls -la .npm-pack/ || true | |
| exit 1 | |
| fi | |
| - name: Create GitHub Release | |
| if: steps.publish-type.outputs.type == 'release' && github.event.inputs.create-github-release == 'true' | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const tagName = `v${{ steps.version.outputs.version }}`; | |
| const version = `${{ steps.version.outputs.version }}`; | |
| const releaseName = `create-solana-dapp v${version}`; | |
| const isPrerelease = '${{ steps.npm-tag.outputs.is_prerelease }}' === 'true'; | |
| const body = `## create-solana-dapp v${version} | |
| ### Installation | |
| \`\`\`bash | |
| npx create-solana-dapp@${version} | |
| \`\`\` | |
| `; | |
| // Check if release already exists | |
| try { | |
| await github.rest.repos.getReleaseByTag({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| tag: tagName, | |
| }); | |
| console.log(`Release ${tagName} already exists, skipping`); | |
| return; | |
| } catch (e) { | |
| if (e.status !== 404) throw e; | |
| } | |
| await github.rest.repos.createRelease({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| tag_name: tagName, | |
| name: releaseName, | |
| body: body.trim(), | |
| draft: false, | |
| prerelease: isPrerelease, | |
| }); | |
| console.log(`Created release: ${releaseName}`); | |
| - name: Publish summary | |
| run: | | |
| TYPE="${{ steps.publish-type.outputs.type }}" | |
| VERSION="${{ steps.version.outputs.version }}" | |
| NPM_TAG="${{ steps.npm-tag.outputs.npm_tag }}" | |
| cat >> $GITHUB_STEP_SUMMARY << EOF | |
| ## TypeScript Package Published | |
| **Type**: \`${TYPE}\` | |
| **Version**: \`${VERSION}\` | |
| **Package**: \`create-solana-dapp\` | |
| **npm tag**: \`${NPM_TAG}\` | |
| EOF | |
| if [ "$TYPE" == "canary" ]; then | |
| echo "Canary published to npm: \`create-solana-dapp@${NPM_TAG}\`" >> $GITHUB_STEP_SUMMARY | |
| else | |
| if [ "${{ github.event.inputs.publish-to-npm }}" == "true" ]; then | |
| echo "Published to npm: https://www.npmjs.com/package/create-solana-dapp/v/${VERSION}" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "Skipped npm publish (dry run)" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| if [ "${{ github.event.inputs.create-github-release }}" == "true" ]; then | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "GitHub release created: https://github.com/${{ github.repository }}/releases/tag/v${VERSION}" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "Skipped GitHub release creation" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| fi |