Perspective · Learning lab

From manual uploads to CI/CD

This site is my learning lab. I am here to learn how it works by doing something real. This discussion is about what changed in the way I publish it.

Where I started

Until recently, every change meant uploading the whole site by hand. I kept one folder per version on my drive, zipped the latest one, and sent it to Cloudflare. I was repeating this step even when I had changed a small sentence.

It worked, but of course I was not bringing updates frequently and I was not controlling errors or a list of current changes implemented. The only record of what had changed was my memory and a list of notes, and the only test was opening the page afterwards and looking at it.

How it works now

Now, the site lives in a Git repository on GitHub. I make small changes on a separate branch and open a pull request, and GitHub runs the tests on it. The public version only changes when I merge into main, after every check has passed. Cloudflare takes it from there.

Flow diagram. Your computer: you change the map or another site file, then git push to a development branch. GitHub stores versions and runs the tests. If the tests pass, you approve and merge into main. If they fail, you fix it without affecting the site. Cloudflare then automatically publishes the approved version, and fsartori.com is updated and publicly accessible.
A failure stops at the branch. Only what is merged into main gets published.

A real example: updating the maps

My Two runoffs post links to two interactive maps, and I had a new final version of them. In the old routine that meant a new folder, a new zip and a full upload. This time the whole change was two files:

public/perspective/brazil-runoffs/maps/mapa_eleicao_2022.html
public/perspective/brazil-runoffs/maps/mapa_eleicao_2026.html

The maps come out of a script, and the new files did not include the Cloudflare Web Analytics snippet. I knew that and I had written a check for this case. I wanted to know whether it would flag the error.

It did. Here is the relevant part of the log:

FAIL .../maps/mapa_eleicao_2022.html: Web Analytics script present exactly once  ->  found 0, fsartori.com token missing
FAIL .../maps/mapa_eleicao_2026.html: Web Analytics script present exactly once  ->  found 0, fsartori.com token missing

28 checks passed, 2 failed.

I added the snippet to both files and pushed again to the same branch. The tests ran again on their own and passed, and only then did I merge. This is the whole sequence:

TimeWhat happened
10:08Committed the two new map files on a branch
10:12Opened the pull request, which started the tests
10:13The static checks failed: 28 passed, 2 failed. The live site still had the old maps
10:27Pushed the fix to the same branch
10:28The tests ran again and passed
10:36Merged into main, and Cloudflare published the new version

Why this check exists

I use Cloudflare Web Analytics to see how many people visit the site and which pages they open. When I moved the site from Cloudflare Pages to Workers, the snippet that Cloudflare used to add automatically disappeared after a deploy. So it now lives in the HTML of every page, and a test requires it exactly once per page.

This kind of mistake is easy to miss. Without the snippet the maps look perfect and no error appears anywhere. I would only have noticed later, as a gap in the numbers.

On every pull request, my tests check that:

Analytics. The snippet sends page views and performance metrics to Cloudflare Web Analytics, which only I read, through my account. Cloudflare states that the product uses no cookies or localStorage and does not fingerprint visitors.

Stack. Static HTML and CSS, Git and GitHub, GitHub Actions for the tests (Python, Playwright), Cloudflare Workers Builds for publishing.