Wrap logs in codeblocks
13 September, 2023 - Tags: bash, til
Problem Statement
I was working on some builds and was trying to improve the security posture of the Dockerfile
and overall build process. As it always happens, some of the builds were failing and I wanted to share the logs via GitHub gist. One way is that you directly use your mouse and keep copy and pasting stuff to a gist via a UI or put that in codeblock and then share it but that's not feasible if you're doing a lot of builds and testing it out say every 2-3 minutes.
I wanted a solution that will automate the process.
The obvious and the first method where I looked is to write all the stdout
and stderr
logs messages to a file when we invoke a docker build
for a Dockerfile. I used |&
bash operator for this purpose. This basically writes everything to a file when executed.
To summarize, the build command looked like this.
bash
$ docker build -t ttl.sh/$(uuidgen | cut -d - -f 1):1h -f Dockerfile . |& tee docker_build_logs.md
fish
docker build -t ttl.sh/(uuidgen | cut -d - -f 1):1h -f demo/Dockerfile . &| tee docker_build.md
Note: There are some very minor differences here, we don't use $
in fish when it comes to command expansion and we use &|
in fish for redirection.
Wrapping Logs inside Markdown codeblock
If you look at the logs then it looks something like this.
#1 [internal] load .dockerignore
#1 transferring context: 2B done
#1 DONE 0.0s
#2 [internal] load build definition from Dockerfile
#2 transferring dockerfile: 191B done
#2 DONE 0.0s
#3 [internal] load metadata for docker.io/library/openjdk:17-alpine
#3 DONE 0.5s
#4 [internal] load build context
#4 transferring context: 2B done
#4 DONE 0.0s
It's good but not markdown compatible, if you'll upload it directly to GitHub gist then you'll not have a smooth experience looking at it.
I wanted to wrap these logs in markdown codeblock so that it looks good and GitHub gist and I can also use gh gist create
command and after that I can automate it using a script.
So, I wanted the file to start with ```bash and end with ````:
wraping a single file inside codeblock
After few iterations I came up with this script below:
#!/bin/bash
file="$1"
sed -i '1i```bash' $file
printf '\n```' >> $file
wraping multiple files inside codeblock
This was working well but I also wanted to have the ability to simultaneously add codeblocks to a lot of files. So, again after a few iterations I came up with this.
#!/bin/bash
files=("$@")
for file in "${files[@]}"
do
sed -i '1i```bash' "$file"
printf '\n```\n' >> "$file"
done
Now, this was also working good.
removing codeblocks
Now, I wanted to remove those codeblocks from the existing file to which I have already added the codeblock for quick testing. I came up with this script after reading the sed manual.
#!/bin/bash
files=("$@")
for file in "${files[@]}"
do
sed -i '1d;$d' $file
done
I'm thinking of keeping the wrap one as cwrap
in the path and unwrap one as unwrap
in the path. This will I'll be able to execute the script from anywhere in the system.
Credits: