diff --git a/README.md b/README.md index f70336f..b058f0e 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Currently supported formats are [Bitbucket Pipelines](https://support.atlassian.com/bitbucket-cloud/docs/configure-bitbucket-pipelinesyml/), [GitLab CI](https://docs.gitlab.com/ee/ci/yaml/gitlab_ci_yaml.html), [GitHub Actions](https://docs.github.com/en/actions), +[Drone CI](https://docs.drone.io/pipeline/overview/), and (very limited) [Ansible](https://docs.ansible.com/ansible/2.9/modules/shell_module.html) ## Usage @@ -78,6 +79,12 @@ is considered a shell script. this is a todo, it should be simple enough to only check `sh` and `bash` scripts with right shebang line * [expressions](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions) get replaced with a simple variable before running shellcheck +### Drone CI + +Drone CI has a very simple file structure. As far as I can tell it only has +conditions, but no deep nesting or includes. All command lists are concatenated +and checked as a shell script. + ### GitLab CI Pipelines GitLab CI files have more structure, and we try to support more of it. diff --git a/test-input/.drone.yml b/test-input/.drone.yml new file mode 100644 index 0000000..472ea6a --- /dev/null +++ b/test-input/.drone.yml @@ -0,0 +1,18 @@ +--- +# Drone CI example, from https://docs.drone.io/pipeline/overview/ +kind: pipeline +type: docker +name: default + +steps: +- name: backend + image: golang + commands: + - go build + - go test + +- name: frontend + image: node + commands: + - npm install + - npm run test diff --git a/yaml_shellcheck.py b/yaml_shellcheck.py index ba16ae4..24f9324 100755 --- a/yaml_shellcheck.py +++ b/yaml_shellcheck.py @@ -157,6 +157,23 @@ def get_runs(data, path): return result +def get_drone_scripts(data): + """Drone CI has a simple file format, with all scripts in + `lists in steps[].commands[]`, see https://docs.drone.io/yaml/exec/ + """ + result = {} + if "steps" not in data: + return result + jobkey = data.get("name", "unknown") + for item in data["steps"]: + section = item.get("name") + result[f"{jobkey}/{section}"] = "\n".join(item.get("commands", [])) + logging.debug("got scripts: %s", result) + for key in result: + logging.debug("%s: %s", key, result[key]) + return result + + def get_gitlab_scripts(data): """GitLab is nice, as far as I can tell its files have a flat hierarchy with many small job entities""" @@ -245,6 +262,11 @@ def select_yaml_schema(data, filename): elif isinstance(data, dict) and "on" in data and "jobs" in data: logging.info(f"read {filename} as GitHub Actions config...") return get_github_scripts + elif ( + isinstance(data, dict) and "steps" in data and "kind" in data and "type" in data + ): + logging.info(f"read {filename} as Drone CI config...") + return get_drone_scripts elif isinstance(data, list): logging.info(f"read {filename} as Ansible file...") return get_ansible_scripts