name: Build and Push Docker Images on: push: branches: [main] tags: ['v*'] workflow_dispatch: inputs: tag: description: 'Image tag (leave empty for "latest")' required: false default: '' # Default minimal permissions permissions: contents: read env: REGISTRY: ghcr.io jobs: # ============================================================================= # Run Tests First # ============================================================================= backend-test: name: Backend Tests runs-on: ubuntu-latest permissions: contents: read defaults: run: working-directory: backend steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '22' cache: 'npm' cache-dependency-path: backend/package-lock.json - run: npm ci - run: npx tsc --noEmit - run: npm run test:run frontend-build: name: Frontend Build runs-on: ubuntu-latest permissions: contents: read defaults: run: working-directory: frontend steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '22' cache: 'npm' cache-dependency-path: frontend/package-lock.json - run: npm ci - run: npm run build # ============================================================================= # Build and Push Docker Images (only after tests pass) # ============================================================================= build-and-push: needs: [backend-test, frontend-build] runs-on: ubuntu-latest permissions: contents: read packages: write strategy: matrix: include: - context: ./backend image: backend - context: ./frontend image: frontend steps: - name: Checkout repository uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to Container Registry 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 }}/${{ github.repository_owner }}/medassist-ng-${{ matrix.image }} tags: | type=ref,event=branch type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=raw,value=${{ github.event.inputs.tag || 'latest' }},enable=${{ github.event_name == 'workflow_dispatch' }} type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} - name: Build and push uses: docker/build-push-action@v5 with: context: ${{ matrix.context }} push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max platforms: linux/amd64,linux/arm64 # ============================================================================= # Create GitHub Release (only on tag push) # ============================================================================= create-release: runs-on: ubuntu-latest needs: build-and-push if: startsWith(github.ref, 'refs/tags/v') permissions: contents: write steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 # Fetch all history for changelog generation - name: Get previous tag id: prev_tag run: | PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "") echo "tag=${PREV_TAG}" >> $GITHUB_OUTPUT - name: Generate changelog id: changelog run: | CURRENT_TAG=${GITHUB_REF#refs/tags/} PREV_TAG="${{ steps.prev_tag.outputs.tag }}" echo "## What's Changed" > changelog.md echo "" >> changelog.md if [ -n "$PREV_TAG" ]; then # Get commits between tags git log ${PREV_TAG}..${CURRENT_TAG} --pretty=format:"* %s (%h)" --no-merges >> changelog.md else # First release - get recent commits git log -20 --pretty=format:"* %s (%h)" --no-merges >> changelog.md fi echo "" >> changelog.md echo "" >> changelog.md echo "## Docker Images" >> changelog.md echo "" >> changelog.md echo '```bash' >> changelog.md echo "docker pull ghcr.io/${{ github.repository_owner }}/medassist-ng-backend:${CURRENT_TAG#v}" >> changelog.md echo "docker pull ghcr.io/${{ github.repository_owner }}/medassist-ng-frontend:${CURRENT_TAG#v}" >> changelog.md echo '```' >> changelog.md echo "" >> changelog.md echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${PREV_TAG}...${CURRENT_TAG}" >> changelog.md - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: body_path: changelog.md generate_release_notes: false draft: false prerelease: ${{ contains(github.ref, '-rc') || contains(github.ref, '-beta') || contains(github.ref, '-alpha') }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}