Skip to content
shellhacks.dev
CI/CD

Group log lines in GitHub Actions

Fold log output in GitHub Actions by printing ::group::Title and ::endgroup::. A wrapper function keeps the pair together and passes the command's status on.

1 min read
Summarize in AI

A build step prints three hundred lines, and the one you need is hidden among them.

Shell
group() {
  local title=$1; shift
  echo "::group::$title"
  "$@"; local rc=$?
  echo "::endgroup::"
  return $rc
}
group "Install" echo "installing 42 packages"
group "Test" sh -c 'echo "running tests"; exit 3'
echo "test group status: $?"
Text
::group::Install
installing 42 packages
::endgroup::
::group::Test
running tests
::endgroup::
test group status: 3

The runner watches the output for lines that begin with ::. Everything between ::group::title and ::endgroup:: is folded under the title in the log, as the workflow commands documentation describes. Outside the runner, as above, the lines are printed literally. The wrapper closes the group even when the command fails and returns its exit status, so the step still fails.

GitHub does not support nested groups, so wrap one level only. The wrapper runs the command in the current shell, so a function works as well as a program. On a developer machine the marker lines are noise, so print them only when the GITHUB_ACTIONS variable is set.

Share

More snippets

CI/CD

Check what changed in a pull request

List the files a pull request changed with git diff --name-only origin/main...HEAD. Three dots compare against the merge base, and a shallow checkout cannot do it.

2 min read
CI/CD

Print a warning annotation

Print ::warning file=...,line=...::message from a step to show an annotation on the run and in the pull request diff. Newlines in the text must be encoded.

1 min read
CI/CD

Run a script from the repo

Run a repository script from a workflow with run: ./script.sh only if Git stores it as executable. Otherwise the step fails with Permission denied, status 126.

2 min read

Get new posts by email

One email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.