name: CI/CD Pipeline
on:
push:
branches:
- main
paths:
- 'package.json'
- 'src/**'
- 'tsconfig.json'
- 'Dockerfile'
- '.github/workflows/**'
pull_request:
branches:
- main
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
check-version:
runs-on: ubuntu-latest
outputs:
version-changed: ${{ steps.version-check.outputs.changed }}
version: ${{ steps.version-check.outputs.version }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Check if version changed
id: version-check
run: |
if git diff HEAD~1 HEAD --name-only | grep -q "package.json"; then
OLD_VERSION=$(git show HEAD~1:package.json | jq -r '.version')
NEW_VERSION=$(jq -r '.version' package.json)
if [ "$OLD_VERSION" != "$NEW_VERSION" ]; then
echo "changed=true" >> $GITHUB_OUTPUT
echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT
echo "Version changed from $OLD_VERSION to $NEW_VERSION"
else
echo "changed=false" >> $GITHUB_OUTPUT
echo "Package.json changed but version remained the same"
fi
else
echo "changed=false" >> $GITHUB_OUTPUT
echo "Package.json not changed"
fi
test-and-build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 10.13.1
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build
run: pnpm build
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
publish-npm:
needs: [test-and-build, check-version, create-git-tag]
runs-on: ubuntu-latest
if: needs.check-version.outputs.version-changed == 'true'
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 10.13.1
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: dist
path: dist/
- name: Publish to npm
run: pnpm publish --no-git-checks --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
create-git-tag:
needs: [test-and-build, check-version]
runs-on: ubuntu-latest
if: needs.check-version.outputs.version-changed == 'true'
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Create and push git tag
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
TAG="v${{ needs.check-version.outputs.version }}"
if git rev-parse "$TAG" >/dev/null 2>&1; then
echo "Tag $TAG already exists, skipping tag creation"
else
git tag "$TAG"
git push origin "$TAG"
echo "Created and pushed tag $TAG"
fi
build-and-push-docker:
needs: [test-and-build, check-version, create-git-tag]
runs-on: ubuntu-latest
if: needs.check-version.outputs.version-changed == 'true'
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=v${{ needs.check-version.outputs.version }}
type=raw,value=latest
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max