Skip to content

Commit 1443635

Browse files
Include transitive dependencies of local reusable workflows
This is necessary when the target is not a whole repository or when an external reusable workflow uses a (for that workflow)-local workflow - otherwise the reusable workflow would be included regardless. Hence, this is also only tested in the suite for `ghasum verify` (because it doesn't apply to `init` nor `update`).
1 parent 3022804 commit 1443635

7 files changed

Lines changed: 92 additions & 13 deletions

File tree

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,16 @@ Versioning].
1212

1313
## [Unreleased]
1414

15+
### Bugs
16+
17+
- Cover the actions and workflows used in local actions and reusable workflows.
18+
19+
### Security
20+
21+
- Upgrade Go to `v1.25.0`.
22+
23+
## [v0.6.0] - 2025-08-17
24+
1525
### Enhancements
1626

1727
- Add the `ghasum list` subcommand to get a nested list of GitHub Actions

internal/gha/actions.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"maps"
2323
"path"
2424
"slices"
25+
"strings"
2526
)
2627

2728
type workflowFile struct {
@@ -50,13 +51,15 @@ func actionsInWorkflows(workflows []workflow) ([]GitHubAction, error) {
5051

5152
if job.Uses != "" {
5253
action, err := parseUses(job.Uses)
53-
if errors.Is(err, ErrLocalAction) {
54-
continue
55-
} else if err != nil {
54+
switch {
55+
case err == nil:
56+
action.Kind = ReusableWorkflow
57+
case errors.Is(err, ErrLocalAction):
58+
action.Kind = LocalReusableWorkflow
59+
default:
5660
return nil, err
5761
}
5862

59-
action.Kind = ReusableWorkflow
6063
unique[actionId(action)] = action
6164
}
6265
}
@@ -134,7 +137,7 @@ func workflowsInRepo(repo fs.FS) ([]workflowFile, error) {
134137
}
135138

136139
func workflowInRepo(repo fs.FS, path string) ([]byte, error) {
137-
file, err := repo.Open(path)
140+
file, err := repo.Open(strings.TrimPrefix(path, "./"))
138141
if err != nil {
139142
return nil, fmt.Errorf("could not open workflow at %q: %v", path, err)
140143
}

internal/gha/actions_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ func TestActionsInWorkflows(t *testing.T) {
371371
},
372372
},
373373
},
374-
want: 0,
374+
want: 1,
375375
},
376376
"job with external reusable workflow": {
377377
in: []workflow{

internal/gha/gha.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ const (
6363
// Dockerfile.
6464
LocalAction
6565

66+
// LocalReusableWorkflow represent a GitHub Actions component local to the
67+
// parent project that is a "reusable workflow".
68+
//
69+
// A local reusable workflow is a workflow in the parent repository with the
70+
// appropriate workflow trigger. These are used in the `uses:` value of
71+
// workflow jobs.
72+
LocalReusableWorkflow
73+
6674
// ReusableWorkflow represent a GitHub Actions component that is a "reusable
6775
// workflow".
6876
//
@@ -187,13 +195,13 @@ func (k ActionKind) String() string {
187195
switch k {
188196
case Action, LocalAction:
189197
return "action"
190-
case ReusableWorkflow:
198+
case ReusableWorkflow, LocalReusableWorkflow:
191199
return "reusable workflow"
192200
default:
193201
panic("unknown action kind " + string(k))
194202
}
195203
}
196204

197205
func (k ActionKind) IsLocal() bool {
198-
return k == LocalAction
206+
return k == LocalAction || k == LocalReusableWorkflow
199207
}

internal/gha/parse_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ func TestParseUses(t *testing.T) {
7979
want: GitHubAction{
8080
Owner: "foo",
8181
Project: "bar",
82+
Path: "baz",
8283
Ref: "v2",
8384
},
8485
},
@@ -110,9 +111,17 @@ func TestParseUses(t *testing.T) {
110111
t.Errorf("Incorrect project (got %q, want %q)", got, want)
111112
}
112113

114+
if got, want := got.Path, tt.want.Path; got != want {
115+
t.Errorf("Incorrect path (got %q, want %q)", got, want)
116+
}
117+
113118
if got, want := got.Ref, tt.want.Ref; got != want {
114119
t.Errorf("Incorrect ref (got %q, want %q)", got, want)
115120
}
121+
122+
if got, want := got.Kind, tt.want.Kind; got != want {
123+
t.Errorf("Incorrect kind (got %q, want %q)", got, want)
124+
}
116125
})
117126
}
118127
})

internal/ghasum/atoms.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ func find(cfg *Config) (tree, error) {
216216
if err != nil {
217217
return root, fmt.Errorf("action manifest parsing failed for %s: %v", action, err)
218218
}
219-
case gha.ReusableWorkflow:
219+
case gha.ReusableWorkflow, gha.LocalReusableWorkflow:
220220
transitive, err = gha.WorkflowActions(repo.FS(), action.Path)
221221
if err != nil {
222222
return root, fmt.Errorf("reusable workflow parsing failed for %s: %v", action, err)

testdata/verify/problems.txtar

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
# Checksum mismatch - Repo
22
! exec ghasum verify -offline -cache .cache/ mismatch/
3-
stdout '4 problem\(s\) occurred during validation:'
3+
stdout '5 problem\(s\) occurred during validation:'
44
stdout 'checksum mismatch for "actions/checkout@v4"'
55
stdout 'checksum mismatch for "actions/github-script@v8"'
66
stdout 'checksum mismatch for "actions/setup-go@v5"'
77
stdout 'checksum mismatch for "actions/setup-java@v4"'
8+
stdout 'checksum mismatch for "actions/setup-python@v6"'
89
! stdout 'Ok'
910
! stderr .
1011

1112
# Checksum mismatch - Workflow
1213
! exec ghasum verify -offline -cache .cache/ mismatch/.github/workflows/workflow.yml
13-
stdout '4 problem\(s\) occurred during validation:'
14+
stdout '5 problem\(s\) occurred during validation:'
1415
stdout 'checksum mismatch for "actions/checkout@v4"'
1516
stdout 'checksum mismatch for "actions/github-script@v8"'
1617
stdout 'checksum mismatch for "actions/setup-go@v5"'
1718
stdout 'checksum mismatch for "actions/setup-java@v4"'
19+
stdout 'checksum mismatch for "actions/setup-python@v6"'
1820
! stdout 'Ok'
1921
! stderr .
2022

@@ -33,6 +35,13 @@ stdout 'checksum mismatch for "actions/github-script@v8"'
3335
! stdout 'Ok'
3436
! stderr .
3537

38+
# Checksum mismatch - Local reusable workflow
39+
! exec ghasum verify -offline -cache .cache/ mismatch/.github/workflows/workflow.yml:local-reusable-workflow
40+
stdout '1 problem\(s\) occurred during validation:'
41+
stdout 'checksum mismatch for "actions/setup-python@v6"'
42+
! stdout 'Ok'
43+
! stderr .
44+
3645
# Checksum mismatch - Transitive, manifest
3746
! exec ghasum verify -offline -cache .cache/ mismatch/.github/workflows/workflow.yml:transitive-manifest
3847
stdout '1 problem\(s\) occurred during validation:'
@@ -49,19 +58,21 @@ stdout 'checksum mismatch for "actions/setup-java@v4"'
4958

5059
# Checksum missing - Repo
5160
! exec ghasum verify -offline -cache .cache/ missing/
52-
stdout '3 problem\(s\) occurred during validation:'
61+
stdout '4 problem\(s\) occurred during validation:'
5362
stdout 'no checksum found for "actions/github-script@v8"'
5463
stdout 'no checksum found for "actions/setup-go@v5"'
5564
stdout 'no checksum found for "actions/setup-java@v4"'
65+
stdout 'no checksum found for "actions/setup-python@v6"'
5666
! stdout 'Ok'
5767
! stderr .
5868

5969
# Checksum missing - Workflow
6070
! exec ghasum verify -offline -cache .cache/ missing/.github/workflows/workflow.yml
61-
stdout '3 problem\(s\) occurred during validation:'
71+
stdout '4 problem\(s\) occurred during validation:'
6272
stdout 'no checksum found for "actions/github-script@v8"'
6373
stdout 'no checksum found for "actions/setup-go@v5"'
6474
stdout 'no checksum found for "actions/setup-java@v4"'
75+
stdout 'no checksum found for "actions/setup-python@v6"'
6576
! stdout 'Ok'
6677
! stderr .
6778

@@ -79,6 +90,13 @@ stdout 'no checksum found for "actions/github-script@v8"'
7990
! stdout 'Ok'
8091
! stderr .
8192

93+
# Checksum missing - Local reusable workflow
94+
! exec ghasum verify -offline -cache .cache/ missing/.github/workflows/workflow.yml:local-reusable-workflow
95+
stdout '1 problem\(s\) occurred during validation:'
96+
stdout 'no checksum found for "actions/setup-python@v6"'
97+
! stdout 'Ok'
98+
! stderr .
99+
82100
# Checksum missing - Transitive, manifest
83101
! exec ghasum verify -offline -cache .cache/ missing/.github/workflows/workflow.yml:transitive-manifest
84102
stdout '1 problem\(s\) occurred during validation:'
@@ -128,6 +146,18 @@ actions/github-script@v8 this-is-intentionally-incorrect
128146
actions/reusable@v2 /PcY8RI/utekzCyLUiLOEeL3FpJ96/FJVRbb5LBLmkU=
129147
actions/setup-go@v5 this-is-intentionally-incorrect
130148
actions/setup-java@v4 this-is-intentionally-incorrect
149+
actions/setup-python@v6 this-is-intentionally-incorrect
150+
-- mismatch/.github/workflows/reusable.yml --
151+
name: Reusable workflow
152+
on: [workflow_call]
153+
154+
jobs:
155+
example:
156+
name: example
157+
runs-on: ubuntu-22.04
158+
steps:
159+
- name: Install Python
160+
uses: actions/setup-python@v6
131161
-- mismatch/.github/workflows/workflow.yml --
132162
name: Example workflow
133163
on: [push]
@@ -151,6 +181,9 @@ jobs:
151181
steps:
152182
- name: This step uses a local action
153183
uses: ./.github/actions/hello-world-action
184+
local-reusable-workflow:
185+
name: example local reusable workflow
186+
uses: ./.github/workflows/reusable.yml
154187
transitive-manifest:
155188
name: example transitive action
156189
runs-on: ubuntu-24.04
@@ -177,6 +210,17 @@ version 1
177210
actions/checkout@v4 +34igsJdK09ZFEkVNQ+ZoyZnIlg48X3bm4ZaGGlX5o8=
178211
actions/composite@v1 VHsmCNCNfU2qFyTntn14sMoZL1UOOyne/omuQUvzQfA=
179212
actions/reusable@v2 /PcY8RI/utekzCyLUiLOEeL3FpJ96/FJVRbb5LBLmkU=
213+
-- missing/.github/workflows/reusable.yml --
214+
name: Reusable workflow
215+
on: [workflow_call]
216+
217+
jobs:
218+
example:
219+
name: example
220+
runs-on: ubuntu-22.04
221+
steps:
222+
- name: Install Python
223+
uses: actions/setup-python@v6
180224
-- missing/.github/workflows/workflow.yml --
181225
name: Example workflow
182226
on: [push]
@@ -200,6 +244,9 @@ jobs:
200244
steps:
201245
- name: This step uses a local action
202246
uses: ./.github/actions/hello-world-action
247+
local-reusable-workflow:
248+
name: example local reusable workflow
249+
uses: ./.github/workflows/reusable.yml
203250
transitive-manifest:
204251
name: example transitive action
205252
runs-on: ubuntu-24.04
@@ -254,3 +301,5 @@ jobs:
254301
name: actions/setup-go@v5
255302
-- .cache/actions/setup-java/v4/action.yml --
256303
name: actions/setup-java@v4
304+
-- .cache/actions/setup-python/v6/action.yml --
305+
name: actions/setup-python@v6

0 commit comments

Comments
 (0)