|
1 | | -# pr-bot |
| 1 | +# Preview Environment PR Commenter (Go) |
2 | 2 |
|
3 | | -## Requirements |
| 3 | +A small Kubernetes service that watches **Argo CD Applications** representing preview environments and posts a **GitHub Pull Request comment** with: |
| 4 | + |
| 5 | +- the latest commit SHA deployed, |
| 6 | +- an Argo CD link, |
| 7 | +- preview links rendered as **QR codes** (minted via a protected QR signing service), |
| 8 | +- Grafana metrics and Loki logs links. |
| 9 | + |
| 10 | +It’s designed for GitOps/preview workflows where each PR spins up a temporary environment and you want an automatic “here’s where it is” comment. |
4 | 11 |
|
5 | | -- You need a k8s cluster. |
6 | | -- You need to deploy the resources below before to the `glueops-core` cluster |
7 | | -- You need a git provider api token (Ex. Github Personal Access Token) |
8 | | -- You need a captain domain |
9 | | - |
10 | | -```yaml |
11 | 12 | --- |
12 | | -apiVersion: v1 |
13 | | -kind: Secret |
14 | | -metadata: |
15 | | - name: git-provider-api-token |
16 | | -type: Opaque |
17 | | -data: |
18 | | - token: <base64 encoded github token> |
| 13 | + |
| 14 | +## How it works |
| 15 | + |
| 16 | +On a fixed interval, the service: |
| 17 | + |
| 18 | +1. Lists Argo CD `Applications` (`argoproj.io/v1alpha1`) from Kubernetes using the dynamic client. |
| 19 | +2. Filters to apps that: |
| 20 | + - have at least one `ownerReference`, |
| 21 | + - have annotation `preview_environment: "true"`, |
| 22 | + - have annotation `head_sha` and the SHA appears in `status.sync.revisions`, |
| 23 | + - have `status.health.status` of `Healthy` or `Degraded`, |
| 24 | + - have at least one `status.summary.externalURLs` entry, |
| 25 | + - contain required GitHub metadata annotations: `repository_organization`, `repository_name`, `pull_request_number`. |
| 26 | +3. Builds links to: |
| 27 | + - Argo CD application page, |
| 28 | + - Grafana “workload metrics” dashboard, |
| 29 | + - Loki logs dashboard. |
| 30 | +4. For each external URL, calls a QR mint endpoint to produce a signed QR image URL. |
| 31 | +5. Posts a markdown table comment to the matching PR via the GitHub API. |
| 32 | +6. De-duplicates per process lifetime using `head_sha` (in-memory). |
| 33 | + |
19 | 34 | --- |
20 | | -apiVersion: v1 |
21 | | -kind: ConfigMap |
22 | | -metadata: |
23 | | - name: glueops-captain-domain |
24 | | -data: |
25 | | - captain_domain: <example: nonprod.tenant.glueopshosted.rocks> |
| 35 | + |
| 36 | +## Inputs expected on the Argo CD Application |
| 37 | + |
| 38 | +### Required annotations |
| 39 | + |
| 40 | +| Annotation | Required | Meaning | |
| 41 | +|---|:---:|---| |
| 42 | +| `preview_environment` | ✅ | Must be `"true"` to be considered | |
| 43 | +| `head_sha` | ✅ | Commit SHA expected to be deployed | |
| 44 | +| `repository_organization` | ✅ | GitHub org/owner | |
| 45 | +| `repository_name` | ✅ | GitHub repo name | |
| 46 | +| `pull_request_number` | ✅ | PR number to comment on | |
| 47 | + |
| 48 | +### Required status fields (set by Argo CD) |
| 49 | + |
| 50 | +- `status.sync.revisions` must contain `head_sha` |
| 51 | +- `status.health.status` must be `Healthy` or `Degraded` |
| 52 | +- `status.summary.externalURLs` must contain at least one URL |
| 53 | + |
| 54 | +--- |
| 55 | + |
| 56 | +## Configuration |
| 57 | + |
| 58 | +Configuration is via environment variables: |
| 59 | + |
| 60 | +| Env var | Default | Required | Description | |
| 61 | +|---|---:|:---:|---| |
| 62 | +| `NAMESPACE` | `glueops-core` | | Namespace used to read ConfigMap/Secret and list Applications | |
| 63 | +| `GITHUB_APP_SECRET_NAME` | `tenant-repo-creds` | | K8s Secret with GitHub App credentials | |
| 64 | +| `CAPTAIN_DOMAIN_K8S_CONFIGMAP_NAME` | `glueops-captain-domain` | | K8s ConfigMap with `captain_domain` | |
| 65 | +| `WATCH_FOR_APPS_DELAY_SECONDS` | `10` | | Poll interval in seconds | |
| 66 | +| `QR_MINT_TOKEN` | | ✅ | Bearer token for QR signing endpoint | |
| 67 | +| `QR_TTL_SECONDS` | `600` | | Signed QR TTL in seconds | |
| 68 | +| `KUBECONFIG` | `~/.kube/config` | | Used only when not running in-cluster | |
| 69 | + |
| 70 | +Hard-coded defaults: |
| 71 | +- HTTP timeout: 15 seconds |
| 72 | +- GitHub API version header: `2022-11-28` |
| 73 | + |
26 | 74 | --- |
27 | | -``` |
28 | 75 |
|
29 | | -## Running the app |
| 76 | +## Kubernetes resources required |
30 | 77 |
|
31 | | -- Ensure you have the following set in your ```.env``` file (at **root** foolder): |
| 78 | +### ConfigMap: captain domain |
32 | 79 |
|
33 | | -```bash |
34 | | -export GITHUB_TOKEN=<some-value> |
35 | | -``` |
| 80 | +A ConfigMap containing the base domain used for service links: |
36 | 81 |
|
37 | | -For cloud specific setup (to be authenticated to the captain cluster), check [here](https://github.com/GlueOps/terraform-module-cloud-aws-kubernetes-cluster/wiki) |
| 82 | +- Name: `CAPTAIN_DOMAIN_K8S_CONFIGMAP_NAME` (default `glueops-captain-domain`) |
| 83 | +- Key: `captain_domain` |
38 | 84 |
|
39 | | -- Then run |
| 85 | +Example: |
40 | 86 |
|
41 | | -```python |
42 | | -python main.py |
43 | | -``` |
| 87 | +```yaml |
| 88 | +apiVersion: v1 |
| 89 | +kind: ConfigMap |
| 90 | +metadata: |
| 91 | + name: glueops-captain-domain |
| 92 | + namespace: glueops-core |
| 93 | +data: |
| 94 | + captain_domain: example.internal |
0 commit comments