Skip to content

Commit

Permalink
Merge branch 'strict-available-contexts'
Browse files Browse the repository at this point in the history
  • Loading branch information
rhysd committed Dec 27, 2024
2 parents d3399fe + d936cb4 commit 49b7457
Show file tree
Hide file tree
Showing 12 changed files with 61 additions and 26 deletions.
18 changes: 14 additions & 4 deletions docs/checks.md
Original file line number Diff line number Diff line change
Expand Up @@ -2642,6 +2642,12 @@ jobs:
env:
# ERROR: 'env' context is not available here
NAME: ${{ env.NAME }}
services:
redis:
image: redis
env:
# ERROR: No context is allowed here
COMMIT_SHA: ${{ github.sha }}
steps:
- env:
# OK: 'env' context is available here
Expand All @@ -2663,13 +2669,17 @@ test.yaml:18:17: context "env" is not allowed here. available contexts are "gith
|
18 | NAME: ${{ env.NAME }}
| ^~~~~~~~
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]
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]
|
24 | COMMIT_SHA: ${{ github.sha }}
| ^~~~~~~~~~
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]
|
24 | run: echo 'Success? ${{ success() }}'
30 | run: echo 'Success? ${{ success() }}'
| ^~~~~~~~~
```

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

Some contexts are only available in some places. For example, `env` context is not available at `jobs.<job_id>.env`, but it is
available at `jobs.<job_id>.steps.env`.
Expand Down Expand Up @@ -2958,7 +2968,7 @@ Note that `steps` in Composite action's metadata is not checked at this point. I
[reusable-workflow-outputs]: https://docs.github.com/en/actions/using-workflows/reusing-workflows#using-outputs-from-a-reusable-workflow
[inherit-secrets-announce]: https://github.blog/changelog/2022-05-03-github-actions-simplify-using-secrets-with-reusable-workflows/
[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
[availability-doc]: https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
[availability-doc]: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#context-availability
[deprecate-set-output-save-state]: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
[deprecate-set-env-add-path]: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/
[workflow-commands-doc]: https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions
Expand Down
20 changes: 10 additions & 10 deletions expr_sema.go
Original file line number Diff line number Diff line change
Expand Up @@ -462,27 +462,27 @@ func (sema *ExprSemanticsChecker) SetContextAvailability(avail []string) {
}

func (sema *ExprSemanticsChecker) checkAvailableContext(n *VariableNode) {
if len(sema.availableContexts) == 0 {
return
}

ctx := strings.ToLower(n.Name)
for _, c := range sema.availableContexts {
if c == ctx {
return
}
}

s := "contexts are"
if len(sema.availableContexts) == 1 {
s = "context is"
var notes string
switch len(sema.availableContexts) {
case 0:
notes = "no context is available here"
case 1:
notes = "available context is " + quotes(sema.availableContexts)
default:
notes = "available contexts are " + quotes(sema.availableContexts)
}
sema.errorf(
n,
"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",
"context %q is not allowed here. %s. see https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability for more details",
n.Name,
s,
quotes(sema.availableContexts),
notes,
)
}

Expand Down
21 changes: 21 additions & 0 deletions expr_sema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,7 @@ func TestExprSemanticsCheckOK(t *testing.T) {
}

c := NewExprSemanticsChecker(false, nil)
c.SetContextAvailability([]string{"github", "job", "jobs", "matrix", "steps", "needs", "env", "inputs", "secrets", "vars", "runner"})
if tc.funcs != nil {
c.funcs = tc.funcs
}
Expand Down Expand Up @@ -1210,6 +1211,14 @@ func TestExprSemanticsCheckError(t *testing.T) {
},
availCtx: []string{"env", "matrix"},
},
{
what: "no available context",
input: "github",
expected: []string{
"context \"github\" is not allowed here. no context is available",
},
availCtx: []string{},
},
{
what: "no special function allowed",
input: "success()",
Expand Down Expand Up @@ -1301,6 +1310,8 @@ func TestExprSemanticsCheckError(t *testing.T) {
}
if tc.availCtx != nil {
c.SetContextAvailability(tc.availCtx)
} else {
c.SetContextAvailability([]string{"github", "job", "jobs", "matrix", "steps", "needs", "env", "inputs", "secrets", "vars", "runner"})
}
if tc.availSP != nil {
c.SetSpecialFunctionAvailability(tc.availSP)
Expand Down Expand Up @@ -1496,6 +1507,16 @@ func TestExprCompareOperandsCheck(t *testing.T) {
},
"any": AnyType{},
}
c.SetContextAvailability([]string{
"any",
"number",
"string",
"bool",
"null",
"object",
"array",
"array_2d",
})

ty, errs := c.Check(e)
if ok {
Expand Down
4 changes: 3 additions & 1 deletion testdata/err/context_availability.out
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/test\.yaml:3:34: context "env" is not allowed here\. .+ \[expression\]/
/test\.yaml:3:35: context "env" is not allowed here\. .+ \[expression\]/
/test\.yaml:10:12: context "env" is not allowed here\. .+ \[expression\]/
/test\.yaml:15:32: context "env" is not allowed here\. .+ \[expression\]/
/test\.yaml:25:22: context "env" is not allowed here\. .+ \[expression\]/
Expand All @@ -17,6 +17,7 @@
/test\.yaml:106:18: context "runner" is not allowed here\. .+ \[expression\]/
/test\.yaml:111:20: context "env" is not allowed here\. .+ \[expression\]/
/test\.yaml:115:25: context "runner" is not allowed here\. .+ \[expression\]/
/test\.yaml:121:23: context "runner" is not allowed here\. .+ \[expression\]/
/test\.yaml:127:17: context "env" is not allowed here\. .+ \[expression\]/
/test\.yaml:134:23: context "env" is not allowed here\. .+ \[expression\]/
/test\.yaml:139:23: context "env" is not allowed here\. .+ \[expression\]/
Expand All @@ -31,3 +32,4 @@
/test\.yaml:208:19: context "runner" is not allowed here\. .+ \[expression\]/
/test\.yaml:210:18: context "runner" is not allowed here\. .+ \[expression\]/
/test\.yaml:217:34: context "env" is not allowed here\. .+ \[expression\]/
/test\.yaml:221:17: context "inputs" is not allowed here\. no context is available here\. .+ \[expression\]/
6 changes: 4 additions & 2 deletions testdata/err/context_availability.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# run-name
# ERROR at env
run-name: ${{ github.actor}} ${{ env.GITHUB_ACTOR }}
run-name: ${{ github.actor }} ${{ env.GITHUB_ACTOR }}

# env
env:
Expand Down Expand Up @@ -117,7 +117,7 @@ jobs:
password: ${{ env.MY_PASSWORD }}
# jobs.<job_id>.services.<service_id>.env.<env_id>
env:
# OK
# ERROR
RUNNER: ${{ runner.name }}
# jobs.<job_id>.strategy
strategy:
Expand Down Expand Up @@ -217,3 +217,5 @@ jobs:
services: ${{ inputs.bool || env.FOO }}
steps:
- run: echo
# ERROR at env because `id` allow no context
id: ${{ inputs.foo }}
2 changes: 1 addition & 1 deletion testdata/err/env_context_banned.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- uses: test/my-action@main
env:
OS: ${{ runner.os }}
id: foo-${{ runner.name }}
NAME: ${{ runner.name }}
container-job:
runs-on: ubuntu-latest
container:
Expand Down
2 changes: 1 addition & 1 deletion testdata/err/reusable_workflow_empty_secrets.out
Original file line number Diff line number Diff line change
@@ -1 +1 @@
/test\.yaml:12:24: property "calling_workflow_secret" is not defined in object type {.+} \[expression\]/
/test\.yaml:12:23: property "calling_workflow_secret" is not defined in object type {.+} \[expression\]/
2 changes: 1 addition & 1 deletion testdata/err/reusable_workflow_empty_secrets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ jobs:
steps:
- name: Use a repo or org secret from the calling workflow.
# So referring this secret causes an error
uses: echo ${{ secrets.CALLING_WORKFLOW_SECRET }}
run: echo ${{ secrets.CALLING_WORKFLOW_SECRET }}
6 changes: 3 additions & 3 deletions testdata/ok/dynamic_shell_name.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ on: push

defaults:
run:
shell: ${{ env.SHELL }}
shell: ${{ 'sh {0}' }}

jobs:
test:
runs-on: ubuntu-latest
defaults:
run:
shell: ${{ env.SHELL }}
shell: ${{ 'sh {0}' }}
steps:
- run: echo hi
shell: ${{ env.SHELL }}
shell: ${{ 'sh {0}' }}
2 changes: 1 addition & 1 deletion testdata/ok/issue-101.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: echo ${{ runner.arch }}
- run: echo ${{ runner.arch }}
2 changes: 1 addition & 1 deletion testdata/ok/reusable_workflow_inherit_secrets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ jobs:
steps:
# The CALLING_WORKFLOW_SECRET secret is passed with `secrets: inherit`
- name: Use a repo or org secret from the calling workflow.
uses: echo ${{ secrets.CALLING_WORKFLOW_SECRET }}
run: echo ${{ secrets.CALLING_WORKFLOW_SECRET }}
2 changes: 1 addition & 1 deletion testdata/ok/workflow_call_job.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ jobs:
permissions: read-all
call6:
# Edge case. Give up checking format.
uses: ${{ runner.name }}
uses: ${{ 'oooops' }}

0 comments on commit 49b7457

Please sign in to comment.