---
name: CI
on:
  pull_request:
  push:

permissions:
  contents: read

jobs:
  test_go:
    name: Go tests
    runs-on: ubuntu-latest
    container:
      # Whenever the Go version is updated here, .promu.yml
      # should also be updated.
      image: quay.io/prometheus/golang-builder:1.25-base
    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          persist-credentials: false
      - uses: prometheus/promci@443c7fc2397e946bc9f5029e313a9c3441b9b86d # v0.4.7
      - uses: ./.github/promci/actions/setup_environment
        with:
          enable_npm: true
      - run: make GO_ONLY=1 SKIP_GOLANGCI_LINT=1
      - run: go test ./tsdb/ -test.tsdb-isolation=false
      - run: make -C documentation/examples/remote_storage
      - run: make -C documentation/examples

  test_go_more:
    name: More Go tests
    runs-on: ubuntu-latest
    container:
      image: quay.io/prometheus/golang-builder:1.25-base
    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          persist-credentials: false
      - uses: prometheus/promci@443c7fc2397e946bc9f5029e313a9c3441b9b86d # v0.4.7
      - uses: ./.github/promci/actions/setup_environment
      - run: go test --tags=dedupelabels ./...
      - run: go test --tags=slicelabels -race ./cmd/prometheus ./model/textparse ./prompb/...
      - run: go test --tags=forcedirectio -race ./tsdb/
      - run: GOARCH=386 go test ./...
      - uses: ./.github/promci/actions/check_proto
        with:
          version: "3.15.8"

  test_go_oldest:
    name: Go tests with previous Go version
    runs-on: ubuntu-latest
    env:
      # Enforce the Go version.
      GOTOOLCHAIN: local
      # TODO: remove once 1.25 is the min version.
      GOEXPERIMENT: synctest
    container:
      # The go version in this image should be N-1 wrt test_go.
      image: quay.io/prometheus/golang-builder:1.24-base
    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          persist-credentials: false
      - run: make build
      # Don't run NPM build; don't run race-detector.
      - run: make test GO_ONLY=1 test-flags=""
      # TODO: remove once 1.25 is the min version.
      # ensure we can build without the tag.
      - run: GOEXPERIMENT="" make build

  test_ui:
    name: UI tests
    runs-on: ubuntu-latest
    # Whenever the Go version is updated here, .promu.yml
    # should also be updated.
    container:
      image: quay.io/prometheus/golang-builder:1.25-base

    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          persist-credentials: false
      - uses: prometheus/promci@443c7fc2397e946bc9f5029e313a9c3441b9b86d # v0.4.7
      - uses: ./.github/promci/actions/setup_environment
        with:
          enable_go: false
          enable_npm: true
      - run: make assets-tarball
      - run: make ui-lint
      - run: make ui-test
      - uses: ./.github/promci/actions/save_artifacts
        with:
          directory: .tarballs

  test_windows:
    name: Go tests on Windows
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          persist-credentials: false
      - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
        with:
          go-version: 1.25.x
      - run: |
          $TestTargets = go list ./... | Where-Object { $_ -NotMatch "(github.com/prometheus/prometheus/config|github.com/prometheus/prometheus/web)"}
          go test $TestTargets -vet=off -v
        shell: powershell

  test_mixins:
    name: Mixins tests
    runs-on: ubuntu-latest
    # Whenever the Go version is updated here, .promu.yml
    # should also be updated.
    container:
      image: quay.io/prometheus/golang-builder:1.25-base
    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          persist-credentials: false
      - run: go install ./cmd/promtool/.
      - run: go install github.com/google/go-jsonnet/cmd/jsonnet@latest
      - run: go install github.com/google/go-jsonnet/cmd/jsonnetfmt@latest
      - run: go install github.com/jsonnet-bundler/jsonnet-bundler/cmd/jb@latest
      - run: make -C documentation/prometheus-mixin clean
      - run: make -C documentation/prometheus-mixin jb_install
      - run: make -C documentation/prometheus-mixin
      - run: git diff --exit-code

  build:
    name: Build Prometheus for common architectures
    runs-on: ubuntu-latest
    if: |
      !(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v2.'))
      &&
      !(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v3.'))
      &&
      !(github.event_name == 'pull_request' && startsWith(github.event.pull_request.base.ref, 'release-'))
      &&
      !(github.event_name == 'push' && github.event.ref == 'refs/heads/main')
    strategy:
      matrix:
        thread: [ 0, 1, 2 ]
    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          persist-credentials: false
      - uses: prometheus/promci@443c7fc2397e946bc9f5029e313a9c3441b9b86d # v0.4.7
      - uses: ./.github/promci/actions/build
        with:
          promu_opts: "-p linux/amd64 -p windows/amd64 -p linux/arm64 -p darwin/amd64 -p darwin/arm64 -p linux/386"
          parallelism: 3
          thread: ${{ matrix.thread }}
  build_all:
    name: Build Prometheus for all architectures
    runs-on: ubuntu-latest
    if: |
      (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v2.'))
      ||
      (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v3.'))
      ||
      (github.event_name == 'pull_request' && startsWith(github.event.pull_request.base.ref, 'release-'))
      ||
      (github.event_name == 'push' && github.event.ref == 'refs/heads/main')
    strategy:
      matrix:
        thread: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ]

    # Whenever the Go version is updated here, .promu.yml
    # should also be updated.
    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          persist-credentials: false
      - uses: prometheus/promci@443c7fc2397e946bc9f5029e313a9c3441b9b86d # v0.4.7
      - uses: ./.github/promci/actions/build
        with:
          parallelism: 12
          thread: ${{ matrix.thread }}
  build_all_status:
    # This status check aggregates the individual matrix jobs of the "Build
    # Prometheus for all architectures" step into a final status. Fails if a
    # single matrix job fails, succeeds if all matrix jobs succeed.
    # See https://github.com/orgs/community/discussions/4324 for why this is
    # needed
    name: Report status of build Prometheus for all architectures
    runs-on: ubuntu-latest
    needs: [build_all]
    # The run condition needs to include always(). Otherwise actions
    # behave unexpected:
    # only "needs" will make the Status Report be skipped if one of the builds fails https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/using-jobs-in-a-workflow#defining-prerequisite-jobs
    # And skipped is treated as success https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborat[…]n-repositories-with-code-quality-features/about-status-checks
    # Adding always ensures that the status check is run independently of the
    # results of Build All
    if: always() && github.event_name == 'pull_request' && startsWith(github.event.pull_request.base.ref, 'release-')
    steps:
      - name: Successful build
        if: ${{ !(contains(needs.*.result, 'failure')) && !(contains(needs.*.result, 'cancelled')) }}
        run: exit 0
      - name: Failing or cancelled build
        if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
        run: exit 1
  check_generated_parser:
    name: Check generated parser
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          persist-credentials: false
      - name: Install Go
        uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
        with:
          cache: false
          go-version: 1.25.x
      - name: Run goyacc and check for diff
        run: make install-goyacc check-generated-parser
  golangci:
    name: golangci-lint
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          persist-credentials: false
      - name: Install Go
        uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
        with:
          go-version: 1.25.x
      - name: Install snmp_exporter/generator dependencies
        run: sudo apt-get update && sudo apt-get -y install libsnmp-dev
        if: github.repository == 'prometheus/snmp_exporter'
      - name: Get golangci-lint version
        id: golangci-lint-version
        run: echo "version=$(make print-golangci-lint-version)" >> $GITHUB_OUTPUT
      - name: Lint
        uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0
        with:
          args: --verbose
          version: ${{ steps.golangci-lint-version.outputs.version }}
      - name: Lint with slicelabels
        uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0
        with:
          # goexperiment.synctest to ensure we don't miss files that depend on it.
          args: --verbose --build-tags=slicelabels,goexperiment.synctest
          version: ${{ steps.golangci-lint-version.outputs.version }}
      - name: Lint with dedupelabels
        uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0
        with:
          args: --verbose --build-tags=dedupelabels
          version: ${{ steps.golangci-lint-version.outputs.version }}
  fuzzing:
    uses: ./.github/workflows/fuzzing.yml
    if: github.event_name == 'pull_request'
  codeql:
    uses: ./.github/workflows/codeql-analysis.yml
    permissions:
      contents: read
      security-events: write

  publish_main:
    name: Publish main branch artifacts
    runs-on: ubuntu-latest
    needs: [test_ui, test_go, test_go_more, test_go_oldest, test_windows, golangci, codeql, build_all]
    if: github.event_name == 'push' && github.event.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          persist-credentials: false
      - uses: prometheus/promci@443c7fc2397e946bc9f5029e313a9c3441b9b86d # v0.4.7
      - uses: ./.github/promci/actions/publish_main
        with:
          docker_hub_login: ${{ secrets.docker_hub_login }}
          docker_hub_password: ${{ secrets.docker_hub_password }}
          quay_io_login: ${{ secrets.quay_io_login }}
          quay_io_password: ${{ secrets.quay_io_password }}
  publish_release:
    name: Publish release artefacts
    runs-on: ubuntu-latest
    needs: [test_ui, test_go, test_go_more, test_go_oldest, test_windows, golangci, codeql, build_all]
    if: |
      (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v2.'))
      ||
      (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v3.'))
    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          persist-credentials: false
      - uses: prometheus/promci@443c7fc2397e946bc9f5029e313a9c3441b9b86d # v0.4.7
      - uses: ./.github/promci/actions/publish_release
        with:
          docker_hub_login: ${{ secrets.docker_hub_login }}
          docker_hub_password: ${{ secrets.docker_hub_password }}
          quay_io_login: ${{ secrets.quay_io_login }}
          quay_io_password: ${{ secrets.quay_io_password }}
          github_token: ${{ secrets.PROMBOT_GITHUB_TOKEN }}
  publish_ui_release:
    name: Publish UI on npm Registry
    runs-on: ubuntu-latest
    needs: [test_ui, codeql]
    steps:
      - name: Checkout
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          persist-credentials: false
      - uses: prometheus/promci@443c7fc2397e946bc9f5029e313a9c3441b9b86d # v0.4.7
      - name: Install nodejs
        uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
        with:
          node-version-file: "web/ui/.nvmrc"
          registry-url: "https://registry.npmjs.org"
      - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-
      - name: Check libraries version
        if: |
          (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v2.'))
          ||
          (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v3.'))
        run: ./scripts/ui_release.sh --check-package "$(./scripts/get_module_version.sh ${GH_REF_NAME})"
        env:
          GH_REF_NAME: ${{ github.ref_name }}
      - name: build
        run: make assets
      - name: Copy files before publishing libs
        run: ./scripts/ui_release.sh --copy
      - name: Publish dry-run libraries
        if: |
          !(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v2.'))
          &&
          !(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v3.'))
        run: ./scripts/ui_release.sh --publish dry-run
      - name: Publish libraries
        if: |
          (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v2.'))
          ||
          (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v3.'))
        run: ./scripts/ui_release.sh --publish
        env:
          # The setup-node action writes an .npmrc file with this env variable
          # as the placeholder for the auth token
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
