Skip to content

Commit

Permalink
Add Ephemeral Environments for GitHub Pull Requests guide
Browse files Browse the repository at this point in the history
Signed-off-by: Stefan Prodan <[email protected]>
  • Loading branch information
stefanprodan committed Feb 14, 2025
1 parent deee283 commit 6c3c187
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 2 deletions.
5 changes: 3 additions & 2 deletions docs/operator/resourcesets/app-definition.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ in a cluster with different configurations.
each target cluster that are deployed by Flux from a management cluster.

**Multi-tenancy provisioning** - Generate a set of resources
(Namespace, ServiceAccount, RoleBinding) for each tenant with specific roles and permissions
to simplify the onboarding of new tenants and their applications on a shared cluster.
(Namespace, ServiceAccount, RoleBinding, Flux GitRepository, Kustomization) for each tenant
with specific roles and permissions to simplify the onboarding of new tenants
and their applications on a shared cluster.

**Dependency management** - Define dependencies between apps to ensure that the resources
are applied in the correct order. The dependencies are more flexible than in Flux,
Expand Down
192 changes: 192 additions & 0 deletions docs/operator/resourcesets/github-pull-requests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
# Ephemeral Environments for GitHub Pull Requests

This guide demonstrates how to use the Flux Operator ResourceSet API to automate the deployment of
applications changes made in GitHub Pull Requests to ephemeral environments for testing and validation.

## Development workflow

- A developer opens a Pull Request with changes to the app code and Helm chart.
- The CI builds and pushes the app container image to GitHub Container Registry. The image is tagged with the Git commit SHA.
- Another developer reviews the changes and labels the Pull Request with the `deploy/flux-preview` label.
- Flux Operator running in the preview cluster scans the repository and finds the new PR using the label filter.
- Flux Operator installs a Helm release using the PR number and the commit SHA inputs to deploy the app and chart changes in the cluster.
- The app is accessible at a preview URL composed of the PR number and the app name.
- The developers iterate over changes, with each push to the PR branch triggering a Helm release upgrade in the cluster.
- Once the PR is approved and merged, the Flux Operator uninstalls the Helm release form the cluster.

## GitOps configuration

To enable the above workflow, we'll define a series of Flux Operator custom resources in the preview cluster.
Note that the preview cluster must be provisioned with a [Flux Instance](../fluxinstance.md).

### Preview namespace

First we'll create a dedicated namespace called `app-preview` where all the app instances generated
from PRs will be deployed. In that namespace, we'll create a Kubernetes Secret containing a GitHub
token that grants read access to the app repository and PRs.

```shell
flux -n app-preview create secret git github-token-readonly \
--url=https://github.com/org/app \
--username=flux \
--password=${GITHUB_TOKEN}
```

### ResourceSet input provider

In the `app-preview` namespace, we'll create a [ResourceSetInputProvider](../resourcesetinputprovider.md)
that tells Flux Operator to scan the repository for PRs labeled with `deploy/flux-preview`:

```yaml
apiVersion: fluxcd.controlplane.io/v1
kind: ResourceSetInputProvider
metadata:
name: app-pull-requests
namespace: app-preview
annotations:
fluxcd.controlplane.io/reconcileEvery: "10m"
spec:
type: GitHubPullRequest
url: https://github.com/org/app
secretRef:
name: github-token-readonly
filter:
labels:
- "deploy/flux-preview"
defaultValues:
chart: "charts/app"
```
### GitHub Webhook
Optionally, we can create a Flux [Webhook Receiver](https://fluxcd.io/flux/components/notification/receivers/)
that GitHub will call to notify the Flux Operator when a new PR is opened or updated:
```yaml
apiVersion: notification.toolkit.fluxcd.io/v1
kind: Receiver
metadata:
name: github-receiver
namespace: app-preview
spec:
type: github
secretRef:
name: receiver-token
resources:
- apiVersion: fluxcd.controlplane.io/v1
kind: ResourceSetInputProvider
name: app-pull-requests
```
### ResourceSet
Finally, to deploy the app from PRs we'll create a [ResourceSet](../resourceset.md)
that takes its inputs from the `ResourceSetInputProvider`:

```yaml
apiVersion: fluxcd.controlplane.io/v1
kind: ResourceSet
metadata:
name: app
namespace: app-preview
spec:
inputsFrom:
- apiVersion: fluxcd.controlplane.io/v1
kind: ResourceSetInputProvider
name: app-pull-requests
resources:
- apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: app-<< inputs.id >>
namespace: app-preview
spec:
interval: 1h
url: https://github.com/org/app
ref:
commit: << inputs.sha >>
secretRef:
name: github-token-readonly
- apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: app-<< inputs.id >>
namespace: app-preview
annotations:
event.toolkit.fluxcd.io/preview-url: "https://app-<< inputs.id >>.example.com"
event.toolkit.fluxcd.io/branch: << inputs.branch | quote >>
event.toolkit.fluxcd.io/author: << inputs.author | quote >>
spec:
interval: 10m
releaseName: app-<< inputs.id >>
chart:
spec:
chart: << inputs.chart >>
reconcileStrategy: Revision
sourceRef:
kind: GitRepository
name: app-<< inputs.id >>
values:
image:
tag: << inputs.sha >>
ingress:
hosts:
- host: app-<< inputs.id >>.example.com
```

The above `ResouceSet` will generate a Flux `GitRepository` and a `HelmRelease` for each opened PR.
The PR number passed as `<< inputs.id >>` is used as the name suffix for the Flux objects,
and is also used to compose the Ingress host name where the app can be accessed.

The latest commit SHA pushed to the PR HEAD is passed as `<< inputs.sha >>`,
the SHA is used to set the app image tag in the Helm release values.

The preview URL, branch name and author are set as annotations on the HelmRelease
object to enrich the Flux notifications that the dev team receives.

### Notifications

To receive notifications when a PR triggers a Helm release install,
upgrade and uninstall (including any deploy errors),
a Flux [Alert](https://fluxcd.io/flux/components/notification/alerts/)
can be created in the `app-preview` namespace:

```yaml
---
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Provider
metadata:
name: slack-bot
namespace: app-preview
spec:
type: slack
channel: general
address: https://slack.com/api/chat.postMessage
secretRef:
name: slack-bot-token
---
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Alert
metadata:
name: slack
namespace: app-preview
spec:
providerRef:
name: slack-bot
eventSources:
- kind: GitRepository
name: '*'
- kind: HelmRelease
name: '*'
eventMetadata:
cluster: "preview-cluster-1"
region: "us-east-1"
```

Note that all the Kubernetes manifests part of this workflow should be stored in the Git repository
used to define the preview cluster desired state.

To learn more about ResourceSets and the various configuration options, see the following docs:

- [ResourceSet CRD](../resourceset.md)
- [ResourceSetInputProvider CRD](../resourcesetinputprovider.md)
3 changes: 3 additions & 0 deletions docs/operator/resourcesets/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ or GitLab Merge Request to an ephemeral environment for testing and validation.
The Flux Operator has the ability to create, update and delete application instances on-demand
based on the ResourceSet definitions and Pull/Merge Requests state.

To get started with self-service environments see
the [Ephemeral Environments for GitHub Pull Requests](./github-pull-requests.md) guide.

Another use-case is to automate the provisioning of new environments for feature branches,
and for long-lived branches to deploy to dedicated namespaces and/or clusters, effectively
enabling Namespace-as-a-Service to developers securely in a GitOps manner.
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ nav:
- ResourceSet Guides:
- Introduction: operator/resourcesets/introduction.md
- App Definitions: operator/resourcesets/app-definition.md
- Ephemeral envs for GitHub PRs: operator/resourcesets/github-pull-requests.md
- API Reference:
- FluxInstance: operator/fluxinstance.md
- FluxReport: operator/fluxreport.md
Expand Down

0 comments on commit 6c3c187

Please sign in to comment.