Skip to content

Commit b104264

Browse files
committed
chore(dc-init): update workflows,actions
1 parent d69d23c commit b104264

12 files changed

Lines changed: 3365 additions & 46 deletions

File tree

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

0 commit comments

Comments
 (0)