Migrating Wordpress posts to Markdown
Last year (2024) I relaunched my website and I promised to write about the migration process. This post describes how I migrated the posts of my blog to Markdown, automating as much as possible.
Last year (2024) I relaunched my website and I promised to write about the migration process. This post describes how I migrated the posts of my blog to Markdown, automating as much as possible.
semantic-release with an SSH deploy key in GitHub ActionsWe use semantic-release to release new versions of one of our JavaScript-based web applications.
semantic-release can help with various release-based activities, such as figuring out the version bump based on the commit history using conventional commits, updating the changelog, pushing a new version tag, and so on.
We recently migrated our repositories to GitHub and have a ruleset enabled for the main (default) branch to protect this branch.
Using a ruleset is basically the new way of protecting a branch.
For a single developer or a very small team this might be overkill and slow you down.
For bigger teams definitely it makes sense to ensure that certain practices are adhered to.
For example, you can enforce that force pushes are getting blocked, or that a pull request is required before merging.
This is where we ran into issues where the release commit by semantic-release could not be pushed directly to main due to this rule.
GitHub allows you to grant bypass permissions for your ruleset.
Unfortunately, you cannot add a single user to this bypass list, and the GITHUB_TOKEN secret is associated with the (special) github-actions[bot] user.
So, how were we able to accomplish this?
At Opal we want to support the current industry standard in healthcare integration which is SMART on FHIR. This also makes sense given that Opal has a partnership with OpenEMR which supports this standard.
In this article I describe how to authenticate a backend service using the client_credentials grant in Python in two different ways (i.e., with two different packages).
For example, this is required when making use of the Bulk Export API.
The last virtual server (vServer) I had had limited storage space and Docker kept filling up my /var/lib/ directory.
A friend suggested to use lvm to partition the disk.
Here is how I accomplished it using the Debian installer.
I have tripped over an outdated environment variable a few times when running Python from within vscode.
And I finally figured out what caused it.
We store our environment variables in a .env file that is then used by our Django application.
We use the django-environ package for this.
During development, this file is loaded on startup.
When deployed, we provide the file via env_file in the compose file.
What happened in vscode is that when a value in .env changed, running something, such as pytest, would not see this new environment variable value.
After a while I noticed that there was a yellow warning sign next to the terminal process. When hovering over it it asks you to relaunch the terminal because the environment changed. It took me a long time to figure this out in the first place. It's not something I expected and not very intuitive.
I had looked in the past in the settings where this is coming from and how this can be disabled and could not find anything. Today I finally figured it out, after running into this issue again and wasting time until I realized why something did not work.
The popup shown when hovering over the allows you to "Show Environment Contributions".
The Python VSCode extension contributed the variables and causes this behaviour.
In Settings > Extensions > Python there is an entry called "Env File" that contains ${workspaceFolder}/.env.
Remove the value and relaunch the terminal.
Now changes to your .env file won't affect your terminal's environment anymore.
My blog has existed since 2011. The intent has always been to share knowledge I gained, whether this be for someone else, or just for my future self. From the beginning I used Wordpress which makes it quite easy to set up a blog. There are also tons of themes and plugins that you can install and use.
Writing (especially in public) is not super natural for me. Doing it in WordPress did not feel natural to me either. So for a while I was dredding to create new blog posts because it was too cumbersome for me multiple reasons.
Another difficulty was keeping WordPress up to date along with the plugins and any customizations to it. While it is fairly easy to customize CSS, JS, or the PHP code of themes and plugins, there is no easy way to keep those separate so that themes and plugins can be easily updated.
I switched to a containerized setup, putting as much as possible in a repository. This included customizations. My idea was that it would be easier to update themes and plugins and re-apply those customizations. In the end, it was still too much manual work, however. It's not as easy as merging a dependency update on your repository raised by Renovate (of which I am a huge fan) and automatically re-deploying.
A few years ago, I came across the amazing Material for MkDocs. It is a technical documentation theme for MkDocs with many great features. Documentation is written in Markdown and can be version controlled in a repository. This is basically "documentation as code".
I first introduced it at work a few years ago for various documentation sites. Together with Material for MkDocs this has been fantastic.
Since Material for MkDocs has a blog plugin I've been wanting to switch to this for a while. I knew that this will allow me to write blog posts more naturally (in a text editor) and treat everything as code. I finally got around to it and migrated my old WordPress site to what is now a static site.
It is live now .
Keep reading if you are interested in the details of how it is set up.
I was always intrigued by Django. After all, it's slogan is
Quote
The web framework for perfectionists with deadlines
Last year I started a project for a client who needed a web app to manage a digital printing workflow. I evaluated Django and did their tutorial (which is really well made by the way). Since the project also required lots of data processing of different data sources (CSV, XML, etc.) Python made a lot of sense. So in the end the choice was to use Django.
I needed to create several tabIes showing data from the Django models.
In this post I explain how I combined django_tables2 (for the table definitions) and Bootstrap Table (for visualizing the tables and client-side table features).
Thanks in particular to the great German podcast Das Coronavirus-Update from NDR with two fantastic virologists (Christian Drosten and Sandra Ciesek) I gained a better understanding of the pandemic and this coronavirus (SARS-CoV-2) and learned quite a lot new stuff. Maybe because of this, I felt for a while that there was a lack here (in Québec/Montréal) about how the data is presented/visualized. But I had this realization "late" (Fall 2020) and didn't have past data so I didn't want to start something from scratch.
One day I randomly came across a repository on GitHub of a dashboard for Montreal. Unfortunately, the website hadn't been updated in a while so I reached out to Jeremy Moreau who created it. We had a chat and I started helping him adding the data, adjusting to new data formats and automating the data retrieval and processing. Adding the missing data from the past was possible thanks to the Wayback Machine and (for the most part) to the hard work by Jean-Paul Soucy archiving all Canada-wide data for the COVID-19 Canada Open Data Working Group.
Recently, we were trying to find an available camp site on SEPAQ during the summer. We were late to the party, though, and most (interesting) sites were already booked or had single days left here and there.
Finding the remaining sites at flexible dates is actually quite cumbersome since you need to go to each camp site (and click through a calendar week by week there) or go to a single spot of a camp site to see its availability calendar. This is especially cumbersome if you are flexible in terms of the dates and the park.
Long story short, I looked at how to get the availability of the camp sites and hacked together a scraper. It recursively finds all camping spots and downloads the availability for each of them. Once they are downloaded it can parse them and filter for available spots (with minimum days and a desired date range).
You can find the code here: https://github.com/mschoettle/sepaq-availability-scraper
There's definitely some things that could be improved but it got the job done.
msmtpFor a long time I struggled with setting up cronjobs properly. It always took a lot of trial and error. Most of the times this was due to an environment problem (or a typo). You could test your cronjob using a script or saving the command output to a file but it is still cumbersome. At the same time, it would also be nice to be notified whenever something goes wrong, such as your backup script failing all of a sudden.
In this post I explain how to set up msmtp so that your system will send you emails.