A script for Go dependency updates

I regularly update the dependencies of my blog software, a Go based project. Dependency updates are important because they can contain security fixes or fixes for bugs.

Because I don’t want to manually check and update every dependency manually, I built myself a script that updates all direct and indirect dependencies. It’s also helpful because I’m bad at remembering all the necessary flags for the go mod command.

Recently Tailscale released a new version. I use Tailscale in my software as a dependency, so that it can publish blogs directly to a private Tailscale network, or tailnet.

However, this update conflicted with another dependency I use, golang.org/x/crypto. This package is used for the acme/autocert part that helps creating automatic HTTPS certificated for public sites. When I tried to run my script, I always got the following error.

go.goblog.app/app imports
tailscale.com/tsnet imports
tailscale.com/ipn/ipnlocal imports
github.com/tailscale/golang-x-crypto/ssh imports
github.com/tailscale/golang-x-crypto/chacha20 imports
github.com/tailscale/golang-x-crypto/internal/subtle tested by
github.com/tailscale/golang-x-crypto/internal/subtle.test imports
golang.org/x/crypto/internal/subtle: module golang.org/x/crypto@latest found (v0.0.0-20220829220503-c86fa9a7ed90), but does not contain package golang.org/x/crypto/internal/subtle

The only (temporary!) solution is to just upgrade Tailscale and all the other direct dependencies and ignore the crypto package until Tailscale updates their dependencies as well and releases a new version.

To do so, I modified the script and introduced a “skip list”. It now fetches all updates for the direct dependencies and checks one-by-one whether the package should be skipped and when not, upgrades the package.

#!/bin/bash

FLAGS="-tags=linux,libsqlite3,sqlite_fts5"
SKIP="
golang.org/x/crypto
"

checkSkip() {
echo $SKIP | grep -F -q -w "$1"
}

# Update all direct dependencies to latest version
echo "Check for updates..."

# 1. Get all direct dependency updates
updates=$(go list -f '{{if (and (not .Indirect) .Update)}}{{.Path}}{{end}}' -u -m all)

# 2. Update each dependency and tidy
for update in $updates
do
if checkSkip $update
then
continue
fi
echo ""
echo "Update $update"
GOFLAGS=$FLAGS go get $update@latest
GOFLAGS=$FLAGS go mod tidy
done

I thought about moving Tailscale to a plugin to avoid this collision, but that’s a complex project for another time…

Interactions & Comments