Skip to content

Commit 1a66dea

Browse files
add blog on how to use starlark in Woodpecker CI
Signed-off-by: prashant-gurung899 <prasantgrg777@gmail.com>
1 parent 0c1007c commit 1a66dea

File tree

9 files changed

+254
-0
lines changed

9 files changed

+254
-0
lines changed
67 KB
Loading
49.3 KB
Loading
48.6 KB
Loading
42.6 KB
Loading
37.9 KB
Loading
19 KB
Loading
152 KB
Loading
124 KB
Loading
Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
---
2+
title: Starlark-Powered Pipelines in Woodpecker CI
3+
authorName: Prashant Gurung
4+
authorAvatar: https://avatars.githubusercontent.com/u/53248463?v=4
5+
authorLink: https://github.com/prashant-gurung899
6+
createdAt: July 3, 2025
7+
tags: CI/CD
8+
banner: https://raw.githubusercontent.com/JankariTech/blog/woodpecker-ci-starlark/src/assets/woodpeckerCI/images/cover.png
9+
---
10+
11+
## Background
12+
Continuous Integration (CI) tools are vital for automating the testing and deployment of modern software. One such open-source tool is Woodpecker CI, a lightweight CI/CD system. Woodpecker CI is an open-source continuous integration and delivery platform that helps developers automate building, testing, and deploying their code. It is a community-driven fork and successor of the popular Drone CI project, sharing many design principles and compatibility with Drone pipelines. Traditionally, Woodpecker pipelines are written in YAML. But with the rise of programmable pipelines, we now have the flexibility to define our CI configuration using Starlark — a Python-like configuration language.
13+
14+
In this blog, I’ll walk you through setting up Woodpecker CI with Traefik as a reverse proxy and integrating it with WCCS (Woodpecker CI Config Service) to convert Starlark configurations into YAML files, enabling us to write pipelines in .woodpecker.star files. Here's a high-level view of what we'll cover:
15+
16+
- Spinning up a Woodpecker server with Traefik
17+
18+
- Authenticating with GitHub
19+
20+
- Enabling a repository
21+
22+
- Connecting WCCS with the Woodpecker server
23+
24+
By the end, you’ll be able to write CI pipelines in Starlark and dynamically convert them to YAML during runtime.
25+
26+
## Prepare Woodpecker secrets via .env
27+
```console
28+
#Your woodpecker host
29+
WOODPECKER_HOST=https://<your-ci-server>
30+
31+
32+
# GitHub OAuth Secrets
33+
WOODPECKER_GITHUB_CLIENT=XXXXXXXXXXXXXXXX
34+
WOODPECKER_GITHUB_SECRET=XXXXXXXXXXXXXXXXXXXXXXXX
35+
36+
37+
# Shared secret used by server<->agent - you can generate it using openSSL
38+
WOODPECKER_AGENT_SECRET=<generated-secret>
39+
40+
41+
# Let’s Encrypt contact email (Traefik will use this)
42+
ACME_EMAIL=admin@example.com
43+
```
44+
45+
## Traefik Configuration
46+
Traefik plays a crucial role in this architecture by handling all the networking complexities - SSL termination, routing, and load balancing
47+
48+
```yml
49+
version: "3.9"
50+
51+
services:
52+
traefik:
53+
image: traefik:v3.1
54+
container_name: traefik
55+
command:
56+
- "--log.level=DEBUG"
57+
- "--providers.docker=true"
58+
- "--providers.docker.exposedbydefault=false"
59+
- "--entrypoints.web.address=:80"
60+
- "--entrypoints.websecure.address=:443"
61+
- "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
62+
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
63+
- "--certificatesresolvers.letsencrypt.acme.email=${ACME_EMAIL}"
64+
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
65+
ports:
66+
- "80:80"
67+
- "443:443"
68+
volumes:
69+
- "./letsencrypt:/letsencrypt"
70+
- "/var/run/docker.sock:/var/run/docker.sock:ro"
71+
networks:
72+
- woodpecker-net
73+
```
74+
75+
This configuration:
76+
77+
- Sets up Traefik to listen on ports 80 and 443
78+
- Configures Let's Encrypt for automatic SSL certificate management
79+
- Enables Docker provider to automatically detect new services
80+
- Mounts necessary volumes for certificate storage and Docker socket access
81+
82+
## Setting Up Woodpecker Server and Agent
83+
Now that we have Traefik running, let's set up the Woodpecker server and agent services. Here's the essential setup:
84+
85+
```yml
86+
woodpecker-server:
87+
image: woodpeckerci/woodpecker-server:v3
88+
environment:
89+
- WOODPECKER_LOG_LEVEL=debug
90+
- WOODPECKER_OPEN=false
91+
- WOODPECKER_HOST=${WOODPECKER_HOST}
92+
- WOODPECKER_GITHUB=true
93+
- WOODPECKER_GITHUB_CLIENT=${WOODPECKER_GITHUB_CLIENT}
94+
- WOODPECKER_GITHUB_SECRET=${WOODPECKER_GITHUB_SECRET}
95+
- WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}
96+
- WOODPECKER_ADMIN=prashant-gurung899
97+
# The following variable is where we set our Woodpecker CI Config Service (Starlark Conversion Service) later
98+
- WOODPECKER_CONFIG_SERVICE_ENDPOINT=http://<your-config-service-server>
99+
volumes:
100+
- woodpecker-server-data:/var/lib/woodpecker/
101+
labels:
102+
- "traefik.enable=true"
103+
- "traefik.http.routers.woodpecker-secure.rule=Host(`your-ci-server`)"
104+
- "traefik.http.routers.woodpecker-secure.entrypoints=websecure"
105+
- "traefik.http.routers.woodpecker-secure.tls.certresolver=letsencrypt"
106+
- "traefik.http.routers.woodpecker-secure.tls=true"
107+
- "traefik.http.services.woodpecker-secure.loadbalancer.server.port=8000"
108+
# HTTP router + redirect to HTTPS
109+
- "traefik.http.routers.woodpecker-http.rule=Host(`your-ci-server`)"
110+
- "traefik.http.routers.woodpecker-http.entrypoints=web"
111+
- "traefik.http.routers.woodpecker-http.middlewares=redirect-to-https"
112+
# Redirect middleware
113+
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
114+
networks:
115+
- woodpecker-net
116+
117+
woodpecker-agent:
118+
image: woodpeckerci/woodpecker-agent:v3
119+
command: agent
120+
restart: always
121+
depends_on:
122+
- woodpecker-server
123+
volumes:
124+
- woodpecker-agent-config:/etc/woodpecker
125+
- /var/run/docker.sock:/var/run/docker.sock
126+
environment:
127+
- WOODPECKER_LOG_LEVEL=debug
128+
- WOODPECKER_SERVER=woodpecker-server:9000
129+
- WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}
130+
networks:
131+
- woodpecker-net
132+
```
133+
134+
## Authenticating with GitHub
135+
136+
To connect GitHub with Woodpecker:
137+
138+
1. Register a new OAuth application in your GitHub developer settings.
139+
140+
2. Set the callback URL to `https://<your-ci-server>/authorize`
141+
142+
3. Copy the generated Client ID and Secret.
143+
144+
4. Use these values in the `WOODPECKER_GITHUB_CLIENT` and `WOODPECKER_GITHUB_SECRET` env vars.
145+
146+
After that, you can log into the Woodpecker web UI using your GitHub account.
147+
148+
![GitHub Login](https://raw.githubusercontent.com/JankariTech/blog/woodpecker-ci-starlark/src/assets/woodpeckerCI/images/github.png)
149+
150+
## Enabling a Repository
151+
From the Woodpecker UI:
152+
153+
- Click on Add Repository.
154+
155+
![Add Repo](https://raw.githubusercontent.com/JankariTech/blog/woodpecker-ci-starlark/src/assets/woodpeckerCI/images/add.png)
156+
157+
- Enable it.
158+
159+
![Enable Repo](https://raw.githubusercontent.com/JankariTech/blog/woodpecker-ci-starlark/src/assets/woodpeckerCI/images/enable.png)
160+
161+
Woodpecker will automatically add the necessary webhooks to the repo.
162+
163+
164+
After enabling your desired repository, there's one more thing that you need to do i.e. to set pipeline config path.
165+
166+
- From the settings of your Woodpecker Server, go to repositories and click on the enabled repo's settings icon as shown below:
167+
168+
![Settings](https://raw.githubusercontent.com/JankariTech/blog/woodpecker-ci-starlark/src/assets/woodpeckerCI/images/settings.png)
169+
170+
- Then, add `.woodpecker.star` as pipeline config path and save it:
171+
172+
![Pipeline Config](https://raw.githubusercontent.com/JankariTech/blog/woodpecker-ci-starlark/src/assets/woodpeckerCI/images/path.png)
173+
174+
## Generating the Public Key
175+
Every request sent by Woodpecker is signed using a http-signature by a private key (ed25519) generated on the first start of the Woodpecker server. You can get the public key for the verification of the http-signature from:
176+
```console
177+
http(s)://your-ci-server/api/signature/public-key
178+
```
179+
Store that public key into `keys/public.pem` in the same directory level as your docker compose, it will be needed for signature verification.
180+
181+
## Setting Up WCCS-Woodpecker CI Config Service (Starlark Conversion Service)
182+
The Woodpecker Config Conversion Service (WCCS) is a lightweight web service created and maintained by [Opencloud-eu](https://opencloud.eu/en). It enables Woodpecker CI to convert pipeline definitions written in Starlark into standard YAML on the fly by receiving a signed POST request from Woodpecker.
183+
You can easily deploy WCCS using their official Docker image available on Docker Hub: [opencloudeu/wccs](https://hub.docker.com/r/opencloudeu/wccs).
184+
```yml
185+
wccs:
186+
image: opencloudeu/wccs:latest
187+
container_name: wccs
188+
command: server
189+
environment:
190+
- WCCS_LOG_LEVEL=debug
191+
- WCCS_SERVER_PUBLIC_KEY=/keys/public.pem
192+
volumes:
193+
- /opt/woodpecker/keys:/keys
194+
- /etc/ssl/certs:/etc/ssl/certs:ro
195+
labels:
196+
- "traefik.enable=true"
197+
- "traefik.http.routers.wccs.rule=Host(`your-wccs-server`)"
198+
- "traefik.http.routers.wccs.entrypoints=websecure"
199+
- "traefik.http.routers.wccs.tls.certresolver=letsencrypt"
200+
- "traefik.http.services.wccs.loadbalancer.server.port=8080"
201+
networks:
202+
- woodpecker-net
203+
204+
volumes:
205+
woodpecker-server-data:
206+
woodpecker-agent-config:
207+
208+
networks:
209+
woodpecker-net:
210+
driver: bridge
211+
```
212+
213+
## Connecting WCCS with Woodpecker
214+
To allow Woodpecker to fetch pipeline configs from WCCS, we added this to the server env:
215+
```console
216+
WOODPECKER_CONFIG_SERVICE_ENDPOINT=http://wccs:8080/ciconfig
217+
```
218+
Woodpecker now sends a signed JSON payload to WCCS whenever a build is triggered. WCCS verifies the signature using the public key and responds with a YAML pipeline based on your .woodpecker.star file.
219+
220+
## Add a Simple Starlark Pipeline
221+
Here's a simple `.woodpecker.star` example that you can add in your project's root and you're all set:
222+
```console
223+
def main(ctx):
224+
return [{
225+
"name": "hello",
226+
"steps": [
227+
{
228+
"name": "greeting",
229+
"image": "alpine",
230+
"commands": [
231+
"echo Hello from CI",
232+
],
233+
"when": {
234+
"event": ["push", "pull_request"],
235+
"branch": ["master"],
236+
},
237+
}
238+
]
239+
}]
240+
```
241+
242+
## Triggering Your First CI Run
243+
Now that you have your `.woodpecker.star` file ready, commit and push it to your GitHub repository and then, open a Pull Request from your branch <your-branch-name> to master.
244+
Once the PR is created, Woodpecker will automatically send the build request to WCCS, fetch the pipeline config, and start your first CI run. You can head over to the Woodpecker UI to watch the build logs in real time.
245+
246+
![Converted Yaml](https://raw.githubusercontent.com/JankariTech/blog/woodpecker-ci-starlark/src/assets/woodpeckerCI/images/converted.png)
247+
248+
![CI build](https://raw.githubusercontent.com/JankariTech/blog/woodpecker-ci-starlark/src/assets/woodpeckerCI/images/CI.png)
249+
250+
251+
## Conclusion
252+
This setup provides a robust, secure, and flexible CI/CD pipeline using Woodpecker CI, enhanced with WCCS for configuration management and protected by Traefik. The integration of these components creates a powerful system that can handle complex pipeline configurations while maintaining security and ease of use.
253+
254+
Now, we can write pipelines in Starlark and let WCCS handle the conversion on the fly. This approach brings flexibility, structure, and the power of logic-based configurations to our CI pipelines.

0 commit comments

Comments
 (0)