Skip to content

Commit 6e0fe86

Browse files
committed
Document release process for Crossplane extensions.
Signed-off-by: Jason Tang <[email protected]>
1 parent 9f943f4 commit 6e0fe86

File tree

5 files changed

+1105
-0
lines changed

5 files changed

+1105
-0
lines changed
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
---
2+
title: Releasing Crossplane Extensions
3+
weight: 80
4+
description: "Configuring build pipelines for Crossplane extensions with GitHub
5+
Actions"
6+
---
7+
8+
Crossplane extensions are built as OCI images in the [xpkg] format. Authors and
9+
maintainers of Crossplane extensions must push their packages to an OCI
10+
registry before they can be used and referenced by Crossplane.
11+
12+
{{< hint "tip" >}}
13+
For more information about Crossplane packages, review the concepts
14+
[here]({{<ref "../concepts/packages" >}}).
15+
{{< /hint >}}
16+
17+
## Typical Workflow
18+
19+
This guide covers configuring a GitHub Action for building Crossplane
20+
providers and functions and pushing them to an OCI registry such as `ghcr.io`.
21+
22+
A typical GitHub workflow definition contains the following steps:
23+
24+
1. Fetching the source repository
25+
2. Authenticating to a remote registry
26+
3. Building and packaging artifacts
27+
4. Pushing (publishing) the artifact
28+
29+
{{< hint "warning" >}}
30+
The supplied credentials for the remote registry require read+write access, as
31+
subsequent requests to the registry will specify `push` authorization scope.
32+
{{< /hint >}}
33+
34+
Fortunately, the template repositories for [providers] and [functions] provide
35+
a functional GitHub Action in `.github/workflows/ci.yml`. The following
36+
sections of this guide cover configuration options and conventions for each.
37+
38+
## Common Configuration
39+
40+
All workflows require references to credentials for a remote registry.
41+
Typically, these are stored as [GitHub Actions Secrets], and authentication
42+
is performed via the`docker/login-action`
43+
[action](http://github.com/docker/login-action).
44+
45+
For example, adding the following step to a pipeline will authenticate
46+
the job to `ghcr.io` using the workflow's ephemeral GitHub OIDC token.
47+
48+
```yaml
49+
- name: Login to GHCR
50+
uses: docker/login-action@v3
51+
with:
52+
registry: ghcr.io
53+
username: ${{ github.repository_owner }}
54+
password: ${{ secrets.GITHUB_TOKEN }}
55+
```
56+
57+
{{< hint "important" >}}
58+
By default, the job's OIDC token will not have permission to write packages
59+
to `ghcr.io`. This can be configured in the GitHub repository's settings, or
60+
declared [explicitly](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token) in the workflow definition YAML file.
61+
{{< /hint >}}
62+
63+
For other registries, it is still best practice to reference credentials as
64+
custom Secret variables. For example:
65+
66+
```yaml
67+
- name: Login to Upbound
68+
uses: docker/login-action@v3
69+
if: env.XPKG_ACCESS_ID != ''
70+
with:
71+
registry: xpkg.upbound.io
72+
username: ${{ env.XPKG_ACCESS_ID }}
73+
password: ${{ secrets.XPKG_TOKEN }}
74+
```
75+
76+
## Branching Conventions
77+
78+
Repositories for Crossplane extensions follow similar branching conventions
79+
to upstream Crossplane, where the release process is predicated on the workflow
80+
executing in branches with the `release-*` prefix. `main` is often included,
81+
though a conventional release process would not build and push off of tags on
82+
`main`.
83+
84+
```yaml
85+
on:
86+
push:
87+
branches:
88+
- main
89+
- release-*
90+
```
91+
92+
For example, when releasing `v0.1.0` of an extension, the conventional
93+
process is to cut a release branch `release-0.1` at the git commit
94+
where it will be built, and tag it as `v0.1.0`.
95+
96+
{{< hint "note" >}}
97+
Some custom workflows may accept an explicit input for the remote reference,
98+
which overrides inferring from a git ref or tag. The [ci.yml] file for
99+
`crossplane-contrib/function-python` is a good example.
100+
{{< /hint >}}
101+
102+
## Configuring Workflows for Functions
103+
104+
Function workflow definitions will differ based on the base language the
105+
function is implemented in. For example, a Python function will require
106+
a Python environment in the GitHub Action runner:
107+
108+
```yaml
109+
- name: Setup Python
110+
uses: actions/setup-python@v5
111+
with:
112+
python-version: ${{ env.PYTHON_VERSION }}
113+
114+
- name: Setup Hatch
115+
run: pipx install hatch==1.7.0
116+
117+
- name: Lint
118+
run: hatch run lint:check
119+
```
120+
121+
While the template repository provides a working pipeline definition, users may
122+
choose to customize their environment with different tooling.
123+
124+
Functions also require a runtime image of the core business logic to be
125+
built and embedded into the Function package. The default workflow definition
126+
will build for two platforms: `linux/amd64` and `linux/arm64`.
127+
128+
```yaml
129+
- name: Build Runtime
130+
id: image
131+
uses: docker/build-push-action@v6
132+
with:
133+
context: .
134+
platforms: linux/${{ matrix.arch }}
135+
cache-from: type=gha
136+
cache-to: type=gha,mode=max
137+
target: image
138+
build-args:
139+
PYTHON_VERSION=${{ env.PYTHON_VERSION }}
140+
outputs: type=docker,dest=runtime-${{ matrix.arch }}.tar
141+
```
142+
143+
## Configuring Workflows for Providers
144+
145+
Providers, unlike Functions, use custom `make` targets in the [build submodule]
146+
for building and pushing Crossplane Provider packages.
147+
148+
Configuring the workflow for a specific registry involves two steps:
149+
150+
1. Updating the registry variables in the top-level `Makefile`.
151+
2. Referencing GitHub Actions Secrets for authorized credentials to the
152+
registry.
153+
154+
### Configure Target Registry
155+
156+
The provider template repository includes a top-level `Makefile`. Edit
157+
the following variables to define the target registry:
158+
159+
1. `XPKG_REG_ORGS` - a space-delimited list of target repositories.
160+
2. `XPKG_REG_ORGS_NO_PROMOTE` - for registries that do not use or infer
161+
channel tags, such as `xpkg.upbound.io`.
162+
163+
For example, the following dual-pushes to `xpkg.upbound.io` as well as
164+
`index.docker.io`:
165+
166+
```make
167+
XPKG_REG_ORGS ?= xpkg.upbound.io/crossplane-contrib index.docker.io/crossplanecontrib
168+
169+
XPKG_REG_ORGS_NO_PROMOTE ?= xpkg.upbound.io/crossplane-contrib
170+
```
171+
172+
## Reusable Workflows
173+
174+
The [crossplane-contrib/provider-workflows] repository provide reusable
175+
workflow definitions that can be called from a custom CI pipeline.
176+
177+
For example, the following snippet references the callable workflow to
178+
build and push the `provider-kubernetes` package to both `ghcr.io` and
179+
`xpkg.upbound.io`:
180+
181+
```yaml
182+
jobs:
183+
publish-provider-package:
184+
uses: crossplane-contrib/provider-workflows/.github/workflows/publish-provider-non-family.yml@main
185+
with:
186+
repository: provider-kubernetes
187+
version: ${{ github.event.inputs.version }}
188+
go-version: ${{ github.event.inputs.go-version }}
189+
cleanup-disk: true
190+
secrets:
191+
GHCR_PAT: ${{ secrets.GITHUB_TOKEN }}
192+
XPKG_UPBOUND_TOKEN: ${{ secrets.XPKG_UPBOUND_TOKEN }}
193+
```
194+
195+
{{< hint "tip" >}}
196+
The reusable workflows referenced here will publish to `ghcr.io` by default.
197+
Ensure that the default GitHub Actions OIDC token is granted the
198+
`packages: write` permission.
199+
{{< /hint >}}
200+
201+
## Troubleshooting
202+
203+
{{< expand "Why is my workflow is failing with a 404 error code?" >}}
204+
Ensure the target repository exists in the registry. You will need to create
205+
it if it does not already exist.
206+
{{</expand >}}
207+
208+
{{< expand "Why is my workflow failing with a 401 error code?" >}}
209+
Ensure the credentials used during the registry login step are authorized to
210+
pull and push, and that the `{{ secrets.* }}` variable substitutions match
211+
what is configured in GitHub.
212+
{{</expand >}}
213+
214+
<!-- Named Links -->
215+
[xpkg]: https://github.com/crossplane/crossplane/blob/main/contributing/specifications/xpkg.md
216+
[functions]: https://github.com/crossplane/function-template-go/blob/main/.github/workflows/ci.yml
217+
[providers]: https://github.com/crossplane/upjet-provider-template/blob/main/.github/workflows/ci.yml
218+
[GitHub Actions Secrets]: https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions
219+
[build submodule]: https://github.com/crossplane/build
220+
[ci.yml]: https://github.com/crossplane-contrib/function-python/blob/main/.github/workflows/ci.yml
221+
[crossplane-contrib/provider-workflows]: https://github.com/crossplane-contrib/provider-workflows/blob/main/.github/workflows

0 commit comments

Comments
 (0)