GitHub-Actions

GitHub-Actions is a managed CI/CD offering integrated into GitHub. For standardisation and re-use within Gardener-Project, we maintain some re-usable Actions and Workflows (kept in cc-utils repository). Those offer functionality similar to Concourse-Pipeline-Template. This includes integration with OCM (Open Component Model), as well as release (notes) handling.

To improve security posture, we make use of trustbased-authentication, and avoid usage of static credentials where possible.

Migration from Concourse-Pipelines

The default pipeline setup for Concourse-Pipelines consists of three pipelines:

  • head-update (run for certain branches - typically default + release-branches)

  • pull-request (run for pullrequests)

  • release (manually triggered to publish new releases)

This is migrated to workflows of the following layout:

.github/workflows/build.yaml       # shared; called by other workflows
.github/workflows/release.yaml     # for manually triggering releases
.github/workflows/non-release.yaml # for triggering upon head-updates / pullrequests

Branch-Protection -> Rulesets

Most repositories use branch-protections to forbid directly pushing to a branch. Some pipelines, most prominently release-pipelines (which push release- and “bump”-commits), need to circumvent those rules. As we want to avoid using static credentials (for Service-Accounts w/ owner-permissions), we use a GitHub-App for granting such permissions more fine-granular.

However, as discussed here, it is only possible to grant exceptions (or “bypassers”, as GitHub Rulesets call them) to branch protections if using the more modern Rulesets. Hence, as part of migration to GitHub-Actions, it is necessary to migrate branch-protections to rulesets.

Note

It is important to no longer use “classical” branch protections after migration of release-pipeline to GitHub-Actions. Configure any protection-rules using the more modern Rulesets, instead. The latter are a superset to branch-protections w.r.t. configuration options.

Pull-Requests from forked Repositories

To mitigate harm from malicious Pull-Requests, GitHub-Actions-Workflow-Runs are run with restricted privileges. If using pull_request as pipeline-trigger, corresponding workflow-runs will only have readonly-access to target-repository. This prevents such runs to push build artefacts, such as OCI-Images or Helmcharts (to OCI-Registries).

As an alternative, there is the pull_request_target trigger, which does not have this limitation. However, by default, thus-triggered runs will be based on the pull-request’s target repository, i.e. the actual changes proposed by a Pull-Request will not be visible to the pipeline-run.

For the latter case, there is the trusted-checkout action, which will circumvent this limiation, and explicitly checkout commits from trusted pullrequests. Pullrequests are considered to be trusted, if

  • the fork’s owner is the same as the target-repository (i.e. a fork within the same organisation)

OR - the pullrequest-author is either of:

  • COLLABORATOR

  • CONTRIBUTOR

  • MEMBER (org-member)

  • OWNER (repository-owner)

Note

For pullrequests that are not considered to be trusted, the workflow-run will still be executed. However, re-usable workflows from cc-utils will not attempt to push build-results, nor will the run be based on the changes from the pullrequest, which may be unintuitive.

In such cases, a warning is emitted into the pipeline-run’s summary.

When to use what

If a workflow does not need to publish changes from pullrequests, use on.pull_request. Otherwise, use on.pull_request_target. In this case, consistently use trusted-checkout instead of actions/checkout.

Warning

If using pull_request_target, special care needs to be done to catch malicious changes, especially such changes that are done in buildscripts.

Caveats

Regardless which of on.pull_request or on.pull_request_target is used, workflow-runs will always be based on target-repository’s local workflow- and actions-definitions.