- Published on
Automating the workflow
- Authors
- Name
- ディーン・タリサイ
- @prjctimg
NOTE
Repetitive tasks ought not to be redone by hand. ~me
When overwhelmed with the amount of tasks we have to perform, often repeatedly, certain it becomes tedious to do this by hand. Automation, in the context of this article, allows us to reuse commands or procedures with the obvious benefits being time saved and reduced mental overhead, allowing us to focus on the interesting parts of our work and if necessary, multitask our way through.
What should I automate ?
Everything.
We should automate any work that we can because the goal of using a computer is to reduce the amount of work we have to do as humans. A good example of automation is how platforms like GitHub can watch for events on a repository and react to them on your behalf such as when someone opens a new issue or pushes to main
.
How do we set ourselves up for this ?
It depends.
The key takeaway is that for whatever tool or environment you're working in, we should have a way to abstract regular and repetitive tasks. The following sub-headings will go over different scenarios showing automation in practice.
cron
Running at intervals with Using the crontab
utility, we can write scripts that can be run at specified intervals. I store my scripts for crontab
under $HOME/.routines
but you may store yours wherever you see fit.
cd "$HOME/.routines"
# Make it executable
sudo chmod +x workspace_backup.sh
# NB - you can use any text editor
vi workspace_backup.sh
Inside of our workspace.sh
, we define our script, for most tasks bash
is a good choice because it's widely available in most environments.
#! /bin/env bash
# The directory where your Git repositories are located.
WORKSPACE_DIR="$HOME/workspace"
# The directory where the backups will be stored.
# Ensure this directory exists and the script has write permissions.
BACKUP_DIR="/tmp/workspace_backup"
# This will include a timestamp to make each backup unique.
ARCHIVE_NAME="workspace_snapshot-$(date +%Y%m%d_%H%M%S).tar.gz"
# Temporary directory to store individual git bundles before archiving.
TEMP_BUNDLE_DIR="${BACKUP_DIR}/git_bundles"
echo "Starting workspace backup routine for $(date)"
echo "Workspace directory: ${WORKSPACE_DIR}"
echo "Backup destination: ${BACKUP_DIR}"
# Create backup directory if it doesn't exist
mkdir -p "${BACKUP_DIR}" || {
echo "Error: Could not create backup directory ${BACKUP_DIR}. Exiting."
exit 1
}
# Create temporary bundle directory
mkdir -p "${TEMP_BUNDLE_DIR}" || {
echo "Error: Could not create temporary bundle directory ${TEMP_BUNDLE_DIR}. Exiting."
exit 1
}
# Find all Git repositories and create bundles
find "${WORKSPACE_DIR}" -type d -name ".git" | while read -r GIT_DIR; do
# Get the parent directory of .git (which is the repository root)
REPO_PATH=$(dirname "${GIT_DIR}")
# Extract the repository name for the bundle file
REPO_NAME=$(basename "${REPO_PATH}")
# Construct the full path for the bundle file
BUNDLE_FILE="${TEMP_BUNDLE_DIR}/${REPO_NAME}.bundle"
echo "Backing up repository: ${REPO_PATH} to ${BUNDLE_FILE}"
# Change to the repository directory to create the bundle
(cd "${REPO_PATH}" && git bundle create "${BUNDLE_FILE}" --all) || {
echo "Warning: Failed to create bundle for ${REPO_PATH}. Skipping."
}
done
# Check if any bundles were created
if [ -z "$(ls -A "${TEMP_BUNDLE_DIR}")" ]; then
echo "No Git repositories found or no bundles were created. Exiting."
rmdir "${TEMP_BUNDLE_DIR}" # Remove empty temp directory
exit 0
fi
echo "Creating archive: ${BACKUP_DIR}/${ARCHIVE_NAME}"
# Create a compressed tar archive of all bundle files
# -C "${TEMP_BUNDLE_DIR}" changes to the directory before archiving,
# so the archive contains just the bundle files, not the full path.
tar -czf "${BACKUP_DIR}/${ARCHIVE_NAME}" -C "${TEMP_BUNDLE_DIR}" . || {
echo "Error: Failed to create archive ${ARCHIVE_NAME}. Exiting."
rm -rf "${TEMP_BUNDLE_DIR}" # Clean up even on error
exit 1
}
echo "Backup successful! Archive saved to: ${BACKUP_DIR}/${ARCHIVE_NAME}"
# Clean up temporary bundle files
echo "Cleaning up temporary bundle directory: ${TEMP_BUNDLE_DIR}"
rm -rfv "${TEMP_BUNDLE_DIR}"
echo "Backup process completed."
After we save our script, we then edit our crontab
file:
crontab -e

Our script will now run at regular intervals without our intervention.
git
hooks
Easier version control with Git hooks allow us to attach routines to events that occur when we are working with git
such as committing and pushing. They're particularly useful if you want to deeply integrate with Git (events).
Here's an example of setting up a pre-push hook, it will run before we push changes to our remote repository. If it exits with an error then git push
will be cancelled:
# cd into any direcctory with a git repository
cd workspace/me/.git/hooks
mv pre-push.sample pre-push
sudo chmod +x pre-push
This hook will just run tests:
#! /usr/bin/env sh
bun test
You can see the tests being ran when we run git push
:
#o %% e %%# Use workflows for package publishing
Publishing from your development machine is the traditional way to do things. Nowadays, it's wiser to have your code/binaries released or published to registries via a workflow. GitHub Actions are suited for this and the open source community has a lot of them available.
A popular option is release-please
which allows you to trigger releases and generate changelogs whenever a new git tag
is created. This allows you to keep adding commits until you're ready to merge back to the main/stable branch which will then create the release.
Here's an example of how I use release-please
:
If the platform offers a developer API, use it
The fun part of being a developer is that you don't have to interact with software like normal users, the hacking mentality pushes us to try different ways to solve problems.
Let's say you want to be able to post about what you're currently doing on Tumblr without too much context switching, that is, you want to do this task without leaving your current UI. The same could also be said about web browsers in as much as terminals. Just as you can switch tabs and move between different apps in Chrome, you should also be able to replicate that navigational freedom in the terminal.
NOTE
I'm writing a small collection of TUIs for platforms I use regularly to address this. The code is WIP
Create content in advance and automate the publishing
Writing is really hard and I often find that I don't have the motivation to type out a lot of words. Which is why I now prefer to write in short bursts and then refine each post as I go, this habit helps me stay consistent.
The zen
posts on this site are actually automated and they publish themselves everyday at 5 AM from simple json file that has each day as a key from 1 to 365. The other posts have a released
property that tell the day the post will be published on. A script is run everyday at 7 AM to check if there is any post due to be released, if it is found it's draft
YAML property is changed from true
to false
and then make a release commit that triggers a redeployment of the site. Straight forward stuff.
You can even automate theme toggling in your editor (neovim btw)
If you're in nvim
you can use the init.lua
file to describe the editor's behavior when it starts . The beauty of this all is the freedom to tweak your environment until it suits your workflow. Here's an example of checking if the current theme matches the time of the day:
-- in your init.lua file
local function swap_theme()
local hour = tonumber(os.date("%H"))
local light_theme = "tokyonight-day"
local dark_theme = "tokyonight"
local is_day = hour >= 6 and hour < 17
if is_day then
vim.cmd.colorscheme(light_theme)
Snacks.notifier("Lights on 🌄", "info", {
title = "System",
})
else
vim.cmd.colorscheme(dark_theme)
Snacks.notifier("Lights out 🎑", "info", {
title = "System",
})
end
end
swap_theme()
-- timer to periodically update theme
vim.fn.timer_start(18000000, function()
swap_theme()
end, { ["repeat"] = -1 })
What now ?
This was just an overview of some of the things that can be automated or, at least some ways to use automation in your development workflow.
You can find Gist with the code samples here , feel free to leave a comment on it and or suggest improvements.