Skip to content

Commit 4e45b77

Browse files
committed
feat(arcane-deploy): add SSH authentication support
Add auth-type: ssh alongside existing http and none options. New inputs: ssh-private-key (required for SSH) and ssh-host-key-verification (default: accept_new). When auth-type is ssh, the action passes sshKey, username ("git"), and sshHostKeyVerification to the Arcane git repository API for both create and credential-update flows. The SSH private key is masked in logs like other secrets. https://claude.ai/code/session_019FKVbkxfTf8fyqdx7BzCFs
1 parent c1b5f83 commit 4e45b77

3 files changed

Lines changed: 63 additions & 5 deletions

File tree

‎.github/actions/arcane-deploy/README.md‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,21 @@ Deploy Docker Compose stacks to [Arcane](https://github.com/getarcaneapp/arcane)
4242
git-token: ${{ secrets.REPO_TOKEN }}
4343
```
4444
45+
**SSH deploy key** — use a GitHub deploy key instead of a PAT:
46+
47+
```yaml
48+
- name: Deploy stacks to Arcane
49+
uses: nsheaps/github-actions/.github/actions/arcane-deploy@main
50+
with:
51+
arcane-url: ${{ secrets.ARCANE_URL }}
52+
arcane-api-key: ${{ secrets.ARCANE_API_KEY }}
53+
environment-id: '1'
54+
compose-dir: stacks
55+
auth-type: ssh
56+
ssh-private-key: ${{ secrets.DEPLOY_KEY }}
57+
repository-url: git@github.com:myorg/myrepo.git
58+
```
59+
4560
**With workflow environment variables** (available to subsequent steps, not inside containers):
4661
4762
```yaml
@@ -71,8 +86,10 @@ Deploy Docker Compose stacks to [Arcane](https://github.com/getarcaneapp/arcane)
7186
| `repository-url` | No | GitHub repo HTTPS URL | Git URL for Arcane to clone |
7287
| `repository-name` | No | GitHub repo name | Display name in Arcane |
7388
| `branch` | No | Triggering branch | Branch to sync from |
74-
| `auth-type` | No | `http` | Git auth type: `none` or `http` |
89+
| `auth-type` | No | `http` | Git auth type: `none`, `http`, or `ssh` |
7590
| `git-token` | No | | Token for HTTP git auth. Required when auth-type=http. |
91+
| `ssh-private-key` | No | | SSH private key for git auth (e.g. deploy key). Required when auth-type=ssh. |
92+
| `ssh-host-key-verification` | No | `accept_new` | SSH host key verification mode: `accept_new`, `accept_all`, or `reject`. |
7693
| `auto-sync` | No | `true` | Enable Arcane auto-sync polling |
7794
| `sync-interval` | No | `5` | Minutes between auto-sync polls |
7895
| `trigger-sync` | No | `true` | Trigger immediate sync after create/update |

‎.github/actions/arcane-deploy/action.sh‎

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ REPO_NAME="${INPUT_REPOSITORY_NAME:-${GITHUB_REPOSITORY##*/}}"
1212
BRANCH="${INPUT_BRANCH:-${GITHUB_REF_NAME:-main}}"
1313
AUTH_TYPE="${INPUT_AUTH_TYPE:-http}"
1414
GIT_TOKEN="${INPUT_GIT_TOKEN:-}"
15+
SSH_PRIVATE_KEY="${INPUT_SSH_PRIVATE_KEY:-}"
16+
SSH_HOST_KEY_VERIFICATION="${INPUT_SSH_HOST_KEY_VERIFICATION:-accept_new}"
1517
AUTO_SYNC="${INPUT_AUTO_SYNC:-true}"
1618
SYNC_INTERVAL="${INPUT_SYNC_INTERVAL:-5}"
1719
TRIGGER_SYNC="${INPUT_TRIGGER_SYNC:-true}"
@@ -20,6 +22,7 @@ ENV_VARS="${INPUT_ENV_VARS:-}"
2022
# [C1/C2] Mask secrets immediately, before any logging or API calls
2123
[[ -n "${API_KEY}" ]] && echo "::add-mask::${API_KEY}"
2224
[[ -n "${GIT_TOKEN}" ]] && echo "::add-mask::${GIT_TOKEN}"
25+
[[ -n "${SSH_PRIVATE_KEY}" ]] && echo "::add-mask::${SSH_PRIVATE_KEY}"
2326

2427
SYNCS_CREATED=0
2528
SYNCS_UPDATED=0
@@ -196,7 +199,7 @@ ensure_repository() {
196199
if [[ -n "${REPOSITORY_ID}" && "${REPOSITORY_ID}" != "null" ]]; then
197200
log_info "Found existing repository: ${REPOSITORY_ID}"
198201

199-
# Update credentials so the token stays current
202+
# Update credentials so they stay current
200203
if [[ "${AUTH_TYPE}" == "http" && -n "${GIT_TOKEN}" ]]; then
201204
local update_payload
202205
update_payload=$(jq -n \
@@ -206,6 +209,17 @@ ensure_repository() {
206209
arcane_api PUT "/customize/git-repositories/${REPOSITORY_ID}" \
207210
-d "${update_payload}" > /dev/null
208211
log_info "Updated repository credentials"
212+
elif [[ "${AUTH_TYPE}" == "ssh" && -n "${SSH_PRIVATE_KEY}" ]]; then
213+
local update_payload
214+
update_payload=$(jq -n \
215+
--arg sshKey "${SSH_PRIVATE_KEY}" \
216+
--arg username "git" \
217+
--arg sshHostKeyVerification "${SSH_HOST_KEY_VERIFICATION}" \
218+
'{sshKey: $sshKey, username: $username, sshHostKeyVerification: $sshHostKeyVerification}')
219+
220+
arcane_api PUT "/customize/git-repositories/${REPOSITORY_ID}" \
221+
-d "${update_payload}" > /dev/null
222+
log_info "Updated repository SSH credentials"
209223
fi
210224
else
211225
log_info "Creating new repository: ${REPO_NAME}"
@@ -218,6 +232,15 @@ ensure_repository() {
218232
--arg authType "${AUTH_TYPE}" \
219233
--arg token "${GIT_TOKEN}" \
220234
'{name: $name, url: $url, authType: $authType, token: $token}')
235+
elif [[ "${AUTH_TYPE}" == "ssh" ]]; then
236+
create_payload=$(jq -n \
237+
--arg name "${REPO_NAME}" \
238+
--arg url "${REPO_URL}" \
239+
--arg authType "${AUTH_TYPE}" \
240+
--arg sshKey "${SSH_PRIVATE_KEY}" \
241+
--arg username "git" \
242+
--arg sshHostKeyVerification "${SSH_HOST_KEY_VERIFICATION}" \
243+
'{name: $name, url: $url, authType: $authType, sshKey: $sshKey, username: $username, sshHostKeyVerification: $sshHostKeyVerification}')
221244
else
222245
create_payload=$(jq -n \
223246
--arg name "${REPO_NAME}" \
@@ -379,9 +402,15 @@ if [[ "${AUTH_TYPE}" == "http" && -z "${GIT_TOKEN}" ]]; then
379402
exit 1
380403
fi
381404

405+
# Validate ssh-private-key is set when auth-type is ssh
406+
if [[ "${AUTH_TYPE}" == "ssh" && -z "${SSH_PRIVATE_KEY}" ]]; then
407+
log_error "ssh-private-key is required when auth-type is ssh."
408+
exit 1
409+
fi
410+
382411
# [H4] Reject unsupported auth-type values
383-
if [[ "${AUTH_TYPE}" != "none" && "${AUTH_TYPE}" != "http" ]]; then
384-
log_error "auth-type '${AUTH_TYPE}' is not supported. Valid values: none, http."
412+
if [[ "${AUTH_TYPE}" != "none" && "${AUTH_TYPE}" != "http" && "${AUTH_TYPE}" != "ssh" ]]; then
413+
log_error "auth-type '${AUTH_TYPE}' is not supported. Valid values: none, http, ssh."
385414
exit 1
386415
fi
387416

‎.github/actions/arcane-deploy/action.yml‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ inputs:
4747
default: ''
4848

4949
auth-type:
50-
description: 'Git authentication type: none or http'
50+
description: 'Git authentication type: none, http, or ssh'
5151
required: false
5252
default: 'http'
5353

@@ -56,6 +56,16 @@ inputs:
5656
required: false
5757
default: ''
5858

59+
ssh-private-key:
60+
description: 'SSH private key for git authentication (e.g. a GitHub deploy key). Required when auth-type is ssh.'
61+
required: false
62+
default: ''
63+
64+
ssh-host-key-verification:
65+
description: 'SSH host key verification mode for Arcane. Valid values: accept_new, accept_all, reject.'
66+
required: false
67+
default: 'accept_new'
68+
5969
# Sync behavior
6070
auto-sync:
6171
description: 'Enable auto-sync polling in Arcane so it periodically pulls changes'
@@ -109,6 +119,8 @@ runs:
109119
INPUT_BRANCH: ${{ inputs.branch }}
110120
INPUT_AUTH_TYPE: ${{ inputs.auth-type }}
111121
INPUT_GIT_TOKEN: ${{ inputs.git-token }}
122+
INPUT_SSH_PRIVATE_KEY: ${{ inputs.ssh-private-key }}
123+
INPUT_SSH_HOST_KEY_VERIFICATION: ${{ inputs.ssh-host-key-verification }}
112124
INPUT_AUTO_SYNC: ${{ inputs.auto-sync }}
113125
INPUT_SYNC_INTERVAL: ${{ inputs.sync-interval }}
114126
INPUT_TRIGGER_SYNC: ${{ inputs.trigger-sync }}

0 commit comments

Comments
 (0)