Skip to content

Commit a407b28

Browse files
address reviews
Signed-off-by: prashant-gurung899 <prasantgrg777@gmail.com>
1 parent 1a66dea commit a407b28

File tree

4 files changed

+131
-76
lines changed

4 files changed

+131
-76
lines changed

oauth.png

60.5 KB
Loading
60.5 KB
Loading
74.1 KB
Loading

src/assets/woodpeckerCI/woodpeckerCI.md

Lines changed: 131 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ authorName: Prashant Gurung
44
authorAvatar: https://avatars.githubusercontent.com/u/53248463?v=4
55
authorLink: https://github.com/prashant-gurung899
66
createdAt: July 3, 2025
7-
tags: CI/CD
7+
tags: CI/CD, Woodpecker, starlark, docker-compose, Traefik, WCCS
88
banner: https://raw.githubusercontent.com/JankariTech/blog/woodpecker-ci-starlark/src/assets/woodpeckerCI/images/cover.png
99
---
1010

1111
## 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.
12+
Continuous Integration tools are essential to build and test modern software automatically and regularly. Woodpecker CI is one such open-source tool, a lightweight CI/CD system. Woodpecker CI is an open-source continuous integration and delivery system that help developers in automating deployment, builds, and testing of code. It's an open-source fork and alternative to the popular Drone CI project with numerous design similarities and Drone pipeline compatibility. Traditionally, Woodpecker pipelines are YAML, but now that programmable pipelines are in vogue, we can finally have the liberty of defining our CI configuration through Starlark — a Python-ish config language.
1313

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:
14+
In this article, I will walk you through setting up Woodpecker CI with Traefik as a reverse proxy and [WCCS](https://github.com/opencloud-eu/woodpecker-ci-config-service/) (Woodpecker CI Config Service) to convert Starlark configurations into YAML files so that we can write pipelines in `.star` files. Here is a high-level overview of what we are going through:
1515

1616
- Spinning up a Woodpecker server with Traefik
1717

@@ -23,27 +23,57 @@ In this blog, I’ll walk you through setting up Woodpecker CI with Traefik as a
2323

2424
By the end, you’ll be able to write CI pipelines in Starlark and dynamically convert them to YAML during runtime.
2525

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
26+
## Setting Up Woodpecker Server and Agent
27+
Let's start by setting up the Woodpecker server and agent services in the `docker-compose.yml` file as show below:
3528

29+
```yml
30+
services:
31+
woodpecker-server:
32+
image: woodpeckerci/woodpecker-server:v3
33+
environment:
34+
- WOODPECKER_LOG_LEVEL=debug
35+
- WOODPECKER_OPEN=false
36+
- WOODPECKER_HOST=http://<your-ci-server>
37+
- WOODPECKER_GITHUB=true
38+
- WOODPECKER_GITHUB_CLIENT=xxxxxxx # GitHub OAuth client ID
39+
- WOODPECKER_GITHUB_SECRET=xxxxxxx # GitHub OAuth secret
40+
- WOODPECKER_AGENT_SECRET=xxxxxxx # shared secret between server and agents
41+
- WOODPECKER_ADMIN=your-github-username
42+
# The following variable is where we set our Woodpecker CI Config Service (Starlark Conversion Service) later
43+
- WOODPECKER_CONFIG_SERVICE_ENDPOINT=http://<your-config-service-server>
44+
volumes:
45+
- woodpecker-server-data:/var/lib/woodpecker/
46+
networks:
47+
- woodpecker-net
3648

37-
# Shared secret used by server<->agent - you can generate it using openSSL
38-
WOODPECKER_AGENT_SECRET=<generated-secret>
49+
woodpecker-agent:
50+
image: woodpeckerci/woodpecker-agent:v3
51+
restart: always
52+
depends_on:
53+
- woodpecker-server
54+
volumes:
55+
- woodpecker-agent-config:/etc/woodpecker
56+
- /var/run/docker.sock:/var/run/docker.sock
57+
environment:
58+
- WOODPECKER_LOG_LEVEL=debug
59+
- WOODPECKER_SERVER=woodpecker-server:9000
60+
- WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}
61+
networks:
62+
- woodpecker-net
3963

64+
volumes:
65+
woodpecker-server-data:
66+
woodpecker-agent-config:
4067

41-
# Let’s Encrypt contact email (Traefik will use this)
42-
ACME_EMAIL=admin@example.com
68+
networks:
69+
woodpecker-net:
70+
driver: bridge
4371
```
4472
45-
## Traefik Configuration
46-
Traefik plays a crucial role in this architecture by handling all the networking complexities - SSL termination, routing, and load balancing
73+
## Traefik Configuration for HTTPS
74+
So far our woodpecker server runs on HTTP, so to serve it on HTTPS we are going to configure Traefik.
75+
Traefik plays a crucial role in this architecture by handling all the networking complexities - SSL termination, routing, and load balancing.
76+
Add the following Traefik service right above the `woodpecker-server` service in the same `docker-compose.yml` file:
4777

4878
```yml
4979
version: "3.9"
@@ -60,7 +90,7 @@ services:
6090
- "--entrypoints.websecure.address=:443"
6191
- "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
6292
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
63-
- "--certificatesresolvers.letsencrypt.acme.email=${ACME_EMAIL}"
93+
- "--certificatesresolvers.letsencrypt.acme.email=example@example.com" #letsEncrypt contact email
6494
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
6595
ports:
6696
- "80:80"
@@ -70,34 +100,32 @@ services:
70100
- "/var/run/docker.sock:/var/run/docker.sock:ro"
71101
networks:
72102
- woodpecker-net
103+
104+
woodpecker-server:
105+
image: woodpeckerci/woodpecker-server:v3
106+
...
107+
...
108+
...
109+
woodpecker-agent:
110+
image: woodpeckerci/woodpecker-agent:v3
111+
...
112+
...
113+
...
73114
```
74115

75116
This configuration:
76117

77118
- Sets up Traefik to listen on ports 80 and 443
78-
- Configures Let's Encrypt for automatic SSL certificate management
119+
- Configures automatic SSL certificate management via [letsEncrypt](https://letsencrypt.org/)
79120
- Enables Docker provider to automatically detect new services
80121
- Mounts necessary volumes for certificate storage and Docker socket access
81122

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:
123+
Now that we have Traefik configured, update the Woodpecker server service by adding following labels:
84124

85125
```yml
86126
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/
127+
...
128+
...
101129
labels:
102130
- "traefik.enable=true"
103131
- "traefik.http.routers.woodpecker-secure.rule=Host(`your-ci-server`)"
@@ -113,31 +141,19 @@ Now that we have Traefik running, let's set up the Woodpecker server and agent s
113141
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
114142
networks:
115143
- 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
132144
```
133145
134146
## Authenticating with GitHub
135147
148+
Woodpecker cannot do anything by itself, it needs a forge (the service where the repositories are hosted). Woodpecker supports [various forges](https://woodpecker-ci.org/docs/administration/configuration/forges/overview), for this blog we will focus on GitHub.
149+
136150
To connect GitHub with Woodpecker:
137151
138-
1. Register a new OAuth application in your GitHub developer settings.
152+
1. Register a new OAuth application in your GitHub developer [settings](https://github.com/settings/applications/new).
153+
154+
2. In your GitHub OAuth App, set the authorization callback URL to `https://<your-ci-server>/authorize`
139155

140-
2. Set the callback URL to `https://<your-ci-server>/authorize`
156+
![Callback URL](https://raw.githubusercontent.com/JankariTech/blog/woodpecker-ci-starlark/src/assets/woodpeckerCI/images/oauth.png)
141157

142158
3. Copy the generated Client ID and Secret.
143159

@@ -148,47 +164,61 @@ After that, you can log into the Woodpecker web UI using your GitHub account.
148164
![GitHub Login](https://raw.githubusercontent.com/JankariTech/blog/woodpecker-ci-starlark/src/assets/woodpeckerCI/images/github.png)
149165

150166
## Enabling a Repository
167+
Before enabling a repo in the Woodpecker CI server, make sure to have a GitHub repository ready. You can use an existing repo of your own or create a new empty one. We will be making a pull request to the repo to trigger CI later.
168+
151169
From the Woodpecker UI:
152170

153171
- Click on Add Repository.
154172

155173
![Add Repo](https://raw.githubusercontent.com/JankariTech/blog/woodpecker-ci-starlark/src/assets/woodpeckerCI/images/add.png)
156174

157-
- Enable it.
175+
- Enable it. For this blog, I am using an existing repo called `Drum-KIT` which has already been enabled(as you can see in the last row of the image below).
158176

159177
![Enable Repo](https://raw.githubusercontent.com/JankariTech/blog/woodpecker-ci-starlark/src/assets/woodpeckerCI/images/enable.png)
160178

161179
Woodpecker will automatically add the necessary webhooks to the repo.
162180

181+
## Triggering Your First CI Run
182+
While we are trying to integrate a starlark conversion service, woodpecker CI supports the default `.yml` pipelines.
183+
So. now we can trigger our first CI using a traditional YAML configuration as show below.
184+
Create a new branch <your-branch-name> and add the following configuration in the root of your enabled github repo with name `.woodpecker.yml`.
185+
186+
187+
```yaml
188+
steps:
189+
- name: hello
190+
image: alpine
191+
commands:
192+
- echo "Hello from CI"
193+
- echo "--------------------"
194+
- echo "This is my first CI BUILD"
195+
- echo "--------------------"
196+
when:
197+
event: pull_request
198+
branch: master # configure it as your repo's base branch.(in my case, it's `master`)
199+
```
163200

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:
201+
Now that you have your `.woodpecker.yaml` file ready, you can commit and push it to your enabled GitHub repository and then, open a Pull Request from your branch <your-branch-name> to `master/main` according to you repo. GitHub's default branch is set to `main`.
202+
Once the PR is created, Woodpecker will automatically fetch the pipeline configuration, and start your first CI run. You can then head over to the Woodpecker UI to watch the build logs in real time.
171203

172-
![Pipeline Config](https://raw.githubusercontent.com/JankariTech/blog/woodpecker-ci-starlark/src/assets/woodpeckerCI/images/path.png)
204+
![Yaml Pipleine](https://raw.githubusercontent.com/JankariTech/blog/woodpecker-ci-starlark/src/assets/woodpeckerCI/images/yaml.png)
173205

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.
206+
Now that we have already set up the woodpecker server and triggered pipelines using the traditional `.yaml` configuration, let's now integrate WCCS to unlock flexibility and define our pipelines in Starlark.
180207

181208
## Setting Up WCCS-Woodpecker CI Config Service (Starlark Conversion Service)
182209
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.
183210
You can easily deploy WCCS using their official Docker image available on Docker Hub: [opencloudeu/wccs](https://hub.docker.com/r/opencloudeu/wccs).
211+
Update your `docker-compose.yml` to include the WCCS service:
184212
```yml
213+
...
214+
185215
wccs:
186216
image: opencloudeu/wccs:latest
187217
container_name: wccs
188218
command: server
189219
environment:
190220
- WCCS_LOG_LEVEL=debug
191-
- WCCS_SERVER_PUBLIC_KEY=/keys/public.pem
221+
- WCCS_SERVER_PUBLIC_KEY=/keys/public.pem # path to public key(generated in the section below)
192222
volumes:
193223
- /opt/woodpecker/keys:/keys
194224
- /etc/ssl/certs:/etc/ssl/certs:ro
@@ -201,6 +231,8 @@ You can easily deploy WCCS using their official Docker image available on Docker
201231
networks:
202232
- woodpecker-net
203233

234+
...
235+
204236
volumes:
205237
woodpecker-server-data:
206238
woodpecker-agent-config:
@@ -210,15 +242,38 @@ networks:
210242
driver: bridge
211243
```
212244
245+
## Generating the Public Key
246+
Before running any pipeline, woodpecker server sends a POST request to an external config service (in our case WCCS) with all current config file and build information of the current repository. The external service takes the information and sends back the pipeline configurations. In our case, this is how a starlark file is being converted into yaml configurations.
247+
248+
And before WCCS can accept and process those requests, it needs to verify that the requests are trusted and coming from the woodpecker server.
249+
250+
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:
251+
```console
252+
https://<your-ci-server>/api/signature/public-key
253+
```
254+
Store that public key into `keys/public.pem` in the same directory level as your docker compose. The `public.pem` file is then mounted to the WCCS container as shown in the snippet above and used in env variable `WCCS_SERVER_PUBLIC_KEY`
255+
213256
## Connecting WCCS with Woodpecker
214257
To allow Woodpecker to fetch pipeline configs from WCCS, we added this to the server env:
215258
```console
216259
WOODPECKER_CONFIG_SERVICE_ENDPOINT=http://wccs:8080/ciconfig
217260
```
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.
261+
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.
262+
263+
After conneting WCCS with the woodpecker server, there's one more thing that you need to do i.e. to set pipeline config path, because by default Woodpecker will take `.woodpecker.yaml` as it's pipeline configuration.
264+
265+
- From the settings of your Woodpecker server, go to `Repositories` and click on the enabled repo's settings icon as shown below:
266+
267+
![Settings](https://raw.githubusercontent.com/JankariTech/blog/woodpecker-ci-starlark/src/assets/woodpeckerCI/images/settings.png)
268+
269+
- Then, add `.woodpecker.star` as pipeline config path and save it:
270+
271+
![Pipeline Config](https://raw.githubusercontent.com/JankariTech/blog/woodpecker-ci-starlark/src/assets/woodpeckerCI/images/path.png)
219272

220273
## 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:
274+
Here's a simple starlark pipeline configuration example that you can add in your project.
275+
Create a new branch by checking out from your `master/main` branch.
276+
Add the following configration in the `.woodpecker.star` file in your repo's root
222277
```console
223278
def main(ctx):
224279
return [{
@@ -232,16 +287,16 @@ def main(ctx):
232287
],
233288
"when": {
234289
"event": ["push", "pull_request"],
235-
"branch": ["master"],
290+
"branch": ["master"], # configure it as your repo's base branch.(in my case, it's `master`)
236291
},
237292
}
238293
]
239294
}]
240295
```
241296

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.
297+
## Triggering CI with starlark-powered pipeline
298+
Now that you have your `.woodpecker.star` file ready, commit and push it to your GitHub repository and then, open a new Pull Request from your branch <your-branch-name> to master/main.
299+
Once the PR is created, Woodpecker will automatically send a build request to WCCS, fetch the pipeline configuration, and start your first CI run. You can then head over to the Woodpecker UI to watch the build logs in real time.
245300

246301
![Converted Yaml](https://raw.githubusercontent.com/JankariTech/blog/woodpecker-ci-starlark/src/assets/woodpeckerCI/images/converted.png)
247302

0 commit comments

Comments
 (0)