Skip to content

Commit 49b7457

Browse files
committed
Merge branch 'strict-available-contexts'
2 parents d3399fe + d936cb4 commit 49b7457

12 files changed

+61
-26
lines changed

docs/checks.md

+14-4
Original file line numberDiff line numberDiff line change
@@ -2642,6 +2642,12 @@ jobs:
26422642
env:
26432643
# ERROR: 'env' context is not available here
26442644
NAME: ${{ env.NAME }}
2645+
services:
2646+
redis:
2647+
image: redis
2648+
env:
2649+
# ERROR: No context is allowed here
2650+
COMMIT_SHA: ${{ github.sha }}
26452651
steps:
26462652
- env:
26472653
# OK: 'env' context is available here
@@ -2663,13 +2669,17 @@ test.yaml:18:17: context "env" is not allowed here. available contexts are "gith
26632669
|
26642670
18 | NAME: ${{ env.NAME }}
26652671
| ^~~~~~~~
2666-
test.yaml:24:33: calling function "success" is not allowed here. "success" is only available in "jobs.<job_id>.if", "jobs.<job_id>.steps.if". see https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability for more details [expression]
2672+
test.yaml:24:27: context "github" is not allowed here. no context is available here. see https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability for more details [expression]
2673+
|
2674+
24 | COMMIT_SHA: ${{ github.sha }}
2675+
| ^~~~~~~~~~
2676+
test.yaml:30:33: calling function "success" is not allowed here. "success" is only available in "jobs.<job_id>.if", "jobs.<job_id>.steps.if". see https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability for more details [expression]
26672677
|
2668-
24 | run: echo 'Success? ${{ success() }}'
2678+
30 | run: echo 'Success? ${{ success() }}'
26692679
| ^~~~~~~~~
26702680
```
26712681

2672-
[Playground](https://rhysd.github.io/actionlint/#eNp8jj1OwzAYhnef4h2QCkNyAC+IgREWTpCkXxtDa0ffT0tU+e7ITU2QkOrFev/sJ0WPyWR0juLJO+D95e3Vg8dZts59pl6KqSRabkCUO6X9vCjg2CmH76qAbWAaNPG8WkCDh8sF+6Cj9e058dfukM7I+V+FLUbiVuk41ZgtSlMorbeo1hy6AnONbsTlLNTlCYqntqi6F6VJaq35u7m/u/3tQcOYsPmwYSCR52tXFvH4hJw3v+2w82vyEwAA//9WsV7P)
2682+
[Playground](https://rhysd.github.io/actionlint/#eNp0j8FOwzAMhu99Ch+QBof2AXJBE0KCQ+Ew7ihNvSawJpXtdFRT3x1lXdsJNF+i/7f953PwCrrINsvQ9yoDeNuWzwrIDlxn2VeoOJmCLOkFYCEt2AyTAmi1kPuZFUDtCI0EGlYLIIe70wkaJzZWxTHQ9/4QjjCO/0Yoeo9UCLbd3KboOU+UsYpeYn7QCebcuhCnmqhTBPq+SGreZ6TeGeR5krB2vMK5VjeoJncxr4JTPb2X5evH5+5lq64PYauXTwS7JTT/u38b7nKgAjQ2wGYXjUHmx/MsT+L+AcZxs/Lu1dr5DQAA//+iDXkG)
26732683

26742684
Some contexts are only available in some places. For example, `env` context is not available at `jobs.<job_id>.env`, but it is
26752685
available at `jobs.<job_id>.steps.env`.
@@ -2958,7 +2968,7 @@ Note that `steps` in Composite action's metadata is not checked at this point. I
29582968
[reusable-workflow-outputs]: https://docs.github.com/en/actions/using-workflows/reusing-workflows#using-outputs-from-a-reusable-workflow
29592969
[inherit-secrets-announce]: https://github.blog/changelog/2022-05-03-github-actions-simplify-using-secrets-with-reusable-workflows/
29602970
[specific-paths-doc]: https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#using-filters-to-target-specific-paths-for-pull-request-or-push-events
2961-
[availability-doc]: https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
2971+
[availability-doc]: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#context-availability
29622972
[deprecate-set-output-save-state]: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
29632973
[deprecate-set-env-add-path]: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/
29642974
[workflow-commands-doc]: https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions

expr_sema.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -462,27 +462,27 @@ func (sema *ExprSemanticsChecker) SetContextAvailability(avail []string) {
462462
}
463463

464464
func (sema *ExprSemanticsChecker) checkAvailableContext(n *VariableNode) {
465-
if len(sema.availableContexts) == 0 {
466-
return
467-
}
468-
469465
ctx := strings.ToLower(n.Name)
470466
for _, c := range sema.availableContexts {
471467
if c == ctx {
472468
return
473469
}
474470
}
475471

476-
s := "contexts are"
477-
if len(sema.availableContexts) == 1 {
478-
s = "context is"
472+
var notes string
473+
switch len(sema.availableContexts) {
474+
case 0:
475+
notes = "no context is available here"
476+
case 1:
477+
notes = "available context is " + quotes(sema.availableContexts)
478+
default:
479+
notes = "available contexts are " + quotes(sema.availableContexts)
479480
}
480481
sema.errorf(
481482
n,
482-
"context %q is not allowed here. available %s %s. see https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability for more details",
483+
"context %q is not allowed here. %s. see https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability for more details",
483484
n.Name,
484-
s,
485-
quotes(sema.availableContexts),
485+
notes,
486486
)
487487
}
488488

expr_sema_test.go

+21
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,7 @@ func TestExprSemanticsCheckOK(t *testing.T) {
754754
}
755755

756756
c := NewExprSemanticsChecker(false, nil)
757+
c.SetContextAvailability([]string{"github", "job", "jobs", "matrix", "steps", "needs", "env", "inputs", "secrets", "vars", "runner"})
757758
if tc.funcs != nil {
758759
c.funcs = tc.funcs
759760
}
@@ -1210,6 +1211,14 @@ func TestExprSemanticsCheckError(t *testing.T) {
12101211
},
12111212
availCtx: []string{"env", "matrix"},
12121213
},
1214+
{
1215+
what: "no available context",
1216+
input: "github",
1217+
expected: []string{
1218+
"context \"github\" is not allowed here. no context is available",
1219+
},
1220+
availCtx: []string{},
1221+
},
12131222
{
12141223
what: "no special function allowed",
12151224
input: "success()",
@@ -1301,6 +1310,8 @@ func TestExprSemanticsCheckError(t *testing.T) {
13011310
}
13021311
if tc.availCtx != nil {
13031312
c.SetContextAvailability(tc.availCtx)
1313+
} else {
1314+
c.SetContextAvailability([]string{"github", "job", "jobs", "matrix", "steps", "needs", "env", "inputs", "secrets", "vars", "runner"})
13041315
}
13051316
if tc.availSP != nil {
13061317
c.SetSpecialFunctionAvailability(tc.availSP)
@@ -1496,6 +1507,16 @@ func TestExprCompareOperandsCheck(t *testing.T) {
14961507
},
14971508
"any": AnyType{},
14981509
}
1510+
c.SetContextAvailability([]string{
1511+
"any",
1512+
"number",
1513+
"string",
1514+
"bool",
1515+
"null",
1516+
"object",
1517+
"array",
1518+
"array_2d",
1519+
})
14991520

15001521
ty, errs := c.Check(e)
15011522
if ok {

testdata/err/context_availability.out

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/test\.yaml:3:34: context "env" is not allowed here\. .+ \[expression\]/
1+
/test\.yaml:3:35: context "env" is not allowed here\. .+ \[expression\]/
22
/test\.yaml:10:12: context "env" is not allowed here\. .+ \[expression\]/
33
/test\.yaml:15:32: context "env" is not allowed here\. .+ \[expression\]/
44
/test\.yaml:25:22: context "env" is not allowed here\. .+ \[expression\]/
@@ -17,6 +17,7 @@
1717
/test\.yaml:106:18: context "runner" is not allowed here\. .+ \[expression\]/
1818
/test\.yaml:111:20: context "env" is not allowed here\. .+ \[expression\]/
1919
/test\.yaml:115:25: context "runner" is not allowed here\. .+ \[expression\]/
20+
/test\.yaml:121:23: context "runner" is not allowed here\. .+ \[expression\]/
2021
/test\.yaml:127:17: context "env" is not allowed here\. .+ \[expression\]/
2122
/test\.yaml:134:23: context "env" is not allowed here\. .+ \[expression\]/
2223
/test\.yaml:139:23: context "env" is not allowed here\. .+ \[expression\]/
@@ -31,3 +32,4 @@
3132
/test\.yaml:208:19: context "runner" is not allowed here\. .+ \[expression\]/
3233
/test\.yaml:210:18: context "runner" is not allowed here\. .+ \[expression\]/
3334
/test\.yaml:217:34: context "env" is not allowed here\. .+ \[expression\]/
35+
/test\.yaml:221:17: context "inputs" is not allowed here\. no context is available here\. .+ \[expression\]/

testdata/err/context_availability.yaml

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# run-name
22
# ERROR at env
3-
run-name: ${{ github.actor}} ${{ env.GITHUB_ACTOR }}
3+
run-name: ${{ github.actor }} ${{ env.GITHUB_ACTOR }}
44

55
# env
66
env:
@@ -117,7 +117,7 @@ jobs:
117117
password: ${{ env.MY_PASSWORD }}
118118
# jobs.<job_id>.services.<service_id>.env.<env_id>
119119
env:
120-
# OK
120+
# ERROR
121121
RUNNER: ${{ runner.name }}
122122
# jobs.<job_id>.strategy
123123
strategy:
@@ -217,3 +217,5 @@ jobs:
217217
services: ${{ inputs.bool || env.FOO }}
218218
steps:
219219
- run: echo
220+
# ERROR at env because `id` allow no context
221+
id: ${{ inputs.foo }}

testdata/err/env_context_banned.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
- uses: test/my-action@main
2222
env:
2323
OS: ${{ runner.os }}
24-
id: foo-${{ runner.name }}
24+
NAME: ${{ runner.name }}
2525
container-job:
2626
runs-on: ubuntu-latest
2727
container:
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
/test\.yaml:12:24: property "calling_workflow_secret" is not defined in object type {.+} \[expression\]/
1+
/test\.yaml:12:23: property "calling_workflow_secret" is not defined in object type {.+} \[expression\]/

testdata/err/reusable_workflow_empty_secrets.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ jobs:
99
steps:
1010
- name: Use a repo or org secret from the calling workflow.
1111
# So referring this secret causes an error
12-
uses: echo ${{ secrets.CALLING_WORKFLOW_SECRET }}
12+
run: echo ${{ secrets.CALLING_WORKFLOW_SECRET }}

testdata/ok/dynamic_shell_name.yaml

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ on: push
22

33
defaults:
44
run:
5-
shell: ${{ env.SHELL }}
5+
shell: ${{ 'sh {0}' }}
66

77
jobs:
88
test:
99
runs-on: ubuntu-latest
1010
defaults:
1111
run:
12-
shell: ${{ env.SHELL }}
12+
shell: ${{ 'sh {0}' }}
1313
steps:
1414
- run: echo hi
15-
shell: ${{ env.SHELL }}
15+
shell: ${{ 'sh {0}' }}

testdata/ok/issue-101.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ jobs:
44
test:
55
runs-on: ubuntu-latest
66
steps:
7-
- uses: echo ${{ runner.arch }}
7+
- run: echo ${{ runner.arch }}

testdata/ok/reusable_workflow_inherit_secrets.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ jobs:
77
steps:
88
# The CALLING_WORKFLOW_SECRET secret is passed with `secrets: inherit`
99
- name: Use a repo or org secret from the calling workflow.
10-
uses: echo ${{ secrets.CALLING_WORKFLOW_SECRET }}
10+
run: echo ${{ secrets.CALLING_WORKFLOW_SECRET }}

testdata/ok/workflow_call_job.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@ jobs:
2727
permissions: read-all
2828
call6:
2929
# Edge case. Give up checking format.
30-
uses: ${{ runner.name }}
30+
uses: ${{ 'oooops' }}

0 commit comments

Comments
 (0)