Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,22 @@ on:
branches: [main]

jobs:
# ── TypeScript SDK (typescript/core/) ──
# ── TypeScript SDK (typescript/packages/solana-pay/core/) ──
core-test:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./typescript/core
working-directory: ./typescript
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 10
- uses: actions/setup-node@v4
with:
node-version: lts/*
- run: npm install
- run: npm test
- run: pnpm install
- run: pnpm --filter @solana/pay test

# ── Rust CLI (rust/) ──
cli-check:
Expand Down
266 changes: 266 additions & 0 deletions .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
name: Publish @solana/pay

on:
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
id-token: write

# Prevent concurrent publishes
concurrency:
group: pay-publish
cancel-in-progress: false

jobs:
guard-main:
name: Guard main branch for publish
runs-on: ubuntu-latest
steps:
- name: Fail if workflow_dispatch is not on main
run: |
if [ "${{ github.ref }}" != "refs/heads/main" ]; then
echo "::error::Publish must be run from main. Current ref: ${{ github.ref }}"
exit 1
fi

publish:
name: Publish @solana/pay
runs-on: ubuntu-latest
needs: guard-main
env:
NPM_CONFIG_PROVENANCE: true
defaults:
run:
working-directory: typescript/packages/solana-pay/core

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"
working-directory: .

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 'lts/*'
registry-url: 'https://registry.npmjs.org'

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
run_install: false

- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV

- name: Setup pnpm cache
uses: actions/cache@v4
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('typescript/packages/solana-pay/core/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Get version
id: version
run: |
VERSION=$(node -p "require('./package.json').version")
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Publishing version: $VERSION"

- name: Check if prerelease
id: prerelease
run: |
if [[ "${{ steps.version.outputs.version }}" == *"-"* ]]; then
echo "is_prerelease=true" >> $GITHUB_OUTPUT
echo "npm_tag=beta" >> $GITHUB_OUTPUT
echo "Pre-release version detected, using 'beta' npm tag"
else
echo "is_prerelease=false" >> $GITHUB_OUTPUT
echo "npm_tag=latest" >> $GITHUB_OUTPUT
fi
working-directory: .

- name: Build
run: pnpm build

- name: Type check
run: pnpm typecheck

- name: Pack package
run: |
mkdir -p .npm-pack
pnpm pack --pack-destination .npm-pack
echo ""
echo "Packed tarball:"
ls -la .npm-pack/

- name: "Guard - Fail if tarball contains workspace: protocol"
run: |
echo "Checking tarball for workspace: protocol..."

for tarball in .npm-pack/*.tgz; do
tar -xzf "$tarball" package/package.json -O > /tmp/pkg.json

if grep -q '"workspace:' /tmp/pkg.json; then
echo "FAIL: ${tarball} contains workspace: dependencies!"
grep '"workspace:' /tmp/pkg.json || true
exit 1
fi
done

echo "All tarballs are clean (no workspace: dependencies)"

- 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.js"; then
echo "FAIL: Missing dist/index.js!"
exit 1
fi

if ! echo "$CONTENTS" | grep -q "package/dist/index.d.ts"; then
echo "FAIL: Missing dist/index.d.ts!"
exit 1
fi

echo "dist/index.js and dist/index.d.ts present"
done

echo "All tarballs contain required dist/ artifacts"

- name: Create and push tag
run: |
TAG="ts-pay-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"
working-directory: .

- name: Publish to npm
if: ${{ github.event.inputs.publish-to-npm == 'true' }}
run: |
VERSION="${{ steps.version.outputs.version }}"
NPM_TAG="${{ steps.prerelease.outputs.npm_tag }}"
TARBALL=".npm-pack/solana-pay-${VERSION}.tgz"

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: ${TARBALL}"
echo "Available tarballs:"
ls -la .npm-pack/ || true
exit 1
fi

- name: Create GitHub Release
if: ${{ github.event.inputs.create-github-release == 'true' }}
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const tagName = `ts-pay-v${{ steps.version.outputs.version }}`;
const version = `${{ steps.version.outputs.version }}`;
const releaseName = `@solana/pay v${version}`;
const isPrerelease = '${{ steps.prerelease.outputs.is_prerelease }}' === 'true';

const body = [
`## @solana/pay v${version}`,
'',
'### Installation',
'',
'```bash',
'pnpm add @solana/pay',
'```',
'',
`https://www.npmjs.com/package/@solana/pay/v/${version}`,
].join('\n');

// 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: |
VERSION="${{ steps.version.outputs.version }}"
NPM_TAG="${{ steps.prerelease.outputs.npm_tag }}"

cat >> $GITHUB_STEP_SUMMARY << EOF
## @solana/pay Published

**Version**: \`${VERSION}\`
**Package**: \`@solana/pay\`
**Tag**: \`ts-pay-v${VERSION}\`
**npm tag**: \`${NPM_TAG}\`

EOF

if [ "${{ github.event.inputs.publish-to-npm }}" == "true" ]; then
echo "Published to npm: https://www.npmjs.com/package/@solana/pay/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/ts-pay-v${VERSION}" >> $GITHUB_STEP_SUMMARY
else
echo "" >> $GITHUB_STEP_SUMMARY
echo "Skipped GitHub release creation" >> $GITHUB_STEP_SUMMARY
fi
working-directory: .
44 changes: 40 additions & 4 deletions .github/workflows/pull-requests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,43 @@ on:
pull_request:

jobs:
# ── TypeScript SDK (typescript/core/) ──
# ── TypeScript SDK (typescript/packages/solana-pay/core/) ──
lint:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./typescript

name: Lint, format, and typecheck

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: current

- name: Install Dependencies
run: pnpm install

- name: Lint
run: pnpm --filter @solana/pay lint

- name: Typecheck
run: pnpm --filter @solana/pay typecheck

unit-test:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./typescript/core
working-directory: ./typescript

strategy:
matrix:
Expand All @@ -23,16 +54,21 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}

- name: Install Dependencies
run: npm install
run: pnpm install

- name: Run unit tests
run: npm test
run: pnpm --filter @solana/pay test

# ── Rust CLI (rust/) ──
cli-check:
Expand Down
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ node_modules
build
.env
.next
package-lock.json
yarn.lock
pnpm-lock.yaml
!typescript/pnpm-lock.yaml
bun.lock
bun.lockb
tsconfig.tsbuildinfo
dist/

# Rust
rust/target
Expand Down
Loading
Loading