Skip to content

Commit d32b16e

Browse files
committed
Merge branch 'docs-gardener'
2 parents 174d079 + abb249d commit d32b16e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1390
-143
lines changed

.github/workflows/ci.yaml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,21 @@ jobs:
9191
- uses: actions/setup-go@v5
9292
with:
9393
go-version: '1.23'
94-
- run: sudo apt-get install -y shellcheck
94+
- name: Install dependencies
95+
run: |
96+
sudo apt-get install -y shellcheck
97+
pip install pyflakes
98+
shellcheck --version
99+
pyflakes --version
95100
- name: Check Go sources are formatted
96101
run: |
97102
diffs="$(gofmt -d ./*.go ./cmd/actionlint/*.go ./scripts/*/*.go ./playground/*.go)"
98103
if [[ "$diffs" != "" ]]; then
99104
echo "$diffs" >&2
100105
exit 1
101106
fi
107+
- name: Check `docs/checks.md` is up-to-date
108+
run: go run ./scripts/update-checks-doc -check ./docs/checks.md
102109
- name: Install staticcheck
103110
run: |
104111
go install honnef.co/go/tools/cmd/staticcheck@latest

CONTRIBUTING.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ To report a bug, please submit a new ticket on GitHub. It's helpful to search si
55
https://github.com/rhysd/actionlint/issues/new
66

77
Providing a reproducible workflow content is much appreciated. If only a small snippet of workflow is provided or no
8-
input is provided at all, such issue tickets may get lower priority since they are occasionally time consuming to
8+
input is provided at all, such issue tickets may get lower priority because they are occasionally time consuming to
99
investigate.
1010

1111
# Sending a patch
@@ -21,6 +21,10 @@ Before submitting your PR, please ensure the following points:
2121
- Confirm build/tests/lints passed. How to run them is described in the following sections.
2222
- If you added a new feature, consider to add tests and explain it in [the usage document](docs/usage.md).
2323
- If you added a new public API, consider to add tests and a doc comment for the API.
24+
- If you updated [the checks document](docs/checks.md), ensure to run [the maintenance script](#about-checks-doc).
25+
26+
Special thanks to the native English speakers for proofreading the documentation and error messages, as the author is not
27+
proficient in English.
2428

2529
# Development
2630

@@ -219,3 +223,14 @@ All tests are automated.
219223
- `testdata/projects/` contains 'Project' tests. Each directories represent a single project (meaning a repository on GitHub).
220224
Corresponding `*.out` files are expected error messages. Empty `*.out` file means the test case should cause no errors.
221225
'Project' test is used for use cases where multiple files are related (reusable workflows, local actions, config files, ...).
226+
227+
<a id="about-checks-doc"></a>
228+
## How to write checks document
229+
230+
The ['Checks' document](./docs/checks.md) is a large document to explain all checks by actionlint.
231+
232+
This document is maintained with [`update-checks-doc`](./scripts/update-checks-doc) script. This script automatically updates
233+
the code blocks after `Output:` and the `Playground` links. This script should be run after modifying the document.
234+
235+
Please see [the readme of the script](./scripts/update-checks-doc/README.md) for the usage and knowing the details of the
236+
document format that this script assumes.

docs/checks.md

Lines changed: 133 additions & 114 deletions
Large diffs are not rendered by default.

docs/install.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ Note: The following targets are not tested since GitHub Actions doesn't support
9696
- Windows i386, arm64
9797
- FreeBSD i386, x86_64
9898

99-
<a name="download-script"></a>
99+
<a id="download-script"></a>
100100
## Download script
101101

102102
To install `actionlint` executable with one command, [the download script](../scripts/download-actionlint.bash) is available.

docs/usage.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ processes.
4242
actionlint -shellcheck= -pyflakes=
4343
```
4444

45-
<a name="format"></a>
45+
<a id="format"></a>
4646
### Format error messages
4747

4848
`-format` option can flexibly format error messages with [Go template syntax][go-template].
@@ -189,7 +189,7 @@ Note that special characters escaped with backslash like `\n` in the format stri
189189
| `2` | The command failed due to invalid command line option |
190190
| `3` | The command failed due to some fatal error |
191191

192-
<a name="on-github-actions"></a>
192+
<a id="on-github-actions"></a>
193193
## Use actionlint on GitHub Actions
194194

195195
Preparing `actionlint` executable with the download script is recommended. See [the instruction](install.md#download-script) for
@@ -263,7 +263,7 @@ Paste your workflow content to the code editor at left pane. It automatically sh
263263
the workflow content in the code editor, the results will be updated on the fly. Clicking an error message in the results
264264
table moves a cursor to position of the error in the code editor.
265265

266-
<a name="docker"></a>
266+
<a id="docker"></a>
267267
## [Docker][docker] image
268268

269269
[Official Docker image][docker-image] is available. The image contains `actionlint` executable and all dependencies (shellcheck
@@ -304,7 +304,7 @@ docker run --rm -v /path/to/workflows:/workflows rhysd/actionlint:latest -color
304304
Go APIs are available. See [the Go API document](api.md) for more details.
305305

306306

307-
<a name="tools-integ"></a>
307+
<a id="tools-integ"></a>
308308
## Tools integration
309309

310310
### reviewdog
@@ -325,7 +325,7 @@ jobs:
325325
- uses: reviewdog/action-actionlint@v1
326326
```
327327

328-
<a name="problem-matchers"></a>
328+
<a id="problem-matchers"></a>
329329
### Problem Matchers
330330

331331
[Problem Matchers][problem-matchers] is a feature to extract GitHub Actions annotations from terminal outputs of linters.

rule_job_needs.go

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package actionlint
22

33
import (
4-
"fmt"
4+
"strconv"
55
"strings"
66
)
77

@@ -44,7 +44,7 @@ func NewRuleJobNeeds() *RuleJobNeeds {
4444
}
4545
}
4646

47-
func contains(heystack []string, needle string) bool {
47+
func contains[T comparable](heystack []T, needle T) bool {
4848
for _, s := range heystack {
4949
if s == needle {
5050
return true
@@ -107,47 +107,61 @@ func (rule *RuleJobNeeds) VisitWorkflowPost(n *Workflow) error {
107107
return nil
108108
}
109109

110-
if edge := detectCyclic(rule.nodes); edge != nil {
111-
edges := map[string]string{}
112-
edges[edge.from.id] = edge.to.id
113-
collectCyclic(edge.to, edges)
110+
// Note: Only the first cycle can be detected even if there are multiple cycles in "needs:" configurations.
111+
if edge := detectFirstCycle(rule.nodes); edge != nil {
112+
edges := map[*jobNode]*jobNode{}
113+
edges[edge.from] = edge.to
114+
collectCycle(edge.to, edges)
115+
116+
// Start cycle from the smallest position to make the error message deterministic
117+
start := edge.from
118+
for n := range edges {
119+
if n.pos.IsBefore(start.pos) {
120+
start = n
121+
}
122+
}
114123

115-
desc := make([]string, 0, len(edges))
116-
for from, to := range edges {
117-
desc = append(desc, fmt.Sprintf("%q -> %q", from, to))
124+
var msg strings.Builder
125+
msg.WriteString("cyclic dependencies in \"needs\" job configurations are detected. detected cycle is ")
126+
127+
msg.WriteString(strconv.Quote(start.id))
128+
from, to := start, edges[start]
129+
for {
130+
msg.WriteString(" -> ")
131+
msg.WriteString(strconv.Quote(to.id))
132+
from, to = to, edges[to]
133+
if from == start {
134+
break
135+
}
118136
}
119137

120-
rule.Errorf(
121-
edge.from.pos,
122-
"cyclic dependencies in \"needs\" configurations of jobs are detected. detected cycle is %s",
123-
strings.Join(desc, ", "),
124-
)
138+
rule.Error(start.pos, msg.String())
125139
}
126140

127141
return nil
128142
}
129143

130-
func collectCyclic(src *jobNode, edges map[string]string) bool {
144+
func collectCycle(src *jobNode, edges map[*jobNode]*jobNode) bool {
131145
for _, dest := range src.resolved {
132146
if dest.status != nodeStatusActive {
133147
continue
134148
}
135-
edges[src.id] = dest.id
136-
if _, ok := edges[dest.id]; ok {
149+
edges[src] = dest
150+
if _, ok := edges[dest]; ok {
137151
return true
138152
}
139-
if collectCyclic(dest, edges) {
153+
if collectCycle(dest, edges) {
140154
return true
141155
}
142-
delete(edges, src.id)
156+
delete(edges, src)
143157
}
144158
return false
145159
}
146160

147161
// Detect cyclic dependencies
148162
// https://inzkyk.xyz/algorithms/depth_first_search/detecting_cycles/
149163

150-
func detectCyclic(nodes map[string]*jobNode) *edge {
164+
func detectFirstCycle(nodes map[string]*jobNode) *edge {
151165
for _, v := range nodes {
152166
if v.status == nodeStatusNew {
153167
if e := detectCyclicNode(v); e != nil {

scripts/update-checks-doc/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/update-checks-doc

scripts/update-checks-doc/README.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
update-checks-doc
2+
=================
3+
4+
This is a script to maintain [the 'Checks' document](../../docs/checks.md).
5+
6+
This script does:
7+
8+
- update the outputs of the example inputs; the code blocks after `Output:` header
9+
- update the links to the [playground](https://rhysd.github.io/actionlint/) for the example inputs
10+
11+
For making the implementation simple, this script does not support Windows. Please run this script
12+
on Linux or macOS.
13+
14+
## Usage
15+
16+
Update the document. This command directly modifies the file.
17+
18+
```sh
19+
go run ./scripts/update-checks-doc ./docs/checks.md
20+
```
21+
22+
Check the document is up-to-date.
23+
24+
```sh
25+
go run ./scripts/update-checks-doc -check ./docs/checks.md
26+
```
27+
28+
The check is run on the [CI workflow](../../.github/workflows/ci.yaml).
29+
30+
## Format
31+
32+
The format of the check document is:
33+
34+
````markdown
35+
<a id="some-id"></a>
36+
## This is title of the check
37+
38+
Example input:
39+
40+
```yaml
41+
This section is referred to generate the output and the playground link
42+
```
43+
44+
Output:
45+
46+
```
47+
This section will be auto-generated
48+
```
49+
50+
[Playground](https://rhysd.github.io/actionlint/#THIS_HASH_PART_WILL_BE_AUTO_GENERATED)
51+
52+
Explanation for the check...
53+
````
54+
55+
When you don't want to update the output by this script, put the comment as follows. This script
56+
will ignore the code block. Instead you need to write the output in the code blcok manually.
57+
58+
```yaml
59+
Output:
60+
<!-- Skip update output -->
61+
```
62+
63+
When you don't want to put a playground link for your example input, put the comment as follows
64+
instead of the link. This script will not generate the hash for the playground link.
65+
66+
```yaml
67+
<!-- Skip playground link -->
68+
```

0 commit comments

Comments
 (0)