From 3c3933d1cd5717962da4616959110c756ca39bf8 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Mon, 30 Jun 2025 21:38:00 +0200 Subject: [PATCH] chore(ci): add workflow to validate `gpg/` folders content (#36) --- .github/workflows/ci.yml | 43 +++++++++++++++++++++++++++++++++++++++ generate-gpg-dir.sh | 31 ++++++++++++++++++++++++++++ gpg/crls.d/DIR.txt | 1 - gpg/pubring.kbx | Bin 89464 -> 90184 bytes gpg/trustdb.gpg | Bin 1200 -> 1200 bytes 5 files changed, 74 insertions(+), 1 deletion(-) create mode 100755 generate-gpg-dir.sh delete mode 100644 gpg/crls.d/DIR.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3451b46..9160643 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,3 +60,46 @@ jobs: } done shell: bash # See https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference, we want the pipefail option. + + lint-pubring: + if: github.event.pull_request.draft == false + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 # We need 0 to validate the git commit signatures. + persist-credentials: false + + - name: Check if there are any keyring changes + id: keyring-changes + run: | + git diff --exit-code --quiet ${{ github.event_name == 'push' && github.event.before || 'HEAD^' }} -- gpg/ || echo "HAS_CHANGED=true" >> "$GITHUB_OUTPUT" + git diff --exit-code --quiet ${{ github.event_name == 'push' && github.event.before || 'HEAD^' }} -- gpg-only-active-keys/ || echo "HAS_ACTIVE_CHANGED=true" >> "$GITHUB_OUTPUT" + + - name: Export pubring content + run: | + for dir in gpg gpg-only-active-keys; do + gpg --no-default-keyring --keyring "$dir/pubring.kbx" --list-keys --with-colons > "$dir/all-keys.list" + gpg --no-default-keyring --keyring "$dir/pubring.kbx" --export --armor > "$dir/all-keys.asc" + git add "$dir/all-keys.list" "$dir/all-keys.asc" + done + - name: Re-generate gpg folders + run: | + ./generate-gpg-dir.sh + for dir in gpg gpg-only-active-keys; do + gpg --no-default-keyring --keyring "$dir/pubring.kbx" --list-keys --with-colons > "$dir/all-keys.list" + gpg --no-default-keyring --keyring "$dir/pubring.kbx" --export --armor > "$dir/all-keys.asc" + done + - run: git diff --exit-code -- gpg/all-keys.list gpg/all-keys.asc gpg-only-active-keys/all-keys.list gpg-only-active-keys/all-keys.asc + + - name: Validate that all non-v0.x releases can be verified using the keyring + if: steps.keyring-changes.outputs.HAS_CHANGED == 'true' + run: | + curl -fs https://nodejs.org/dist/index.json \ + | jq -er '.[].version | select(startswith("v0.") | not)' \ + | while read -r VERSION; do + echo "Checking $VERSION..." + curl -fs "https://nodejs.org/dist/${VERSION}/SHASUMS256.txt.asc" \ + | gpgv --keyring="gpg/pubring.kbx" + done + shell: bash # See https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference, we want the pipefail option. diff --git a/generate-gpg-dir.sh b/generate-gpg-dir.sh new file mode 100755 index 0000000..5511339 --- /dev/null +++ b/generate-gpg-dir.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +set -ex + +GNUPGHOME=${1:-"$(cd "$(dirname "$0")"; pwd)/gpg"} +ONLY_ACTIVE_KEYS=${2:-"$GNUPGHOME-only-active-keys"} + +if [ -d "$GNUPGHOME" ]; then + # If folder exists, move it to a temp dir + # Removing it could be dangerous + TRASH=$(mktemp -d) + mv "$GNUPGHOME" "$TRASH" +fi +if [ -d "$ONLY_ACTIVE_KEYS" ]; then + # If folder exists, move it to a temp dir + # Removing it could be dangerous + TRASH=$(mktemp -d) + mv "$ONLY_ACTIVE_KEYS" "$TRASH" +fi + +mkdir -p "$GNUPGHOME" + +awk -F'`' '/^$/,/^$/ {if($1 == " [") print substr($3, 3, length($3) - 3) }' README.md | while read -r KEY_PATH; do + GNUPGHOME="$GNUPGHOME" gpg --import "$KEY_PATH" +done + +cp -R "$GNUPGHOME" "$ONLY_ACTIVE_KEYS" + +awk -F'`' '/^$/,/^$/ {if($1 == " [") print substr($3, 3, length($3) - 3) }' README.md | while read -r KEY_PATH; do + GNUPGHOME="$GNUPGHOME" gpg --import "$KEY_PATH" +done diff --git a/gpg/crls.d/DIR.txt b/gpg/crls.d/DIR.txt deleted file mode 100644 index 2a29a47..0000000 --- a/gpg/crls.d/DIR.txt +++ /dev/null @@ -1 +0,0 @@ -v:1: diff --git a/gpg/pubring.kbx b/gpg/pubring.kbx index 9036f78d5d9dc69c14200e55c572f8e5c08bd4eb..c2cb7072caa599a9128ebc43c920dabb58709cfc 100644 GIT binary patch delta 4656 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 delta 28 jcmdnMxq(xFF})z2nVFH5k%@sJNh;K9qM`Uk^-dN5SRMu{