name: CI & Publish

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  codeql:
    name: CodeQL Analysis
    runs-on: ubuntu-latest
    permissions:
      actions: read
      security-events: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
      - name: Initialize CodeQL
        uses: github/codeql-action/init@v4
        with:
          languages: javascript
      - name: Autobuild
        uses: github/codeql-action/autobuild@v4
      - name: Perform CodeQL Analysis
        uses: github/codeql-action/analyze@v4

  build-and-test:
    name: Build & Test
    runs-on: ubuntu-latest
    needs: [codeql]
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: '22'
      
      - name: Install specific npm version
        run: npm install -g npm@11.13.0

      - name: Install dependencies
        run: npm ci --prefer-frozen-lockfile

      - name: Check lockfile drift
        run: npm run check:lockfile

      - name: Lint commit messages
        run: npx --no-install commitlint --from=HEAD~1 --to=HEAD

      - name: Lint code
        run: npm run lint

      - name: Check types
        run: npm run type-check

      - name: Check formatting
        run: npx prettier --check .

      - name: Run tests
        run: npm test

      - name: Detect duplicate code
        run: npx jscpd --threshold 20 src

      - name: Run CLI tests
        run: npm run test:cli

      - name: Run E2E CLI tests
        run: npm run test:cli -- test/cli.e2e.real-fixture.test.js

      - name: Ensure no repository changes post tests
        run: git diff --exit-code

      - name: Validate CLI version
        run: |
          expected=$(npm pkg get version | tr -d '"')
          actual=$(npx dry-aged-deps --version)
          if [ "$actual" != "$expected" ]; then
            echo "CLI version $actual does not match package.json version $expected"
            exit 1
          fi

      - name: Check outdated dependencies
        run: npm run check:deps

      - name: Vulnerability scan (all dependencies)
        run: npm run audit:ci

  publish:
    if: ${{ github.event_name == 'push' }}
    name: Release
    runs-on: ubuntu-latest
    needs: build-and-test
    permissions:
      contents: write
      issues: write
      pull-requests: write
      id-token: write
    env:
      HUSKY: 0
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: '22'

      - name: Install specific npm version
        run: npm install -g npm@11.13.0

      - name: Install dependencies
        run: npm ci --prefer-frozen-lockfile

      - name: Check lockfile drift
        run: npm run check:lockfile

      - name: Check tag matches version
        if: startsWith(github.ref, 'refs/tags/')
        run: |
          version=$(npm pkg get version | tr -d '"')
          tag="${GITHUB_REF#refs/tags/}"
          if [ "$tag" != "v$version" ]; then
            echo "Tag $tag does not match package.json version v$version"
            exit 1
          fi

      - name: Release
        run: npx semantic-release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

      - name: Smoke test published package
        run: |
          echo "Smoke testing dry-aged-deps CLI"
          workdir=$(mktemp -d)
          cd "$workdir"
          npm init -y > /dev/null
          npm install dry-aged-deps > /dev/null
          npx dry-aged-deps --version