Skip to content

action: download latest version of apk (with fallback)#4375

Open
behrmann wants to merge 1 commit into
systemd:mainfrom
behrmann:update-apk
Open

action: download latest version of apk (with fallback)#4375
behrmann wants to merge 1 commit into
systemd:mainfrom
behrmann:update-apk

Conversation

@behrmann

Copy link
Copy Markdown
Contributor

This is a version of #4364 with my comments worked in.

/cc @craftyguy

Supersedes: #4364

Comment thread action.yaml Outdated
Comment thread action.yaml Outdated
APK_PKG_ID=$(curl -fsSL --retry 5 --retry-all-errors "${APK_TOOLS_API}/packages?package_name=${APK_VERSION}&package_type=generic" | jq '.[] | select(.version == "x86_64") | .id' | sort | tail -1)
APK_SHA256=$(curl -fsSL --retry 5 --retry-all-errors "${APK_TOOLS_API}/packages/${APK_PKG_ID}/package_files" | jq -r '.[0].file_sha256')
# If the API fails, fall back to a known-good version
if [ -z "$APK_VERSION" ] || [ -z "$APK_SHA256" ]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fallback path can never happen. shell snippets use set -e and pipefail by default, so failure to download apk from above would just abort the script right there.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hoisted by my own petard. Having SC2155 always in my mind I thought the return value would get clobbered. I wrapped it in set +e/set -e. (I'm actually no fan of set -e, I think it makes error handling in shell in harder than it already is—people don't just panic in Rust everywhere either.)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh, I actually think quite the opposite.. Error handling without set -e is unbearably hard. With the new set +e, if the APK_VERSION curl call fails, you then do a curl call with package_name= (empty), instead of aborting. I think a safer pattern would be

if X=$(curl ...) && 
   Y=$(curl ... $X ...) &&
   ...; then
      echo I got it!
else
     echo I am so sad now

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I.e I'm concerned that package_name= might actually be interpreted as "not set"/"no package name filter" instead of "searching for empty package name", and you actually do get something. That's how most web services work?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, for package_name= you get all the packages and then basically a random APK_PKG_ID and therefore sha256sum. This hinges on APK_VERSION being empty, though, which will trigger the first check in the fallback check.

Comment thread action.yaml
APK_TOOLS_API="https://gitlab.alpinelinux.org/api/v4/projects/5"
APK_VERSION=$(curl -fsSL --retry 5 --retry-all-errors "${APK_TOOLS_API}/repository/tags?per_page=1" | jq -r '.[].name' | sort -V | tail -1)
APK_PKG_ID=$(curl -fsSL --retry 5 --retry-all-errors "${APK_TOOLS_API}/packages?package_name=${APK_VERSION}&package_type=generic" | jq '.[] | select(.version == "x86_64") | .id' | sort | tail -1)
APK_SHA256=$(curl -fsSL --retry 5 --retry-all-errors "${APK_TOOLS_API}/packages/${APK_PKG_ID}/package_files" | jq -r '.[0].file_sha256')

@martinpitt martinpitt Jun 26, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An absent .file_sha256 gets rendered as string "null", failing the [ -z ] check below. jq has an // empty guard for that.

Also, is it safe to blindly take the first ([0]) file? I suppose good enough if they only ever publish one file.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope that should be safe, since it's only a single package ID.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went for adding another check for APK_SHA256 being the actual string null. Unlikely, but then it'll cover the key not being there and the value being empty.

Comment thread action.yaml Outdated
sudo curl -fsSL -o /usr/bin/apk https://gitlab.alpinelinux.org/api/v4/projects/5/packages/generic/v3.0.6/x86_64/apk.static
echo 'f1489e05bace7d7dd0a687fcd38d50b585ac660af4231668b123649bef3718c4 /usr/bin/apk' | sha256sum --check
APK_TOOLS_API="https://gitlab.alpinelinux.org/api/v4/projects/5"
APK_VERSION=$(curl -fsSL --retry 5 --retry-all-errors "${APK_TOOLS_API}/repository/tags?per_page=1" | jq -r '.[].name' | sort -V | tail -1)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This gets the most recent tag, not the highest version. I.e. if "2.0.2" is the current highest version, and someone pushes an "1.0.3" maintenance update, the latter will the be most recent tag.

Also, the tail -1 should be redundant with per_page=1?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, the per_page=1 actually still needed to go. Getting the latest version is done by sort -V. I've also added a filter to get out the rc tags.

Comment thread action.yaml Outdated
This uses the gitlab API to fetch the latest release of apk from the
upstream apk-tools repo, instead of hardcoding a version.

Since gitlab API can be flaky, I put it in a retry loop. set -x in a
subshell in the loop because you can never have too much info if/when
things break. I also made the whole thing non-fatal if it still fails
to get apk after retrying, because not all of them need apk (even if it
means other later jobs using apk might fail). I added a warning for that
situation so hopefully it makes it a bit more obvious why a later job
using apk might fail if that was the case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants