Skip to content

Commit 1574ea6

Browse files
committed
Initial commit
0 parents  commit 1574ea6

109 files changed

Lines changed: 21023 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.devcontainer/Dockerfile

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
FROM mcr.microsoft.com/devcontainers/base:ubuntu-24.04
2+
3+
# Install dependencies
4+
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
5+
&& apt-get -y install --no-install-recommends \
6+
curl \
7+
wget \
8+
unzip \
9+
gnupg \
10+
lsb-release \
11+
software-properties-common \
12+
ca-certificates \
13+
apt-transport-https \
14+
python3 \
15+
python3-pip \
16+
pre-commit shellcheck \
17+
&& apt-get clean \
18+
&& rm -rf /var/lib/apt/lists/*
19+
20+
# Install Terraform
21+
RUN wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | tee /usr/share/keyrings/hashicorp-archive-keyring.gpg \
22+
&& echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/hashicorp.list \
23+
&& apt-get update \
24+
&& apt-get install -y terraform \
25+
&& apt-get clean \
26+
&& rm -rf /var/lib/apt/lists/*
27+
28+
# Install Google Cloud CLI
29+
RUN echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list \
30+
&& curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - \
31+
&& apt-get update \
32+
&& apt-get install -y google-cloud-cli \
33+
&& apt-get clean \
34+
&& rm -rf /var/lib/apt/lists/*
35+
RUN curl -sSLo ./terraform-docs.tar.gz https://terraform-docs.io/dl/v0.20.0/terraform-docs-v0.20.0-$(uname)-amd64.tar.gz \
36+
&& tar -xzf terraform-docs.tar.gz \
37+
&& chmod +x terraform-docs \
38+
&& mv terraform-docs /usr/local/bin
39+
40+
# Verify installations
41+
RUN terraform --version && gcloud --version

.devcontainer/README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Terraform & Google Cloud Development Environment
2+
3+
This devcontainer is configured for Terraform and Google Cloud development with Ona compatibility.
4+
5+
## Included Tools
6+
- Terraform (installed via HashiCorp APT repository)
7+
- Google Cloud CLI (installed via Google APT repository)
8+
- HashiCorp Terraform VSCode extension
9+
- Google Cloud Code extension
10+
- Python3 and pip for additional tooling
11+
12+
## Installation Method
13+
Tools are installed directly in the Dockerfile using official APT repositories for maximum compatibility with Gitpod.
14+
15+
## Usage
16+
The environment will automatically install and configure all tools when the container builds.
17+
18+
## Verification
19+
Run `terraform --version && gcloud --version` to verify installation.
20+
21+
## Port Forwarding
22+
- Port 8080: Application
23+
- Port 3000: Development Server

.devcontainer/devcontainer.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "Ona GCP Runner Terraform module",
3+
"build": {
4+
"context": ".",
5+
"dockerfile": "Dockerfile"
6+
},
7+
"customizations": {
8+
"vscode": {
9+
"extensions": [
10+
"ms-vscode.vscode-json",
11+
"hashicorp.terraform",
12+
"googlecloudtools.cloudcode"
13+
]
14+
}
15+
},
16+
"postCreateCommand": "pre-commit install",
17+
"remoteUser": "vscode",
18+
"forwardPorts": [8080, 3000],
19+
"portsAttributes": {
20+
"8080": {
21+
"label": "Application",
22+
"onAutoForward": "notify"
23+
},
24+
"3000": {
25+
"label": "Development Server",
26+
"onAutoForward": "notify"
27+
}
28+
}
29+
}

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* alejandro@gitpod.io nandaja@gitpod.io
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
name: GCP Runner E2E Tests
2+
3+
on:
4+
schedule:
5+
# Run daily at 6 AM UTC
6+
- cron: "0 6 * * *"
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
12+
defaults:
13+
run:
14+
shell: bash
15+
16+
env:
17+
# GCP Configuration - Override with variables if provided
18+
GCP_PROJECT_ID: ${{ vars.E2E_GCP_PROJECT_ID || 'gitpod-gcp-runner-e2e-tests' }}
19+
GCP_REGION: ${{ vars.E2E_GCP_REGION || 'us-central1' }}
20+
GITPOD_API_ENDPOINT: ${{ vars.E2E_GITPOD_API_ENDPOINT || 'https://app.gitpod.io/api' }}
21+
22+
jobs:
23+
e2e-test:
24+
name: Run E2E Test
25+
runs-on: ubuntu-latest
26+
timeout-minutes: 60
27+
28+
steps:
29+
- name: Checkout Repository
30+
uses: actions/checkout@v4
31+
with:
32+
fetch-depth: 0
33+
34+
- name: Set up Cloud SDK
35+
uses: google-github-actions/setup-gcloud@v2
36+
with:
37+
version: 'latest'
38+
39+
- name: Set up Terraform
40+
uses: hashicorp/setup-terraform@v3
41+
with:
42+
terraform_version: "latest"
43+
44+
- name: Configure environment and authentication
45+
run: |
46+
# Set sensitive environment variables for e2e script
47+
echo "GITPOD_TOKEN=${{ secrets.E2E_GITPOD_TOKEN }}" >> $GITHUB_ENV
48+
49+
# Set up service account authentication directly (like dev container)
50+
echo '${{ secrets.E2E_GOOGLE_APPLICATION_CREDENTIALS }}' > /tmp/gcp-sa-key.json
51+
chmod 600 /tmp/gcp-sa-key.json
52+
echo "GOOGLE_APPLICATION_CREDENTIALS=/tmp/gcp-sa-key.json" >> $GITHUB_ENV
53+
54+
- name: Run E2E Test
55+
run: |
56+
echo "Starting GCP Runner E2E test..."
57+
echo "Project: $GCP_PROJECT_ID | Region: $GCP_REGION"
58+
59+
# Run the E2E test script
60+
chmod +x tests/e2e/scripts/e2e-test.sh
61+
./tests/e2e/scripts/e2e-test.sh
62+
63+
- name: Cleanup service account file
64+
if: always()
65+
run: |
66+
# Clean up temporary service account key file
67+
if [[ -f "/tmp/gcp-sa-key.json" ]]; then
68+
rm -f /tmp/gcp-sa-key.json
69+
fi
70+
71+
- name: Slack Notification on Failure
72+
if: failure() && github.ref == 'refs/heads/main'
73+
uses: rtCamp/action-slack-notify@v2.3.3
74+
env:
75+
SLACK_WEBHOOK: ${{ secrets.NEXT_ALERTS_SLACK_WEBHOOK }}
76+
SLACK_ICON_EMOJI: ":gcp:"
77+
SLACK_USERNAME: "GCP Runner E2E Tests"
78+
SLACK_COLOR: "danger"
79+
SLACK_MESSAGE: |
80+
:warning: GCP Runner end-to-end tests have failed
81+
82+
**Details:**
83+
• Project: ${{ env.GCP_PROJECT_ID }}
84+
• Region: ${{ env.GCP_REGION }}
85+
• Workflow: ${{ github.workflow }}
86+
• Commit: ${{ github.sha }}
87+
88+
The test creates a runner via RunnerService API, deploys infrastructure with Terraform, and verifies the runner comes online.
89+
SLACK_FOOTER: "<https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|View workflow logs>"

.github/workflows/release.yml

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- '*'
7+
workflow_dispatch:
8+
inputs:
9+
tag:
10+
description: 'Tag to create release for'
11+
required: true
12+
type: string
13+
14+
permissions:
15+
contents: write
16+
id-token: write
17+
18+
jobs:
19+
release:
20+
name: Create Release
21+
runs-on: ubuntu-latest
22+
23+
env:
24+
RELEASE_TAG: ${{ inputs.tag || github.ref_name }}
25+
26+
steps:
27+
- name: Checkout code
28+
uses: actions/checkout@v4
29+
with:
30+
fetch-depth: 0
31+
ref: ${{ inputs.tag || github.ref }}
32+
33+
- name: Verify tag is on main branch
34+
run: |
35+
if ! git branch -r --contains "${RELEASE_TAG}" | grep -q 'origin/main'; then
36+
echo "::error::Tag ${RELEASE_TAG} is not on main branch. Releases can only be created from tags on main."
37+
exit 1
38+
fi
39+
40+
- name: Get previous tag
41+
id: prev_tag
42+
run: |
43+
PREV_TAG=$(git tag --sort=-creatordate | grep -v "^${RELEASE_TAG}$" | head -1)
44+
echo "tag=${PREV_TAG}" >> $GITHUB_OUTPUT
45+
echo "Previous tag: ${PREV_TAG}"
46+
47+
- name: Fetch manifest.json
48+
id: manifest
49+
run: |
50+
MANIFEST=$(curl -sf https://storage.googleapis.com/gitpod-runner-releases/gcp/stable/manifest.json)
51+
echo "version=$(echo "$MANIFEST" | jq -r '.version')" >> $GITHUB_OUTPUT
52+
echo "runner_image=$(echo "$MANIFEST" | jq -r '.runner_image')" >> $GITHUB_OUTPUT
53+
echo "proxy_image=$(echo "$MANIFEST" | jq -r '.proxy_image')" >> $GITHUB_OUTPUT
54+
echo "prometheus_image=$(echo "$MANIFEST" | jq -r '.prometheus_image')" >> $GITHUB_OUTPUT
55+
echo "node_exporter_image=$(echo "$MANIFEST" | jq -r '.node_exporter_image')" >> $GITHUB_OUTPUT
56+
echo "cli_url=$(echo "$MANIFEST" | jq -r '.cli_url')" >> $GITHUB_OUTPUT
57+
echo "supervisor_url=$(echo "$MANIFEST" | jq -r '.supervisor_url')" >> $GITHUB_OUTPUT
58+
echo "vm_image=$(echo "$MANIFEST" | jq -r '.vm_image')" >> $GITHUB_OUTPUT
59+
60+
- name: Generate changelog
61+
id: changelog
62+
run: |
63+
if [ -n "${{ steps.prev_tag.outputs.tag }}" ]; then
64+
# Get commits between tags, excluding automated image update commits
65+
CHANGELOG=$(git log --pretty=format:"- %s (%h)" \
66+
"${{ steps.prev_tag.outputs.tag }}..${RELEASE_TAG}" \
67+
--grep="Update GCP runner, proxy, prometheus, and node-exporter images" --invert-grep)
68+
else
69+
# First release - get all commits excluding automated ones
70+
CHANGELOG=$(git log --pretty=format:"- %s (%h)" \
71+
--grep="Update GCP runner, proxy, prometheus, and node-exporter images" --invert-grep)
72+
fi
73+
74+
# Handle empty changelog
75+
if [ -z "$CHANGELOG" ]; then
76+
CHANGELOG="- No user-facing changes in this release"
77+
fi
78+
79+
# Write to file to preserve newlines
80+
echo "$CHANGELOG" > changelog.txt
81+
82+
- name: Detect IAM/permission changes
83+
id: iam_changes
84+
run: |
85+
IAM_FILES="iam.tf docs/iam.md docs/detailed_iam_reference.md docs/terraform_service_account_permissions.md"
86+
87+
if [ -n "${{ steps.prev_tag.outputs.tag }}" ]; then
88+
# Check if any IAM-related files changed between tags
89+
CHANGED_FILES=$(git diff --name-only "${{ steps.prev_tag.outputs.tag }}..${RELEASE_TAG}" -- $IAM_FILES 2>/dev/null || true)
90+
91+
if [ -n "$CHANGED_FILES" ]; then
92+
echo "has_changes=true" >> $GITHUB_OUTPUT
93+
94+
# Get commits that touched IAM files
95+
IAM_COMMITS=$(git log --pretty=format:"- %s (%h)" \
96+
"${{ steps.prev_tag.outputs.tag }}..${RELEASE_TAG}" \
97+
--grep="Update GCP runner, proxy, prometheus, and node-exporter images" --invert-grep \
98+
-- $IAM_FILES)
99+
100+
echo "$IAM_COMMITS" > iam_changelog.txt
101+
echo "Changed files: $CHANGED_FILES"
102+
else
103+
echo "has_changes=false" >> $GITHUB_OUTPUT
104+
fi
105+
else
106+
echo "has_changes=false" >> $GITHUB_OUTPUT
107+
fi
108+
109+
- name: Create release tarball
110+
run: |
111+
# Create tarball in /tmp to avoid "file changed as we read it" error
112+
tar --exclude='.git' \
113+
--exclude='.github' \
114+
--exclude='.devcontainer' \
115+
--exclude='.cursor' \
116+
--exclude='tests' \
117+
--exclude='.pre-commit-config.yaml' \
118+
--exclude='changelog.txt' \
119+
--exclude='iam_changelog.txt' \
120+
--exclude='release_body.md' \
121+
-czvf /tmp/terraform-google-ona-runner-${RELEASE_TAG}.tar.gz .
122+
mv /tmp/terraform-google-ona-runner-${RELEASE_TAG}.tar.gz .
123+
124+
- name: Build release body
125+
id: body
126+
run: |
127+
cat << 'EOF' > release_body.md
128+
## Container Images
129+
130+
| Component | Image |
131+
|-----------|-------|
132+
| Runner | `${{ steps.manifest.outputs.runner_image }}` |
133+
| Proxy | `${{ steps.manifest.outputs.proxy_image }}` |
134+
| Prometheus | `${{ steps.manifest.outputs.prometheus_image }}` |
135+
| Node Exporter | `${{ steps.manifest.outputs.node_exporter_image }}` |
136+
137+
## Assets
138+
139+
| Asset | URL |
140+
|-------|-----|
141+
| CLI Binary | `${{ steps.manifest.outputs.cli_url }}` |
142+
| Supervisor Binary | `${{ steps.manifest.outputs.supervisor_url }}` |
143+
| VM Image | `${{ steps.manifest.outputs.vm_image }}` |
144+
145+
EOF
146+
147+
# Add IAM changes section if there are any
148+
if [ "${{ steps.iam_changes.outputs.has_changes }}" = "true" ]; then
149+
cat << 'EOF' >> release_body.md
150+
## ⚠️ IAM/Permission Changes
151+
152+
This release includes changes to IAM roles or permissions. Review the following commits and update your IAM configuration if needed:
153+
154+
EOF
155+
cat iam_changelog.txt >> release_body.md
156+
echo "" >> release_body.md
157+
echo "See [docs/iam.md](docs/iam.md) and [docs/terraform_service_account_permissions.md](docs/terraform_service_account_permissions.md) for the updated permission requirements." >> release_body.md
158+
echo "" >> release_body.md
159+
fi
160+
161+
cat << 'EOF' >> release_body.md
162+
## Changelog
163+
164+
EOF
165+
cat changelog.txt >> release_body.md
166+
167+
- name: Create Release
168+
uses: softprops/action-gh-release@v2
169+
with:
170+
tag_name: ${{ env.RELEASE_TAG }}
171+
name: ${{ env.RELEASE_TAG }}
172+
body_path: release_body.md
173+
files: |
174+
terraform-google-ona-runner-${{ env.RELEASE_TAG }}.tar.gz
175+
fail_on_unmatched_files: true
176+
env:
177+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
178+
179+
- name: Authenticate to GCP
180+
uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # pin@v3
181+
with:
182+
workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_POOL }}
183+
service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }}
184+
185+
- name: Publish release notification
186+
run: |
187+
MANIFEST=$(curl -sf https://storage.googleapis.com/gitpod-runner-releases/gcp/stable/manifest.json)
188+
189+
# Build enriched payload with terraform module changes
190+
PAYLOAD=$(echo "$MANIFEST" | jq \
191+
--arg iam_changes "${{ steps.iam_changes.outputs.has_changes }}" \
192+
--rawfile changelog changelog.txt \
193+
'. + {
194+
terraform_changes: ($changelog | split("\n") | map(select(. != ""))),
195+
iam_changes_detected: ($iam_changes == "true")
196+
}')
197+
198+
gcloud pubsub topics publish gcp-runner-releases \
199+
--project=gitpod-next-production \
200+
--message="$PAYLOAD" \
201+
--attribute="event_type=release.stable,version=${RELEASE_TAG},source=ci_stable_promotion"

0 commit comments

Comments
 (0)