name: build

on:
  pull_request:
    types: [opened, synchronize]
  merge_group:
    types: [checks_requested]
  push:
    # Always run on push to main. The build cache can only be reused
    # if it was saved by a run from the repository's default branch.
    # The run result will be identical to that from the merge queue
    # because the commit is identical, yet we need to perform it to
    # seed the build cache.
    branches:
      - main
  schedule:
    - cron: '0 0,12 * * *'  # Runs at 00:00 and 12:00 UTC daily

env:
  GOTESTSUM_FORMAT: github-actions

jobs:
  cleanups:
    runs-on:
      group: databricks-deco-testing-runner-group
      labels: ubuntu-latest-deco
    steps:
      - name: Clean up cache if running on schedule
        if: ${{ github.event_name == 'schedule' }}
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: gh cache delete --all --repo databricks/cli || true

  tests:
    needs: cleanups
    runs-on: ${{ matrix.os }}

    strategy:
      fail-fast: false
      matrix:
        os:
          - macos-latest
          - ubuntu-latest
          - windows-latest

    steps:
      - name: Checkout repository and submodules
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

      - name: Setup Go
        uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
        with:
          go-version: 1.23.4

      - name: Setup Python
        uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
        with:
          python-version: '3.9'

      - name: Install uv
        uses: astral-sh/setup-uv@887a942a15af3a7626099df99e897a18d9e5ab3a # v5.1.0

      - name: Run ruff
        uses: astral-sh/ruff-action@31a518504640beb4897d0b9f9e50a2a9196e75ba # v3.0.1
        with:
          version: "0.9.1"
          args: "format --check"

      - name: Set go env
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
          go install gotest.tools/gotestsum@v1.12.0

      - name: Pull external libraries
        run: |
          make vendor
          pip3 install wheel

      - name: Run tests with coverage
        run: make cover

  golangci:
    needs: cleanups
    name: lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
      - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
        with:
          go-version: 1.23.4
          # Use different schema from regular job, to avoid overwriting the same key
          cache-dependency-path: |
            go.sum
            .golangci.yaml
      - name: Run go mod tidy
        run: |
          go mod tidy
      - name: Fail on differences
        run: |
          # Exit with status code 1 if there are differences (i.e. unformatted files)
          git diff --exit-code
      - name: golangci-lint
        uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1
        with:
          version: v1.63.4
          args: --timeout=15m

  validate-bundle-schema:
    needs: cleanups
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

      - name: Setup Go
        uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
        with:
          go-version: 1.23.4
          # Use different schema from regular job, to avoid overwriting the same key
          cache-dependency-path: |
            go.sum
            bundle/internal/schema/*.*

      - name: Verify that the schema is up to date
        run: |
          if ! ( make schema && git diff --exit-code ); then
            echo "The schema is not up to date. Please run 'make schema' and commit the changes."
            exit 1
          fi

      # Github repo: https://github.com/ajv-validator/ajv-cli
      - name: Install ajv-cli
        run: npm install -g ajv-cli@5.0.0

      # Assert that the generated bundle schema is a valid JSON schema by using
      # ajv-cli to validate it against bundle configuration files.
      # By default the ajv-cli runs in strict mode which will fail if the schema
      # itself is not valid. Strict mode is more strict than the JSON schema
      # specification. See for details: https://ajv.js.org/options.html#strict-mode-options
      # The ajv-cli is configured to use the markdownDescription keyword which is not part of the JSON schema specification,
      # but is used in editors like VSCode to render markdown in the description field
      - name: Validate bundle schema
        run: |
          go run main.go bundle schema > schema.json

          # Add markdownDescription keyword to ajv
          echo "module.exports=function(a){a.addKeyword('markdownDescription')}" >> keywords.js

          for file in ./bundle/internal/schema/testdata/pass/*.yml; do
            ajv test -s schema.json -d $file --valid -c=./keywords.js
          done

          for file in ./bundle/internal/schema/testdata/fail/*.yml; do
            ajv test -s schema.json -d $file --invalid -c=./keywords.js
          done
