Markup is pervasive in DevOps. But markup is also:
- hard to refactor
- has limited control flow
- not type-safe
- hard to test
Refactoring
I see in our codebase something like this:
- name: Set env to Develop
if: endsWith(github.ref, '/develop')
run: |
echo "ENVIRONMENT=develop" >> $GITHUB_ENV
- name: Set env to Staging
if: endsWith(github.ref, '/main')
run: |
echo "ENVIRONMENT=staging" >> $GITHUB_ENV
- name: Set env to Productions
if: endsWith(github.ref, '/production')
run: |
echo "ENVIRONMENT=production" >> $GITHUB_ENV
Not only is this ugly, it's copy-and-pasted everywhere. I can't refactor it and what's more, there is a...
(Lack) of Control
Imagine I want to create an AWS Postrgres instance with Terraform then provision the DB with a schema using the Python library, Alembic all via GitHub Actions? GHA can call the Terraform file and create a DB, but how do I get the URL of that Postgres instance so I can give it to Alembic for it to connect and create the tables? Weaving different technologies together in a Turing Complete language is easy; with markup: less so. I had to hack some calls to the AWS CLI command and parse the JSON it returned, all in bash.
Type-safety issue #1
An example of a lack of type safety can be found in any Terraform script. We had something like this:resource "aws_ecs_task_definition" "compute_task" {
family = var.task_name
container_definitions = <<DEFINITION
[
{
"name": "${var.task_name}",
"image": "${aws_ecr_repository.docker_container_registry.repository_url}:${var.tag}",
...
Which leads to testing. I made my changes in my GitHub Actions file to use the password in the secret ${{ secrets.DB_PASSWORD-staging }} and ran my mock GHS so:
act -j populate -s DB_PASSWORD-staging=...
Spot the errors |