name: validate
on:
  push:
    tags:
      - v*
    branches:
      - main
      - release-*
  pull_request:
  workflow_dispatch:
env:
  GO_VERSION: 1.25
permissions:
  contents: read

jobs:
  keyring:
    runs-on: ubuntu-24.04
    steps:
    - uses: actions/checkout@v6
    - name: check runc.keyring
      run: make validate-keyring

  lint:
    timeout-minutes: 30
    permissions:
      contents: read
      pull-requests: read
      checks: write # to allow the action to annotate code in the PR.
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 2
      - uses: actions/setup-go@v6
        with:
          go-version: "${{ env.GO_VERSION }}"
      - name: install deps
        run: |
          sudo apt -q update
          sudo apt -qy install libseccomp-dev
      - uses: golangci/golangci-lint-action@v9
        with:
          version: v2.6
          skip-cache: true
      # Extra linters, only checking new code from a pull request to main.
      - name: lint-extra
        if: github.event_name == 'pull_request' && github.base_ref == 'main'
        run: |
          golangci-lint run --config .golangci-extra.yml --new-from-rev=HEAD~1

  modernize:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 2
      - uses: actions/setup-go@v6
        with:
          go-version: stable # modernize@latest may require latest Go.
      - name: install deps
        run: |
          sudo apt -q update
          sudo apt -qy install libseccomp-dev
      - name: run go fix
        run: |
          go fix ./...
          git diff --exit-code
      - name: run modernize
        run: |
          go run golang.org/x/tools/go/analysis/passes/modernize/cmd/modernize@latest -fix ./...
          git diff --exit-code

  compile-buildtags:
    runs-on: ubuntu-24.04
    env:
      # Don't ignore C warnings. Note that the output of "go env CGO_CFLAGS" by default is "-g -O2", so we keep them.
      CGO_CFLAGS: -g -O2 -Werror
    steps:
      - uses: actions/checkout@v6
      - name: install go
        uses: actions/setup-go@v6
        with:
          go-version: "${{ env.GO_VERSION }}"
      - name: install deps
        run: |
          sudo apt update
          sudo apt -y install libseccomp-dev
      - name: compile with no build tags
        run: make BUILDTAGS=""
      - name: compile with runc_nocriu build tag
        run: make EXTRA_BUILDTAGS="runc_nocriu"

  codespell:
    runs-on: ubuntu-24.04
    steps:
    - uses: actions/checkout@v6
    - name: install deps
      # Version of codespell bundled with Ubuntu is way old, so use pip.
      run: pip install --break-system-packages codespell==v2.4.1
    - name: run codespell
      run: codespell

  shfmt:
    runs-on: ubuntu-24.04
    steps:
    - uses: actions/checkout@v6
    - name: shfmt
      run: make shfmt

  shellcheck:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - name: install shellcheck
        env:
          VERSION: v0.11.0
          BASEURL: https://github.com/koalaman/shellcheck/releases/download
          SHA256: 4da528ddb3a4d1b7b24a59d4e16eb2f5fd960f4bd9a3708a15baddbdf1d5a55b
        run: |
          mkdir ~/bin
          curl -sSfL --retry 5 $BASEURL/$VERSION/shellcheck-$VERSION.linux.x86_64.tar.xz |
            tar xfJ - -C ~/bin --strip 1 shellcheck-$VERSION/shellcheck
          sha256sum --strict --check - <<<"$SHA256 *$HOME/bin/shellcheck"
          # make sure to remove the old version
          sudo rm -f /usr/bin/shellcheck
          # Add ~/bin to $PATH.
          echo ~/bin >> $GITHUB_PATH
      - uses: lumaxis/shellcheck-problem-matchers@v2
      - name: run
        run: make shellcheck
      - name: check-config.sh
        run : ./script/check-config.sh

  space-at-eol:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - run: rm -fr vendor
      - run: if git -P grep -I -n '\s$'; then echo "^^^ extra whitespace at EOL, please fix"; exit 1; fi

  deps:
    runs-on: ubuntu-24.04
    steps:
    - uses: actions/checkout@v6
    - name: install go
      uses: actions/setup-go@v6
      with:
        go-version: "${{ env.GO_VERSION }}"
        check-latest: true
    - name: verify deps
      run: make verify-dependencies
    - name: no toolchain in go.mod # See https://github.com/opencontainers/runc/pull/4717, https://github.com/dependabot/dependabot-core/issues/11933.
      run: |
        if grep -q '^toolchain ' go.mod; then echo "Error: go.mod must not have toolchain directive, please fix"; exit 1; fi
    - name: no exclude nor replace in go.mod
      run: |
        if grep -Eq '^\s*(exclude|replace) ' go.mod; then echo "Error: go.mod must not have exclude/replace directive, it breaks go install. Please fix"; exit 1; fi


  commit:
    permissions:
      contents: read
      pull-requests: read
    runs-on: ubuntu-24.04
    steps:
      - name: get pr commits
        if: github.event_name == 'pull_request' # Only check commits on pull requests.
        id: 'get-pr-commits'
        uses: tim-actions/get-pr-commits@v1.3.1
        with:
          token: ${{ secrets.GITHUB_TOKEN }}

      - name: check subject line length
        if: github.event_name == 'pull_request' # Only check commits on pull requests.
        uses: tim-actions/commit-message-checker-with-regex@v0.3.2
        with:
          commits: ${{ steps.get-pr-commits.outputs.commits }}
          pattern: '^.{0,72}(\n.*)*$'
          error: 'Subject too long (max 72)'

      - name: succeed (not a PR) # Allow all-done to succeed for non-PRs.
        if: github.event_name != 'pull_request'
        run: echo "Nothing to check here."

  cfmt:
    runs-on: ubuntu-24.04
    steps:
    - name: checkout
      uses: actions/checkout@v6
    - name: install deps
      run: |
        sudo apt -qq update
        sudo apt -qqy install indent
    - name: cfmt
      run: |
        make cfmt
        git diff --exit-code

  check-go:
    runs-on: ubuntu-24.04
    steps:
    - uses: actions/checkout@v6
    - name: check Go version
      run: |
        GO_VER=$(awk -F= '/^ARG\s+GO_VERSION=/ {print $2; quit}' Dockerfile)
        echo "Go version used in Dockerfile: $GO_VER"
        echo -n "Checking if Go $GO_VER is supported ... "
        curl -fsSL https://go.dev/dl/?mode=json | jq -e 'any(.[]; .version | startswith("go'$GO_VER'"))'
        echo -n "Checking if Go $GO_VER is tested against ... "
        yq -e '.jobs.test.strategy.matrix.go-version | contains(["'$GO_VER'.x"])' .github/workflows/test.yml

  release:
    timeout-minutes: 30
    runs-on: ubuntu-24.04
    steps:
    - name: checkout
      uses: actions/checkout@v6

    - name: check CHANGELOG.md
      run: make verify-changelog

      # We have to run this under Docker as Ubuntu (host) does not support all
      # the architectures we want to compile test against, and Dockerfile uses
      # Debian (which does).
      #
      # XXX: as currently this is the only job that is using Docker, we are
      # building and using the runcimage locally. In case more jobs running
      # under Docker will emerge, it will be good to have a separate make
      # runcimage job and share its result (the docker image) with whoever
      # needs it.
    - name: build docker image
      run: make runcimage
    - name: make releaseall
      run: make releaseall
    - name: upload artifacts
      uses: actions/upload-artifact@v6
      with:
        name: release-${{ github.run_id }}
        path: release/*


  get-images:
    runs-on: ubuntu-24.04
    steps:
    - uses: actions/checkout@v6
    - name: install bashbrew
      env:
        BASEURL: https://github.com/docker-library/bashbrew/releases/download
        VERSION: v0.1.7
        SHA256: 6b71a6fccfb2025d48a2b23324836b5513c29abfd2d16a57b7a2f89bd02fe53a
      run: |
        mkdir ~/bin
        curl -sSfL --retry 5 -o ~/bin/bashbrew \
          $BASEURL/$VERSION/bashbrew-amd64
        sha256sum --strict --check - <<<"$SHA256 *$HOME/bin/bashbrew"
        chmod a+x ~/bin/bashbrew
        # Add ~/bin to $PATH.
        echo ~/bin >> $GITHUB_PATH
    - name: check that get-images.sh is up to date
      run: |
        cd tests/integration
        ./bootstrap-get-images.sh > get-images.sh
        git diff --exit-code

  all-done:
    needs:
      - check-go
      - cfmt
      - codespell
      - commit
      - compile-buildtags
      - deps
      - get-images
      - keyring
      - lint
      - modernize
      - release
      - shellcheck
      - shfmt
      - space-at-eol
    runs-on: ubuntu-24.04
    steps:
    - run: echo "All jobs completed"
