ci.yml•7.13 kB
name: CI, Publish & Release
on:
push:
branches:
- main # Trigger on push to main branch
tags:
- 'v*.*.*' # Trigger on push of version tags (e.g., v0.5.5)
pull_request:
branches:
- main # Trigger on PR to main branch
jobs:
validate:
name: Validate Code Quality
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4.1.7
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: latest # Use the latest pnpm version
- name: Set up Node.js
uses: actions/setup-node@v4.0.3
with:
node-version: 'lts/*' # Use latest LTS
cache: 'pnpm' # Let pnpm handle caching via pnpm/action-setup
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Check Formatting
run: pnpm run check-format # Fails job if check fails
- name: Lint Code
run: pnpm run lint # Fails job if lint fails
- name: Run Tests and Check Coverage
run: pnpm run test:cov # Fails job if tests fail or coverage < 100%
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4.5.0 # Use Codecov action with fixed version
with:
token: ${{ secrets.CODECOV_TOKEN }} # Use Codecov token
files: ./coverage/lcov.info # Specify LCOV file path
fail_ci_if_error: true # Optional: fail CI if upload error
- name: Upload test results to Codecov
if: ${{ !cancelled() }}
uses: codecov/test-results-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
# No file specified, action defaults to common patterns like test-report.junit.xml
- name: Upload coverage reports
uses: actions/upload-artifact@v4.4.0
with:
name: coverage-report
path: coverage/ # Upload the whole coverage directory
build-archive:
name: Build and Archive Artifacts
needs: validate # Depends on successful validation
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v') # Only run for tags
outputs: # Define outputs for the release job
version: ${{ steps.get_version.outputs.version }}
artifact_path: ${{ steps.archive_build.outputs.artifact_path }}
steps:
- name: Checkout repository
uses: actions/checkout@v4.1.7
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: latest
- name: Set up Node.js
uses: actions/setup-node@v4.0.3
with:
node-version: 'lts/*' # Use latest LTS
registry-url: 'https://registry.npmjs.org/' # For pnpm publish
cache: 'pnpm' # Let pnpm handle caching
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build project
run: pnpm run build
- name: Get package version from tag
id: get_version
run: |
VERSION=$(echo "${{ github.ref }}" | sed 's#refs/tags/##')
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Archive build artifacts for release
id: archive_build
run: |
ARTIFACT_NAME="pdf-reader-mcp-${{ steps.get_version.outputs.version }}.tar.gz"
tar -czf $ARTIFACT_NAME dist package.json README.md LICENSE CHANGELOG.md
echo "artifact_path=$ARTIFACT_NAME" >> $GITHUB_OUTPUT
- name: Upload build artifact for release job
uses: actions/upload-artifact@v4.4.0
with:
name: release-artifact
path: ${{ steps.archive_build.outputs.artifact_path }}
# Publish steps moved to parallel jobs below
publish-npm:
name: Publish to NPM
needs: build-archive # Depends on build-archive completion
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v') # Only run for tags
steps:
- name: Checkout repository
uses: actions/checkout@v4.1.7
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: latest
- name: Set up Node.js for NPM
uses: actions/setup-node@v4.0.3
with:
node-version: 'lts/*'
registry-url: 'https://registry.npmjs.org/'
cache: 'pnpm'
# No need to install dependencies again if publish doesn't need them
# If pnpm publish needs package.json, it's checked out
- name: Install all dependencies for prepublishOnly script
run: pnpm install --frozen-lockfile
- name: Publish to npm
run: pnpm publish --access public --no-git-checks
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
publish-docker:
name: Publish to Docker Hub
needs: build-archive # Depends on build-archive completion
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v') # Only run for tags
steps:
- name: Checkout repository
uses: actions/checkout@v4.1.7
- name: Set up QEMU
uses: docker/setup-qemu-action@v3.2.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.5.0
- name: Log in to Docker Hub
uses: docker/login-action@v3.3.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5.5.1
with:
images: sylphlab/pdf-reader-mcp
# Use version from the build-archive job output
tags: |
type=semver,pattern={{version}},value=${{ needs.build-archive.outputs.version }}
type=semver,pattern={{major}}.{{minor}},value=${{ needs.build-archive.outputs.version }}
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/v') }}
- name: Build and push Docker image
uses: docker/build-push-action@v6.7.0
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
release:
name: Create GitHub Release
needs: [publish-npm, publish-docker] # Depends on successful parallel publishes
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v') # Only run for tags
permissions:
contents: write # Need permission to create releases and release notes
steps:
- name: Download build artifact
uses: actions/download-artifact@v4.1.8
with:
name: release-artifact
# No path specified, downloads to current directory
- name: Create GitHub Release
uses: softprops/action-gh-release@v2.0.6
with:
tag_name: ${{ github.ref_name }}
name: Release ${{ github.ref_name }}
generate_release_notes: true # Auto-generate release notes from commits
files: ${{ needs.build-archive.outputs.artifact_path }} # Attach the artifact archive from build-archive job
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}