---
## Offline lint checks. Runs on every PR and on tag pushes.
## Each check is a discrete workflow step so failures are visible
## in the GitHub Actions UI without scrolling. The dispatcher script
## ci/local-checks.sh reproduces the whole flow on a dev machine.
##
## See agents/github-actions-security.md for permissions /
## persist-credentials / fork-PR / SHA-pinning conventions, and for
## the rationale on why actionlint is not used.

name: Lint

on:
  pull_request:
    branches: [master]
  ## Branch-push triggers intentionally omitted: a tag-bearing commit
  ## landing on master would otherwise fire this workflow twice (once
  ## for the branch push, once for the tag push). Same rationale in
  ## the other workflows in this directory.
  push:
    tags:
      - '*'

  workflow_dispatch:

permissions:
  contents: read

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  checks:
    runs-on: ubuntu-latest

    if: github.event.pull_request.head.repo.full_name == github.repository || github.event_name != 'pull_request'

    timeout-minutes: 7

    container:
      ## debian:trixie - Debian 13, current stable. TODO: update for
      ## forky. Re-pin procedure: agents/github-actions-security.md.
      image: debian:trixie@sha256:35b8ff74ead4880f22090b617372daff0ccae742eb5674455d542bef71ef1999  # debian:trixie as of 2026-04-27

    steps:
      - name: Install git for actions/checkout
        ## Inline because checkout has not yet run - the ci/ script
        ## would not be on disk yet.
        run: |
          set -e
          cat /etc/os-release
          apt-get update
          apt-get install -y --no-install-recommends git ca-certificates

      - name: Checkout repository
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6
        with:
          persist-credentials: false

      - name: Install lint dependencies (Debian apt)
        run: ./ci/lint-install

      - name: Lint diagnostics
        run: ./ci/lint-diagnostics

      - name: Lint yaml
        run: ./ci/lint-yaml

      - name: Lint shellcheck
        ## Excludes:
        ##   SC2086 - Many call sites intentionally word-split string
        ##     variables containing space-separated option lists
        ##     ('$apt_unattended_opts', '$pids' in umount_kill.sh,
        ##     'eval $cmd_string' in pre's retry dispatch). Refactoring
        ##     each into arrays is sound but invasive; out of scope.
        ##   SC2317 - False positive in the build-step dispatch pattern:
        ##     each build-steps.d/* file defines functions called via
        ##     the file's own bottom-of-file dispatcher, which shellcheck
        ##     cannot see statically.
        ##   SC2016 - Triggered by intentional literal-'$1' arguments to
        ##     --customize-hook in help-steps/mmdebstrap and 'bash -c'
        ##     recursive calls in help-steps/git_sanity_test. Single
        ##     quoting is correct in those contexts.
        uses: org-ai-assisted/developer-meta-files/.github/actions/shellcheck@master
        with:
          ## Mirrors the pre-composite ci/lint-shellcheck scope:
          ## help-steps, build-steps.d, automated_builder, ci + two
          ## root entry points. Out-of-scope deliberately: the
          ## live-build-config/ subtree (live-build owns those
          ## #!/bin/sh scripts; SC3040 'pipefail in POSIX sh' there
          ## is a known latent issue tracked separately).
          paths: 'help-steps build-steps.d automated_builder ci derivative-maker derivative-update'
          excludes: 'SC2086,SC2317,SC2016'
          severity: 'info'

      - name: Checkout developer-meta-files (summary script)
        if: always()
        ## Needed for ci/step-summary-emit.sh. The shellcheck step
        ## above pulls dmf for its composite action but doesn't
        ## leave a workspace copy; an explicit checkout keeps this
        ## step independent of upstream's internal layout. Pinned
        ## SHA matches the actions/checkout in this file.
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6
        with:
          repository: org-ai-assisted/developer-meta-files
          ref: master
          path: .dmf
          persist-credentials: false

      - name: Emit step summary
        if: always()
        ## Headline panel for the Actions tab. Per-linter pass/fail
        ## is already visible as discrete steps; this panel is for
        ## the at-a-glance row on the PR Checks tab. Template
        ## values routed through env: per developer-meta-files#87.
        env:
          JOB_STATUS: ${{ job.status }}
        run: |
          ./.dmf/ci/step-summary-emit.sh \
            --tool 'Lint' \
            --column-header field \
            --row "outcome=${JOB_STATUS}"
