Skip to content

Demo

Clone and run

An example configuration file and .github directory structure can be found in the example directory of the repository. Use below commands to see octo-linter in action:

git clone https://github.com/keenbytes/octo-linter.git
cd octo-linter/example

docker run --platform=linux/amd64 --rm --name octo-linter \
  -v $(pwd)/dot-github:/dot-github \
  -v $(pwd):/config \
  keenbytes/octo-linter:v2.0.0 \
  lint -p /dot-github -l WARN -c /config/config.yml

Output

This should generate an output similar to the following:

time=2025-06-08T21:18:42.537Z level=WARN msg="action_file_extensions: action 'InvalidActionExtension' file extension must be one of: yml"
time=2025-06-08T21:18:42.548Z level=WARN msg="action_directory_name: action directory name 'InvalidActionExtension' must be lower-case and hyphens only"
time=2025-06-08T21:18:42.548Z level=WARN msg="action_directory_name: action directory name 'InvalidActionName' must be lower-case and hyphens only"
time=2025-06-08T21:18:42.548Z level=ERROR msg="action_step_action: action 'InvalidActionExtension' step 1 calls action 'actions/checkout@v4' that is not a valid local path"
time=2025-06-08T21:18:42.548Z level=ERROR msg="action_step_action: action 'InvalidActionName' step 1 calls action 'actions/checkout@v4' that is not a valid local path"
time=2025-06-08T21:18:42.548Z level=ERROR msg="action_called_step_output_exists: action 'some-action' calls a step 'non-existing-step' output 'output1' but step does not exist"
time=2025-06-08T21:18:42.549Z level=ERROR msg="action_step_action: action 'some-action' step 1 calls action 'actions/checkout@v4' that is not a valid local path"
time=2025-06-08T21:18:42.550Z level=ERROR msg="action_input_required: action 'some-action' input 'output-without-description' does not have a required description"
time=2025-06-08T21:18:42.552Z level=ERROR msg="action_step_env: action 'some-action' step 2 env 'InvalidEnvName' must be alphanumeric uppercase and underscore only"
time=2025-06-08T21:18:42.552Z level=ERROR msg="action_called_input_exists: action 'some-action' calls an input 'non-existing' that does not exist"
time=2025-06-08T21:18:42.552Z level=ERROR msg="workflow_called_input_exists: workflow 'workflow1.yaml' calls an input 'non-existing' that does not exist"
time=2025-06-08T21:18:42.553Z level=ERROR msg="workflow_runs_on_not_latest: workflow 'workflow1.yaml' job 'job-2' should not use 'latest' in 'runs-on' field"
time=2025-06-08T21:18:42.554Z level=WARN msg="workflow_file_extensions: workflow 'workflow1' file extension must be one of: yml"

Exit code

Tool exits with exit code 0 when everything is fine. 1 when there are errors, 2 when there are only warnings. Additionally it may exit with a different code, eg. 22. These numbers indicate another error whilst reading files.

Checking secrets and vars

octo-linter can scan the code for secrets and variables and compare them with file containing list of defined one. If there is any secret or var that is not on the list, tool will output info about it. See below run and its output.

docker run --platform=linux/amd64 --rm --name octo-linter \
  -v $(pwd)/dot-github:/dot-github \
  -v $(pwd):/config \
  keenbytes/octo-linter:v2.0.0 \
  lint -p /dot-github -l WARN -c /config/config.yml \
  -s /config/secrets_list.txt \
  -z /config/vars_list.txt \
  2>&1 | grep NON_EXISTING_ONE
time=2025-06-08T22:09:18.788Z level=ERROR msg="workflow_called_variable_exists_in_file: workflow 'workflow1.yaml' calls a variable 'NON_EXISTING_ONE' that does not exist in the vars file"
time=2025-06-08T22:09:18.789Z level=ERROR msg="workflow_called_variable_exists_in_file: workflow 'workflow1.yaml' calls a secret 'NON_EXISTING_ONE' that does not exist in the secrets file"