Skip to content

Feature: informative error message #646

@r-ea

Description

@r-ea

Pre-submission checks

  • I am not reporting a bug (crash, false positive/negative, etc). These must be filed via the bug report template.
  • I have looked through the open issues for a duplicate request.

What's the problem this feature will solve?

When running zizmor on a badly formatted workflow file, the program exits with an error code without giving much explanation regarding what went wrong and how to fix the issue.

For instance, consider the following workflow file:

name: Test

on:
  workflow_call:
    inputs:
      my-input:
        descripton: My input
    secrets:
      my-secret:
        description: My secret

jobs:
  job:
    runs-on: ubuntu-latest
    steps:
      - run: echo ${{ inputs.my-input }}

This workflow presents 3 issues:

  1. my-input.descripton has a typo, i.e, invalid property
  2. my-input.type property is missing
  3. my-secret.required property is missing

When running zizmor on this workflow, the program prints the following output:

failed to register input: ./.github/workflows/workflow.yaml

Caused by:
    0: invalid GitHub Actions workflow: file://./.github/workflows/workflow.yaml
       
       Caused by:
           data did not match any variant of untagged enum Trigger
    1: invalid GitHub Actions definition: file://./.github/workflows/workflow.yaml
       
       Caused by:
           missing field `runs`
    2: failed to register input as workflow or action

Zizmor attempted to unmarshall the file into a predefined Workflow structure which expected the file to follow a certain pattern and contain some fields that were missing, which in turn caused the program to exit with an error message without explicitly stating the issue itself.

Describe the solution you'd like

When running into such errors, zizmor could attempt to provide more information about the encountered formatting issues. One solution could be validating the workflow file with the GitHub Workflow schema. For example, take the following code:

fn main() {
    let workflow = include_str!("../workflow.yaml");
    let workflow: serde_json::Value = serde_yaml::from_str(workflow).unwrap();

    let schema = include_str!("../github-workflow.json");
    let schema: serde_json::Value = serde_json::from_str(schema).unwrap();

    let validator = jsonschema::validator_for(&schema).unwrap();
    let output = validator.apply(&workflow).basic();
    match output {
        jsonschema::BasicOutput::Valid(_) => println!("ok"),
        jsonschema::BasicOutput::Invalid(errors) => {
            for error in errors {
                println!(
                    "Error: {}: {}",
                    error.instance_location(),
                    error.error_description(),
                )
            }
        }
    }
}

If it gets executed on the aforementioned problematic workflow, it will print the following output:

Error: /on: {"workflow_call":{"inputs":{"my-input":{"descripton":"My input"}},"secrets":{"my-secret":{"description":"My secret"}}}} is not one of ["branch_protection_rule","check_run","check_suite","create","delete","deployment","deployment_status","discussion","discussion_comment","fork","gollum","issue_comment","issues","label","merge_group","milestone","page_build","project","project_card","project_column","public","pull_request","pull_request_review","pull_request_review_comment","pull_request_target","push","registry_package","release","status","watch","workflow_call","workflow_dispatch","workflow_run","repository_dispatch"]
Error: /on: {"workflow_call":{"inputs":{"my-input":{"descripton":"My input"}},"secrets":{"my-secret":{"description":"My secret"}}}} is not of type "string"
Error: /on: {"workflow_call":{"inputs":{"my-input":{"descripton":"My input"}},"secrets":{"my-secret":{"description":"My secret"}}}} is not of type "array"
Error: /on/workflow_call/inputs/my-input: Additional properties are not allowed ('descripton' was unexpected)
Error: /on/workflow_call/inputs/my-input: "type" is a required property
Error: /on/workflow_call/secrets/my-secret: "required" is a required property

As expected, the validation failed and the last three error messages point out the concrete issues that the file has. Maybe something like this could be implemented within the zizmor's file parsing logic in order to give more insightful feedback to the users?

On another note, whenever zizmor runs into such problematic files, it stops the whole execution. Maybe another approach could be to ignore these files and proceed with the analysis of the remaining workflows which are contained within the folder?

Additional context

The example above is an exaggeration since that workflow would never even run. But one reason why this could be a useful feature is because the following workflow is in fact valid and can be called:

name: Test

on:
  workflow_call:
    secrets:
      my-secret:
        description: My secret

jobs:
  job:
    runs-on: ubuntu-latest
    steps:
      - run: echo ${{ secrets.my-secret }}

Even though it is missing the my-secret.required property, it is still possible to execute this workflow all while zizmor would throw an error.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions