My brief journey of moving from GitHub to GitLab
Why GitLab?
I have always used GitHub for my code. So for no reason except curiosity I decided to migrate to GitLab. I had to start somewhere, so I started with this blog!
How was it?
Pretty easy and straightforward. But of course, what would you expect? They are both git online repo serivices. Yes I know that they have some big differences, but I'll discover/learn them later on.
The main differences that I encountered:
- The GitLab UI; I still need to familiarize with it 😂.
- The CI/CD features.
GitLab CI/CD
GitHub Actions and GitLab CI/CD have some important differences. First of all, the configuration file. While the GitHub Actions' file is easy to read for a newcomer, I actually prefer the GitLab one: you need to write/specify more configuration. But in the end, it make much more sense.
After going through the CI/CD docs and understanding some basic concepts (such as stages and rules), I was able to port my GitHub Action to GitLab. This is now my CI script, you can find the old one here:
stages:
- build
- deploy
- clean
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "prod"'
- if: '$CI_PIPELINE_SOURCE == "web" && $CI_COMMIT_BRANCH == "prod"'
variables:
PROJECT_NAME: "jeks"
#CLOUDFLARE_API_TOKEN: # Secret
#CLOUDFLARE_ACCOUNT_ID: # Secret
patch-and-build:
stage: build
image: alpine:3.23
variables:
GIT_SUBMODULE_STRATEGY: recursive
artifacts:
paths:
- ./blog/public
expire_in: 1 day
before_script:
- apk add --no-cache git
- apk add --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/edge/community/ zola
script:
- echo "Applying Git patches"
- |
for patch in patches/*.patch.diff; do
if [ -f "$patch" ]; then
echo "Applying patch $patch"
git apply "$patch" || { echo "Failed to apply patch $patch"; exit 1; }
else
echo "No patch file found: $patch"
exit 1
fi
done
- echo "Running zola build"
- cd ./blog/
- zola build
publish:
image: node:alpine3.23
stage: deploy
script:
- npm install wrangler --location=global
- wrangler pages deploy ./blog/public --project-name "${PROJECT_NAME}" --branch "main"
remove-older:
stage: clean
image: debian:12-slim
before_script:
- apt-get update
- apt-get install -y jq curl
script:
- echo "Cleaning up old deployments"
- |
DEPLOYMENTS=$(curl -s -X GET "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/pages/projects/${PROJECT_NAME}/deployments" \
-H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
| jq -r '.result | reverse | .[].id')
if [ -z "$DEPLOYMENTS" ]; then
echo "No deployments found."
exit 0
fi
readarray -t DEPLOYMENT_ARRAY <<< "$DEPLOYMENTS"
if [ ${#DEPLOYMENT_ARRAY[@]} -gt 2 ]; then
NUM_DEPLOYMENTS_TO_DELETE=$(( ${#DEPLOYMENT_ARRAY[@]} - 2 ))
for (( i=0; i<$NUM_DEPLOYMENTS_TO_DELETE; i++ )); do
DEPLOYMENT_ID="${DEPLOYMENT_ARRAY[$i]}"
echo "Deleting deployment $DEPLOYMENT_ID"
curl -s -X DELETE "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/pages/projects/${PROJECT_NAME}/deployments/$DEPLOYMENT_ID" \
-H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}"
done
else
echo "No old deployments to delete."
fiOne key difference I want to point out is that GitLab has no out-of-the-box way of managing secrets, unlike GitHub. You can create environment variables per Project. And declare them masked ([Masked] will be displayed in the logs instead of the value), hidden (can not be revealed, neither in settings) and protected (can be used only on protected branches). Or you can also configure external secret management serivices, like HashiCorp Vault.
What else has changed? Introducing Umami
When I wrote about analytics I ended up having both Counter and Rybbit. Now, after some months, I can definitely tell that Counter doesn't work for me: it has recorded only 11 users compared to Rybbit's 72.
I recently heard about Umami, and given that it meets my requirements, I decided to give it a try. Now I'll see how it performs compared to Rybbit. And, as always, I'll come back with updates.