Skip to content

Commit c36cb69

Browse files
banjohscottrigby
andauthored
Containerise dependencies required to run tasks in dev workflow (#53)
* feat: Dockerfile containing all dependencies for tasks Signed-off-by: Evans Mungai <evans@replicated.com> * download helmfile Signed-off-by: Evans Mungai <evans@replicated.com> * feat: Dockerfile containing all dependencies for tasks Signed-off-by: Evans Mungai <evans@replicated.com> * download helmfile Signed-off-by: Evans Mungai <evans@replicated.com> * Add initial docker env taskfile Signed-off-by: Evans Mungai <evans@replicated.com> * Move docker tasks into wg-easy application Signed-off-by: Evans Mungai <evans@replicated.com> * Update dev documentation Signed-off-by: Evans Mungai <evans@replicated.com> * Copy replicated auth token to container Signed-off-by: Evans Mungai <evans@replicated.com> * Update dev documentation Signed-off-by: Evans Mungai <evans@replicated.com> * Fix grammer Signed-off-by: Evans Mungai <evans@replicated.com> * Add SHELL env required by replicated shell subcommand Signed-off-by: Evans Mungai <evans@replicated.com> * Default to Podman, allow Docker optionally (#54) Signed-off-by: Scott Rigby <scott@r6by.com> * Prepend DEV to dev container variables Signed-off-by: Evans Mungai <evans@replicated.com> * Changes as per review comments Signed-off-by: Evans Mungai <evans@replicated.com> * Add shell completions and some colour to terminal Signed-off-by: Evans Mungai <evans@replicated.com> * Remove duplicate completion Signed-off-by: Evans Mungai <evans@replicated.com> * Update applications/wg-easy/container/Containerfile Co-authored-by: Scott Rigby <scott@r6by.com> * Update applications/wg-easy/docs/development-workflow.md Co-authored-by: Scott Rigby <scott@r6by.com> * Remove unnecessary shell-implementation task Signed-off-by: Evans Mungai <evans@replicated.com> * Improvements in Containerfile Signed-off-by: Evans Mungai <evans@replicated.com> * Remove unnecessary comment Signed-off-by: Evans Mungai <evans@replicated.com> * Build and publish wg-easy tools image to ghcr Signed-off-by: Evans Mungai <evans@replicated.com> * Update paths to check in workflow file Signed-off-by: Evans Mungai <evans@replicated.com> * Fix repo name Signed-off-by: Evans Mungai <evans@replicated.com> * Push in PR Signed-off-by: Evans Mungai <evans@replicated.com> * Publish multiarch images Signed-off-by: Evans Mungai <evans@replicated.com> * Download architecture specific binaries Signed-off-by: Evans Mungai <evans@replicated.com> * Only push when in main branch Signed-off-by: Evans Mungai <evans@replicated.com> * Check if image exists locally before pulling or building When starting the development container, check if the image exists locally before pulling or building it. Signed-off-by: Evans Mungai <evans@replicated.com> * Remove step to build image in docs dev:shell automatically builds the image if it doesn't exist locally Signed-off-by: Evans Mungai <evans@replicated.com> --------- Signed-off-by: Evans Mungai <evans@replicated.com> Signed-off-by: Scott Rigby <scott@r6by.com> Co-authored-by: Scott Rigby <scott@r6by.com>
1 parent 64af10b commit c36cb69

File tree

7 files changed

+302
-25
lines changed

7 files changed

+302
-25
lines changed

.github/workflows/wg-easy-image.yml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: WG-Easy Image CI
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
paths:
7+
- 'applications/wg-easy/**'
8+
- '.github/workflows/wg-easy-image.yml'
9+
pull_request:
10+
paths:
11+
- 'applications/wg-easy/**'
12+
- '.github/workflows/wg-easy-image.yml'
13+
workflow_dispatch:
14+
15+
env:
16+
DEV_CONTAINER_REGISTRY: ghcr.io
17+
DEV_CONTAINER_IMAGE: replicatedhq/platform-examples/wg-easy-tools
18+
19+
jobs:
20+
build-and-push:
21+
runs-on: ubuntu-latest
22+
permissions:
23+
contents: read
24+
packages: write
25+
26+
steps:
27+
- name: Checkout repository
28+
uses: actions/checkout@v4
29+
30+
- name: Set up QEMU
31+
uses: docker/setup-qemu-action@v3
32+
33+
- name: Set up Docker Buildx
34+
uses: docker/setup-buildx-action@v3
35+
36+
- name: Log in to GHCR
37+
uses: docker/login-action@v3
38+
with:
39+
registry: ${{ env.DEV_CONTAINER_REGISTRY }}
40+
username: ${{ github.actor }}
41+
password: ${{ secrets.GITHUB_TOKEN }}
42+
43+
- name: Extract metadata
44+
id: meta
45+
uses: docker/metadata-action@v5
46+
with:
47+
images: ${{ env.DEV_CONTAINER_REGISTRY }}/${{ env.DEV_CONTAINER_IMAGE }}
48+
tags: |
49+
type=raw,value=latest,enable={{is_default_branch}}
50+
type=sha,format=short
51+
type=ref,event=branch
52+
type=ref,event=pr
53+
54+
- name: Build and push image
55+
uses: docker/build-push-action@v6
56+
with:
57+
context: applications/wg-easy
58+
file: applications/wg-easy/container/Containerfile
59+
platforms: linux/amd64,linux/arm64
60+
push: ${{ github.event_name != 'pull_request' }}
61+
tags: ${{ steps.meta.outputs.tags }}
62+
labels: ${{ steps.meta.outputs.labels }}
63+
cache-from: type=gha
64+
cache-to: type=gha,mode=max

applications/wg-easy/Taskfile.yaml

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,39 @@ version: "3"
22

33
includes:
44
utils: ./taskfiles/utils.yml
5+
dev: ./taskfiles/container.yml
56

67
vars:
78
# Application configuration
89
APP_NAME: '{{.REPLICATED_APP | default "wg-easy"}}'
9-
10+
1011
# Cluster configuration
1112
CLUSTER_NAME: '{{.CLUSTER_NAME | default "test-cluster"}}'
1213
K8S_VERSION: '{{.K8S_VERSION | default "1.32.2"}}'
1314
DISK_SIZE: '{{.DISK_SIZE | default "100"}}'
1415
INSTANCE_TYPE: '{{.INSTANCE_TYPE | default "r1.small"}}'
1516
DISTRIBUTION: '{{.DISTRIBUTION | default "k3s"}}'
1617
KUBECONFIG_FILE: './{{.CLUSTER_NAME}}.kubeconfig'
17-
18+
1819
# Ports configuration
1920
EXPOSE_PORTS:
2021
- port: 30443
2122
protocol: https
2223
- port: 30080
2324
protocol: http
24-
25+
2526
# GCP default configuration
2627
GCP_PROJECT: '{{.GCP_PROJECT | default "replicated-qa"}}'
2728
GCP_ZONE: '{{.GCP_ZONE | default "us-central1-a"}}'
2829
VM_NAME: '{{.VM_NAME | default (printf "%s-dev" (or (env "GUSER") "user"))}}'
2930

31+
# Container workflow configuration
32+
DEV_CONTAINER_REGISTRY: '{{.DEV_CONTAINER_REGISTRY | default "ghcr.io"}}'
33+
DEV_CONTAINER_IMAGE: '{{.DEV_CONTAINER_IMAGE | default "replicatedhq/platform-examples/wg-easy-tools"}}'
34+
DEV_CONTAINER_TAG: '{{.DEV_CONTAINER_TAG | default "latest"}}'
35+
DEV_CONTAINER_NAME: '{{.DEV_CONTAINER_NAME | default "wg-easy-tools"}}'
36+
CONTAINER_RUNTIME: '{{.CONTAINER_RUNTIME | default "podman"}}'
37+
3038
tasks:
3139
default:
3240
desc: Show available tasks
@@ -91,7 +99,7 @@ tasks:
9199
echo "Removing old kubeconfig file"
92100
rm -f {{.KUBECONFIG_FILE}}
93101
fi
94-
fi
102+
fi
95103
96104
setup-kubeconfig:
97105
desc: Get kubeconfig and prepare cluster for application deployment
@@ -112,7 +120,7 @@ tasks:
112120
true
113121
fi
114122
deps:
115-
- create-cluster
123+
- cluster-create
116124
- verify-kubeconfig
117125

118126
dependencies-update:
@@ -138,7 +146,7 @@ tasks:
138146
if [ -z "$CLUSTER_ID" ]; then
139147
exit 1
140148
fi
141-
149+
142150
# Check if all ports are already exposed
143151
expected_count={{len .EXPOSE_PORTS}}
144152
port_checks=""
@@ -147,7 +155,7 @@ tasks:
147155
{{end}}
148156
# Remove trailing "or "
149157
port_checks="${port_checks% or }"
150-
158+
151159
PORT_COUNT=$(replicated cluster port ls $CLUSTER_ID --output json | jq -r ".[] | select($port_checks) | .upstream_port" | wc -l | tr -d ' ')
152160
[ "$PORT_COUNT" -eq "$expected_count" ]
153161
cmds:
@@ -169,10 +177,10 @@ tasks:
169177
echo "Error: Could not find cluster with name {{.CLUSTER_NAME}}"
170178
exit 1
171179
fi
172-
180+
173181
# Get exposed URLs
174182
ENV_VARS=$(task utils:port-operations OPERATION=getenv CLUSTER_NAME={{.CLUSTER_NAME}})
175-
183+
176184
# Deploy with helmfile
177185
echo "Using $ENV_VARS"
178186
eval "KUBECONFIG={{.KUBECONFIG_FILE}} $ENV_VARS helmfile sync --wait"
@@ -193,7 +201,7 @@ tasks:
193201
echo "No clusters found with name {{.CLUSTER_NAME}}"
194202
exit 0
195203
fi
196-
204+
197205
for id in $CLUSTER_IDS; do
198206
echo "Deleting cluster ID: $id"
199207
replicated cluster rm "$id"
@@ -213,7 +221,7 @@ tasks:
213221
- echo "Preparing release files..."
214222
- rm -rf ./release
215223
- mkdir -p ./release
216-
224+
217225
# Copy all non-config.yaml files
218226
- echo "Copying non-config YAML files to release folder..."
219227
- find . -path '*/replicated/*.yaml' -not -name 'config.yaml' -exec cp {} ./release/ \;
@@ -237,27 +245,27 @@ tasks:
237245
yq '.spec.chart.chartVersion = strenv(version) | .spec.chart.chartVersion style="single"' $directory/$helmChartName | tee release/$helmChartName
238246
239247
done < <(find . -maxdepth 2 -mindepth 2 -type d -name replicated)
240-
248+
241249
# Merge config.yaml files
242250
- echo "Merging config.yaml files..."
243251
- |
244252
# Start with an empty config file
245253
echo "{}" > ./release/config.yaml
246-
254+
247255
# Merge all app config.yaml files first (excluding root replicated)
248256
for config_file in $(find . -path '*/replicated/config.yaml' | grep -v "^./replicated/"); do
249257
echo "Merging $config_file..."
250258
yq eval-all '. as $item ireduce ({}; . * $item)' ./release/config.yaml "$config_file" > ./release/config.yaml.new
251259
mv ./release/config.yaml.new ./release/config.yaml
252260
done
253-
261+
254262
# Merge root config.yaml last
255263
if [ -f "./replicated/config.yaml" ]; then
256264
echo "Merging root config.yaml last..."
257265
yq eval-all '. as $item ireduce ({}; . * $item)' ./release/config.yaml "./replicated/config.yaml" > ./release/config.yaml.new
258266
mv ./release/config.yaml.new ./release/config.yaml
259267
fi
260-
268+
261269
# Package Helm charts
262270
- echo "Packaging Helm charts..."
263271
- |
@@ -267,7 +275,7 @@ tasks:
267275
# Navigate to chart directory, package it, and move the resulting .tgz to release folder
268276
(cd "$chart_dir" && helm package . && mv *.tgz ../release/)
269277
done
270-
278+
271279
- echo "Release files prepared in ./release/ directory"
272280
deps:
273281
- update-version
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Base image for all shared Containerfiles for taskfiles
2+
# Use this image as base image for app specific container files
3+
FROM --platform=$BUILDPLATFORM ubuntu:24.04
4+
5+
ARG TARGETOS
6+
ARG TARGETARCH
7+
8+
WORKDIR /tools
9+
10+
# Set environment variables
11+
ENV DEBIAN_FRONTEND=noninteractive \
12+
HOME=/home/devuser \
13+
SHELL=/bin/bash
14+
15+
# Install debian packages
16+
RUN apt-get update && apt-get install -y \
17+
curl \
18+
jq \
19+
less \
20+
yq \
21+
gnupg \
22+
bash-completion \
23+
24+
# Install Google Cloud CLI
25+
&& 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 \
26+
&& curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg \
27+
&& apt-get update \
28+
&& apt-get install google-cloud-cli -y \
29+
30+
# Clean up
31+
&& apt-get purge -y gnupg \
32+
&& rm -rf /var/lib/apt/lists/*
33+
34+
# Install helm
35+
RUN curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash \
36+
37+
# Install kubectl
38+
&& curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/${TARGETARCH}/kubectl" \
39+
&& chmod +x kubectl \
40+
&& mv kubectl /usr/local/bin/ \
41+
42+
# Install Task
43+
&& sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin \
44+
45+
# Install Helmfile
46+
&& curl -Ls $(curl -s https://api.github.com/repos/helmfile/helmfile/releases/latest \
47+
| grep "browser_download_url.*linux_${TARGETARCH}.tar.gz" \
48+
| cut -d : -f 2,3 \
49+
| tr -d \") -o helmfile.tar.gz \
50+
&& tar xf helmfile.tar.gz helmfile && rm helmfile.tar.gz \
51+
&& mv helmfile /usr/local/bin/helmfile \
52+
53+
# Install Replicated CLI
54+
&& curl -Ls $(curl -s https://api.github.com/repos/replicatedhq/replicated/releases/latest \
55+
| grep "browser_download_url.*linux_amd64.tar.gz" \
56+
| cut -d : -f 2,3 \
57+
| tr -d \") -o replicated.tar.gz \
58+
&& tar xf replicated.tar.gz replicated && rm replicated.tar.gz \
59+
&& mv replicated /usr/local/bin/replicated
60+
61+
# Create a non-root user for better security
62+
RUN groupadd -r devuser && useradd -r -g devuser -m -s /bin/bash devuser
63+
64+
# Copy shell completion scripts
65+
COPY container/tool-completions.sh tool-completions.sh
66+
67+
# Copy entrypoint script
68+
COPY container/entrypoint.sh entrypoint.sh
69+
RUN chmod +x entrypoint.sh
70+
71+
# Set working directory
72+
WORKDIR /workspace
73+
74+
# Switch to non-root user
75+
USER devuser
76+
77+
# Set entrypoint
78+
ENTRYPOINT ["/tools/entrypoint.sh", "-l"]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/bash
2+
3+
# Uncomment force_color_prompt in bashrc
4+
sed -i 's/#force_color_prompt=yes/force_color_prompt=yes/' $HOME/.bashrc
5+
6+
# Source the tool completions
7+
echo "source /tools/tool-completions.sh" >> $HOME/.bashrc
8+
9+
# Execute the passed command or default to bash
10+
exec "$@"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/bin/bash
2+
3+
# kubectl completion
4+
source <(kubectl completion bash)
5+
alias k=kubectl
6+
complete -o default -F __start_kubectl k
7+
8+
# helm completion
9+
source <(helm completion bash)
10+
11+
# task completion
12+
source <(task --completion bash)
13+
14+
# helmfile completion
15+
source <(helmfile completion bash)
16+
17+
# replicated completion
18+
source <(replicated completion bash)
19+
20+
# gcloud completion
21+
source /usr/share/google-cloud-sdk/completion.bash.inc

applications/wg-easy/docs/development-workflow.md

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,9 @@ The core philosophy of this workflow is to start simple and add complexity incre
1818
Before starting the development workflow, ensure you have the following tools installed:
1919

2020
- **Task:** The task runner used in this project. ([Installation Guide](https://taskfile.dev/installation/))
21-
- **Replicated CLI:** For managing test clusters and application releases. ([Installation Guide](https://docs.replicated.com/reference/replicated-cli-installing))
22-
- **Helm:** The Kubernetes package manager. ([Installation Guide](https://helm.sh/docs/intro/install/))
23-
- **Helmfile:** For orchestrating Helm chart deployments. ([Installation Guide](https://github.com/helmfile/helmfile#installation))
24-
- **kubectl:** The Kubernetes command-line tool. ([Installation Guide](https://kubernetes.io/docs/tasks/tools/install-kubectl/))
25-
- **jq:** A command-line JSON processor. ([Download Page](https://stedolan.github.io/jq/download/))
26-
- **yq:** A command-line YAML processor. ([Installation Guide](https://github.com/mikefarah/yq#install))
27-
- **gcloud CLI:** Google Cloud command-line interface (optional, only required for GCP-specific tasks). ([Installation Guide](https://cloud.google.com/sdk/docs/install))
28-
- **Standard Unix Utilities:** `find`, `xargs`, `grep`, `awk`, `wc`, `tr`, `cp`, `mv`, `rm`, `mkdir`, `echo`, `sleep`, `test`, `eval` (typically available by default on Linux and macOS).
21+
- **Container runtime tool** Either [Podman](https://podman.io/docs/installation) (default) or [Docker](https://docs.docker.com/get-docker/) for local development
22+
23+
All other tools will be automatically provided through task commands and containers.
2924

3025
## Workflow Stages
3126

@@ -97,6 +92,17 @@ Configure chart values and create or modify templates.
9792
9893
### Stage 3: Local Validation with helm template
9994
95+
> [!IMPORTANT]
96+
> Tools required by tasks in this project will be made available in a container. Run the commands below to start the dev environment
97+
98+
```
99+
# Open shell to execute tasks
100+
task dev:shell
101+
102+
# Start/restart tools container. Idempotent.
103+
task dev:restart
104+
```
105+
100106
Validate chart templates locally without deploying to a cluster.
101107

102108
1. Run helm template to render the chart and inspect manifests:
@@ -177,7 +183,7 @@ Test multiple charts working together using Helmfile orchestration.
177183
# Check if issuers are correctly using cert-manager
178184
kubectl get clusterissuers
179185
kubectl get issuers -A
180-
186+
181187
# Verify Traefik routes
182188
kubectl get ingressroutes -A
183189
```

0 commit comments

Comments
 (0)