-
Notifications
You must be signed in to change notification settings - Fork 12
173 lines (165 loc) · 7.12 KB
/
lint-ci.yaml
File metadata and controls
173 lines (165 loc) · 7.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Repo-wide linting and link-check.
#
# This workflow has NO path filter — it runs on every pull_request and
# every push to main. That guarantees a `ci-gate` check is always posted
# on a PR, even doc-only or label-only changes that wouldn't otherwise
# trigger operator-ci or agent-ci. operator-ci and agent-ci also publish
# checks named `ci-gate`; GitHub composes same-named required checks so
# every ci-gate that posts must pass.
name: Lint CI
on:
workflow_dispatch: {}
pull_request: {}
push:
branches:
- main
env:
# Opt all JS actions into Node 24 ahead of GitHub's Node 20 phase-out.
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
# Pin third-party tooling versions and binary checksums. NVIDIA's enterprise
# restricts which GitHub Actions can be used, so actionlint and lychee are
# installed as binaries directly rather than via wrapper actions; SHA256
# pins protect against tarball replacement on the upstream release.
ACTIONLINT_VERSION: 1.7.7
ACTIONLINT_SHA256: 023070a287cd8cccd71515fedc843f1985bf96c436b7effaecce67290e7e0757
LYCHEE_VERSION: 0.21.0
LYCHEE_SHA256: a06547250f10021dcafc6ed5bb20fca75835b65711745b63cfdda34c29ff6a73
YAMLLINT_VERSION: 1.38.0
jobs:
meta-lint:
name: meta-lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: actionlint (workflow files)
if: always()
run: |
set -euo pipefail
curl -sSfL "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz" -o /tmp/actionlint.tgz
echo "${ACTIONLINT_SHA256} /tmp/actionlint.tgz" | sha256sum -c -
tar -xzf /tmp/actionlint.tgz -C /tmp actionlint
# -shellcheck= disables the shellcheck integration. Existing
# workflows have many SC2086/SC2155/etc. warnings that are
# tracked separately; this PR's scope is structural lint only.
/tmp/actionlint -color -shellcheck=
- name: yamllint
if: always()
run: |
pip install --user --quiet "yamllint==${YAMLLINT_VERSION}"
yamllint -c ci/yamllint.yaml .
- name: markdownlint
if: always()
# SHA pinned to satisfy NVIDIA's enterprise allow-list.
uses: DavidAnson/markdownlint-cli2-action@07035fd053f7be764496c0f8d8f9f41f98305101
with:
config: ci/.markdownlint-cli2.yaml
globs: |
**/*.md
!**/vendor/**
!**/node_modules/**
# Generated by 'make notices'; license texts contain formatting
# we don't control (multiple blanks, etc.). Even with the generator's
# blank-collapse step the per-license bodies vary widely.
!THIRD_PARTY_NOTICES.md
!agent/THIRD_PARTY_NOTICES.md
!operator/THIRD_PARTY_NOTICES.md
# Generated by git-cliff on every release; format intrinsically
# violates MD032/MD024/MD009. Track separately if changelog
# style ever needs enforcement.
!**/CHANGELOG.md
# NVIDIA-managed template; not for us to lint.
!SECURITY.md
- name: Install lychee
if: always()
run: |
set -euo pipefail
curl -sSfL "https://github.com/lycheeverse/lychee/releases/download/lychee-v${LYCHEE_VERSION}/lychee-x86_64-unknown-linux-gnu.tar.gz" -o /tmp/lychee.tgz
echo "${LYCHEE_SHA256} /tmp/lychee.tgz" | sha256sum -c -
tar -xzf /tmp/lychee.tgz -C /tmp lychee
# Persist lychee's URL cache across runs so transient external
# failures don't re-fail every PR. Cache is keyed weekly so dead
# links still surface within ~7 days.
- name: Restore lychee cache
if: always()
uses: actions/cache@v4
with:
path: .lycheecache
key: lychee-${{ github.run_id }}
restore-keys: |
lychee-
# Pass 1: internal links only (relative paths, anchors, file://).
# These can never be flaky — if this fails, the PR really did break
# a link. --offline tells lychee to skip http(s) entirely.
- name: lychee — internal links (blocking)
if: always()
run: |
/tmp/lychee \
--no-progress \
--offline \
--exclude-file ci/lycheeignore \
--exclude-path THIRD_PARTY_NOTICES.md \
--exclude-path agent/THIRD_PARTY_NOTICES.md \
--exclude-path agent/vendor \
--exclude-path operator/THIRD_PARTY_NOTICES.md \
--exclude-path operator/vendor \
'./**/*.md'
# Pass 2: external links. Non-blocking — a `kubernetes.io` blip or
# GitHub rate-limit shouldn't block a docs PR. 4xx/5xx/429 are
# accepted as "not definitively broken" since they're commonly
# transient. Real dead links surface as ❌ in the step log; ci-gate
# below ignores this step's result.
- name: lychee — external links (advisory)
if: always()
continue-on-error: true
# `--retry-wait-time 5` is a constant minimum delay between retries
# (exponential backoff in lychee is reserved for HTTP 429); with
# `--max-retries 8` that's roughly 8×5s = 40s per failing URL. The
# step timeout is a runaway guard for the case where many URLs all
# retry concurrently and/or are stuck timing out at `--timeout 20`.
timeout-minutes: 15
env:
# GitHub token avoids unauthenticated rate-limiting on github.com URLs.
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
/tmp/lychee \
--no-progress \
--cache \
--max-cache-age 7d \
--max-retries 8 \
--retry-wait-time 5 \
--timeout 20 \
--accept "200..=299,403,429,500..=599" \
--exclude-file ci/lycheeignore \
--exclude-path THIRD_PARTY_NOTICES.md \
--exclude-path agent/THIRD_PARTY_NOTICES.md \
--exclude-path agent/vendor \
--exclude-path operator/THIRD_PARTY_NOTICES.md \
--exclude-path operator/vendor \
'./**/*.md'
# See operator-ci.yaml's ci-gate for rationale.
ci-gate:
name: ci-gate
needs: [meta-lint]
if: always()
runs-on: ubuntu-latest
steps:
- name: Verify all required jobs passed
run: |
results='${{ toJSON(needs) }}'
echo "$results"
echo "$results" | jq -e 'to_entries | all(.value.result == "success")'