Skip to content

Commit 09d8e58

Browse files
committed
chore(dc-init): update workflows and actions
1 parent cd38d20 commit 09d8e58

File tree

13 files changed

+3619
-1
lines changed

13 files changed

+3619
-1
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
name: Bot Setup
2+
description: >
3+
Register the machine user GPG key to their GitHub profile, import and configure it
4+
for signed commits/tags, and set global git identity.
5+
All inputs are optional — steps degrade gracefully when secrets are absent.
6+
7+
inputs:
8+
gpg-private-key:
9+
description: Armored GPG private key (secrets.BOT_GPG_PRIVATE_KEY)
10+
required: false
11+
default: ''
12+
gpg-passphrase:
13+
description: GPG key passphrase (secrets.BOT_GPG_PASSPHRASE)
14+
required: false
15+
default: ''
16+
user-token:
17+
description: >
18+
Classic PAT with write:gpg_key scope (secrets.BOT_USER_TOKEN).
19+
Required to register the public key to the machine user's GitHub profile —
20+
installation tokens cannot call POST /user/gpg_keys.
21+
required: false
22+
default: ''
23+
bot-name:
24+
description: Git display name for commits and tags (vars.BOT_NAME)
25+
required: false
26+
default: 'xaos-bot'
27+
bot-email:
28+
description: Bot GitHub noreply email (e.g., 12345+bot@users.noreply.github.com)
29+
required: false
30+
default: '262248812+xaos-bot@users.noreply.github.com'
31+
32+
outputs:
33+
gpg-outcome:
34+
description: Result of GPG key import — success, skipped, or failure
35+
value: ${{ steps.import.outputs.outcome }}
36+
37+
runs:
38+
using: composite
39+
steps:
40+
- name: Register GPG key to bot GitHub profile
41+
shell: bash
42+
env:
43+
GPG_PRIVATE_KEY: ${{ inputs.gpg-private-key }}
44+
GPG_PASSPHRASE: ${{ inputs.gpg-passphrase }}
45+
USER_TOKEN: ${{ inputs.user-token }}
46+
BOT_NAME: ${{ inputs.bot-name }}
47+
BOT_EMAIL: ${{ inputs.bot-email }}
48+
run: |
49+
[[ -z "$GPG_PRIVATE_KEY" ]] && exit 0
50+
echo "$GPG_PRIVATE_KEY" | gpg --batch --import --quiet 2>/dev/null || true
51+
FINGERPRINT=$(gpg --batch --with-colons --list-secret-keys 2>/dev/null | grep '^fpr' | head -1 | cut -d: -f10)
52+
[[ -z "$FINGERPRINT" ]] && exit 0
53+
# Add machine user noreply email as a UID for GitHub signature verification
54+
if [[ -n "$GPG_PASSPHRASE" ]]; then
55+
if ! gpg --list-keys 2>/dev/null | grep -qF "$BOT_EMAIL"; then
56+
printf '%s' "$GPG_PASSPHRASE" | gpg --batch --pinentry-mode loopback --passphrase-fd 0 \
57+
--quick-add-uid "$FINGERPRINT" "${BOT_NAME} <${BOT_EMAIL}>" 2>/dev/null || true
58+
fi
59+
fi
60+
KEY_ID=$(gpg --list-secret-keys --keyid-format=long 2>/dev/null | grep -oE '[0-9A-F]{16}' | head -1)
61+
[[ -z "$KEY_ID" ]] && exit 0
62+
GPG_PUBLIC_KEY=$(gpg --armor --export "$KEY_ID" 2>/dev/null || true)
63+
[[ -z "$GPG_PUBLIC_KEY" ]] && exit 0
64+
if [[ -z "$USER_TOKEN" ]]; then
65+
echo "⚠️ user-token not set — skipping GPG key registration to GitHub profile"
66+
echo "ℹ️ Add a classic PAT (write:gpg_key scope) to enable 'Verified' tags"
67+
exit 0
68+
fi
69+
ALREADY=$(GH_TOKEN="$USER_TOKEN" gh api /user/gpg_keys \
70+
--jq ".[] | select(.key_id == \"$KEY_ID\") | .id" 2>/dev/null || true)
71+
if [[ "$ALREADY" =~ ^[0-9]+$ ]]; then
72+
echo "✅ GPG key already registered (id: $ALREADY) — skipping"
73+
exit 0
74+
fi
75+
RESULT=$(GH_TOKEN="$USER_TOKEN" gh api /user/gpg_keys \
76+
--method POST -f armored_public_key="$GPG_PUBLIC_KEY" --jq '.id' 2>/dev/null) || RESULT=""
77+
if [[ "$RESULT" =~ ^[0-9]+$ ]]; then
78+
echo "✅ GPG public key registered (id: $RESULT)"
79+
else
80+
echo "⚠️ GPG key registration failed: $RESULT"
81+
echo "ℹ️ Ensure user-token is a classic PAT with write:gpg_key scope"
82+
fi
83+
84+
- name: Import GPG key and configure signing
85+
id: import
86+
shell: bash
87+
env:
88+
GPG_PRIVATE_KEY: ${{ inputs.gpg-private-key }}
89+
GPG_PASSPHRASE: ${{ inputs.gpg-passphrase }}
90+
BOT_NAME: ${{ inputs.bot-name }}
91+
BOT_EMAIL: ${{ inputs.bot-email }}
92+
run: |
93+
if [[ -z "$GPG_PRIVATE_KEY" ]]; then
94+
echo "⚠️ GPG key not provided — skipping import, tags will be unsigned"
95+
echo "outcome=skipped" >> "$GITHUB_OUTPUT"
96+
exit 0
97+
fi
98+
mkdir -p ~/.gnupg && chmod 700 ~/.gnupg
99+
printf 'default-cache-ttl 21600\nmax-cache-ttl 31536000\nallow-preset-passphrase\n' > ~/.gnupg/gpg-agent.conf
100+
gpg-connect-agent 'RELOADAGENT' /bye 2>/dev/null || gpgconf --kill gpg-agent 2>/dev/null || true
101+
echo "$GPG_PRIVATE_KEY" | gpg --batch --import --quiet 2>/dev/null || true
102+
FINGERPRINT=$(gpg --batch --with-colons --list-secret-keys 2>/dev/null | grep '^fpr' | head -1 | cut -d: -f10)
103+
if [[ -z "$FINGERPRINT" ]]; then
104+
echo "❌ Failed to import GPG key"
105+
echo "outcome=failure" >> "$GITHUB_OUTPUT"
106+
exit 0
107+
fi
108+
KEYGRIPS=$(gpg --batch --with-colons --with-keygrip --list-secret-keys "$FINGERPRINT" 2>/dev/null | grep '^grp' | cut -d: -f10)
109+
HEX_PASSPHRASE=$(printf '%s' "$GPG_PASSPHRASE" | xxd -p -u | tr -d '\n')
110+
while IFS= read -r KEYGRIP; do
111+
[[ -z "$KEYGRIP" ]] && continue
112+
gpg-connect-agent "PRESET_PASSPHRASE $KEYGRIP -1 $HEX_PASSPHRASE" /bye 2>/dev/null || true
113+
done <<< "$KEYGRIPS"
114+
if ! gpg --list-keys 2>/dev/null | grep -qF "$BOT_EMAIL"; then
115+
gpg --batch --quick-add-uid "$FINGERPRINT" "${BOT_NAME} <${BOT_EMAIL}>" 2>/dev/null || true
116+
fi
117+
KEY_ID=$(gpg --list-secret-keys --keyid-format=long 2>/dev/null | grep -oE '[0-9A-F]{16}' | head -1)
118+
if [[ -z "$KEY_ID" ]]; then
119+
echo "outcome=failure" >> "$GITHUB_OUTPUT"
120+
exit 0
121+
fi
122+
git config --global user.signingkey "$KEY_ID"
123+
git config --global commit.gpgsign true
124+
git config --global tag.gpgsign true
125+
echo "✅ GPG key imported and configured for signing (key: $KEY_ID)"
126+
echo "outcome=success" >> "$GITHUB_OUTPUT"
127+
128+
- name: Configure git identity
129+
shell: bash
130+
env:
131+
BOT_NAME: ${{ inputs.bot-name }}
132+
BOT_EMAIL: ${{ inputs.bot-email }}
133+
run: |
134+
git config --global user.name "${BOT_NAME}"
135+
git config --global user.email "${BOT_EMAIL}"
136+
echo "✅ Git identity configured: ${BOT_NAME} <${BOT_EMAIL}>"

0 commit comments

Comments
 (0)