chore: add auto-import of GPG public key in devcontainer setup

This commit is contained in:
Denys Vuika
2026-07-07 15:03:02 +00:00
parent 8e69330110
commit 114de75e73
3 changed files with 109 additions and 0 deletions
+26
View File
@@ -88,6 +88,32 @@ git commit -S -m "your message" # -S optional if commit.gpgsign is true
git push
```
### Easiest rebuild-safe import flow
This devcontainer auto-imports a public key from `.git/signing.pub` on start.
If present, it runs `gpg --import .git/signing.pub` and removes the file after a
successful import.
So the easiest setup is:
```bash
# on the HOST, from repo root (auto-uses git user.signingkey)
./.devcontainer/export-signing-key.sh
# or pass a key explicitly
./.devcontainer/export-signing-key.sh <YOUR_KEY_ID>
```
The helper auto-selects `gpg2`/`gpg` based on where your key is visible, which
avoids host setups where the two binaries use different keyrings.
After **Rebuild Container** (or next container start), verify in the container:
```bash
gpg --list-secret-keys --keyid-format=long
git commit -S -m "test signed commit"
```
### Manually importing your public key
If `git commit -S` fails with `gpg: signing failed: No secret key`, the forwarded
+2
View File
@@ -55,5 +55,7 @@
"postCreateCommand": "pnpm install --frozen-lockfile",
"postStartCommand": "if [ -f .git/signing.pub ]; then gpg --import .git/signing.pub && rm .git/signing.pub; fi",
"runArgs": ["--cap-drop=ALL", "--security-opt=no-new-privileges:true", "--pids-limit=512"]
}
+81
View File
@@ -0,0 +1,81 @@
#!/usr/bin/env bash
set -euo pipefail
# Export your GPG public key to .git/signing.pub so the devcontainer can auto-import it.
# Usage:
# ./.devcontainer/export-signing-key.sh
# ./.devcontainer/export-signing-key.sh <KEY_ID>
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
OUTPUT_FILE="${REPO_ROOT}/.git/signing.pub"
KEY_ID="${1:-$(git config --global user.signingkey || true)}"
if [[ -z "${KEY_ID}" ]]; then
echo "No key ID provided and git user.signingkey is not set."
echo "Set it with: git config --global user.signingkey <YOUR_KEY_ID>"
echo "Or run: ./.devcontainer/export-signing-key.sh <YOUR_KEY_ID>"
exit 1
fi
available_bins=()
for candidate in gpg2 gpg; do
if command -v "${candidate}" >/dev/null 2>&1; then
available_bins+=("${candidate}")
fi
done
if [[ ${#available_bins[@]} -eq 0 ]]; then
echo "Neither gpg nor gpg2 is available on PATH."
exit 1
fi
has_secret_key() {
local bin="$1"
"${bin}" --list-secret-keys --with-colons "${KEY_ID}" 2>/dev/null | grep -q '^sec'
}
try_export() {
local bin="$1"
"${bin}" --armor --export "${KEY_ID}" > "${OUTPUT_FILE}"
[[ -s "${OUTPUT_FILE}" ]]
}
selected_bin=""
for bin in "${available_bins[@]}"; do
if has_secret_key "${bin}"; then
selected_bin="${bin}"
break
fi
done
if [[ -z "${selected_bin}" ]]; then
selected_bin="${available_bins[0]}"
fi
rm -f "${OUTPUT_FILE}"
if ! try_export "${selected_bin}"; then
for bin in "${available_bins[@]}"; do
if [[ "${bin}" == "${selected_bin}" ]]; then
continue
fi
if try_export "${bin}"; then
selected_bin="${bin}"
break
fi
done
fi
if [[ ! -s "${OUTPUT_FILE}" ]]; then
rm -f "${OUTPUT_FILE}"
echo "Failed to export public key for ${KEY_ID}."
echo "Tried binaries: ${available_bins[*]}"
echo "Check key visibility with:"
echo " gpg --list-secret-keys --keyid-format=long"
echo " gpg2 --list-secret-keys --keyid-format=long"
exit 1
fi
echo "Exported public key ${KEY_ID} to ${OUTPUT_FILE}"
echo "Using: ${selected_bin}"
echo "Rebuild/start the devcontainer to auto-import it."