Skip to content

Commit 8f77794

Browse files
committed
fix(arcane-deploy): address SSH auth PR review feedback
- Mask SSH private key line-by-line for multiline secret handling, since ::add-mask:: operates per-line in GitHub Actions - Default repository-url to SSH format (git@github.com:...) when auth-type is ssh, so users don't need to override it manually - Add comment documenting camelCase API field name convention (sshKey, sshHostKeyVerification) matching existing authType/token - Add security warning for accept_all host key verification in README - Remove explicit repository-url from SSH example (auto-derived now) https://claude.ai/code/session_019FKVbkxfTf8fyqdx7BzCFs
1 parent 844f5ed commit 8f77794

2 files changed

Lines changed: 37 additions & 22 deletions

File tree

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

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,10 @@ Deploy Docker Compose stacks to [Arcane](https://github.com/getarcaneapp/arcane)
5454
compose-dir: stacks
5555
auth-type: ssh
5656
ssh-private-key: ${{ secrets.DEPLOY_KEY }}
57-
repository-url: git@github.com:myorg/myrepo.git
5857
```
5958
59+
> **Note:** When `auth-type: ssh`, the `repository-url` defaults to the SSH format (`git@github.com:owner/repo.git`) automatically. You can override it with `repository-url` if needed.
60+
6061
**With workflow environment variables** (available to subsequent steps, not inside containers):
6162

6263
```yaml
@@ -76,25 +77,25 @@ Deploy Docker Compose stacks to [Arcane](https://github.com/getarcaneapp/arcane)
7677

7778
## Inputs
7879

79-
| Input | Required | Default | Description |
80-
| --------------------------- | -------- | --------------------- | ------------------------------------------------------------------------------- |
81-
| `arcane-url` | Yes | | Base URL of the Arcane instance (must use HTTPS) |
82-
| `arcane-api-key` | Yes | | API key (from Arcane Settings > API Keys) |
83-
| `environment-id` | Yes | | Arcane environment ID |
84-
| `compose-dir` | No | | Directory to scan for compose files (up to 2 levels deep) |
85-
| `compose-files` | No | | Newline-separated list of compose file paths |
86-
| `repository-url` | No | GitHub repo HTTPS URL | Git URL for Arcane to clone |
87-
| `repository-name` | No | GitHub repo name | Display name in Arcane |
88-
| `branch` | No | Triggering branch | Branch to sync from |
89-
| `auth-type` | No | `http` | Git auth type: `none`, `http`, or `ssh` |
90-
| `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`. |
93-
| `auto-sync` | No | `true` | Enable Arcane auto-sync polling |
94-
| `sync-interval` | No | `5` | Minutes between auto-sync polls |
95-
| `trigger-sync` | No | `true` | Trigger immediate sync after create/update |
96-
| `sync-name-prefix` | No | GitHub repo name | Prefix for sync names in Arcane |
97-
| `env-vars` | No | | Runner env vars (`KEY=VALUE` per line) for subsequent steps. Values are masked. |
80+
| Input | Required | Default | Description |
81+
| --------------------------- | -------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
82+
| `arcane-url` | Yes | | Base URL of the Arcane instance (must use HTTPS) |
83+
| `arcane-api-key` | Yes | | API key (from Arcane Settings > API Keys) |
84+
| `environment-id` | Yes | | Arcane environment ID |
85+
| `compose-dir` | No | | Directory to scan for compose files (up to 2 levels deep) |
86+
| `compose-files` | No | | Newline-separated list of compose file paths |
87+
| `repository-url` | No | GitHub repo HTTPS URL | Git URL for Arcane to clone. Defaults to SSH format when auth-type=ssh. |
88+
| `repository-name` | No | GitHub repo name | Display name in Arcane |
89+
| `branch` | No | Triggering branch | Branch to sync from |
90+
| `auth-type` | No | `http` | Git auth type: `none`, `http`, or `ssh` |
91+
| `git-token` | No | | Token for HTTP git auth. Required when auth-type=http. |
92+
| `ssh-private-key` | No | | SSH private key for git auth (e.g. deploy key). Required when auth-type=ssh. |
93+
| `ssh-host-key-verification` | No | `accept_new` | SSH host key verification mode: `accept_new`, `accept_all`, or `reject`. **Warning:** `accept_all` disables host key checking and should only be used for testing. |
94+
| `auto-sync` | No | `true` | Enable Arcane auto-sync polling |
95+
| `sync-interval` | No | `5` | Minutes between auto-sync polls |
96+
| `trigger-sync` | No | `true` | Trigger immediate sync after create/update |
97+
| `sync-name-prefix` | No | GitHub repo name | Prefix for sync names in Arcane |
98+
| `env-vars` | No | | Runner env vars (`KEY=VALUE` per line) for subsequent steps. Values are masked. |
9899

99100
## Outputs
100101

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@ API_KEY="${INPUT_ARCANE_API_KEY}"
77
ENV_ID="${INPUT_ENVIRONMENT_ID}"
88
COMPOSE_DIR="${INPUT_COMPOSE_DIR:-}"
99
COMPOSE_FILES_INPUT="${INPUT_COMPOSE_FILES:-}"
10-
REPO_URL="${INPUT_REPOSITORY_URL:-https://github.com/${GITHUB_REPOSITORY}.git}"
10+
# Default to SSH URL format when auth-type is ssh, HTTPS otherwise
11+
if [[ -z "${INPUT_REPOSITORY_URL:-}" && "${INPUT_AUTH_TYPE:-http}" == "ssh" ]]; then
12+
REPO_URL="git@github.com:${GITHUB_REPOSITORY}.git"
13+
else
14+
REPO_URL="${INPUT_REPOSITORY_URL:-https://github.com/${GITHUB_REPOSITORY}.git}"
15+
fi
1116
REPO_NAME="${INPUT_REPOSITORY_NAME:-${GITHUB_REPOSITORY##*/}}"
1217
BRANCH="${INPUT_BRANCH:-${GITHUB_REF_NAME:-main}}"
1318
AUTH_TYPE="${INPUT_AUTH_TYPE:-http}"
@@ -22,7 +27,14 @@ ENV_VARS="${INPUT_ENV_VARS:-}"
2227
# [C1/C2] Mask secrets immediately, before any logging or API calls
2328
[[ -n "${API_KEY}" ]] && echo "::add-mask::${API_KEY}"
2429
[[ -n "${GIT_TOKEN}" ]] && echo "::add-mask::${GIT_TOKEN}"
25-
[[ -n "${SSH_PRIVATE_KEY}" ]] && echo "::add-mask::${SSH_PRIVATE_KEY}"
30+
# SSH private keys are multiline; ::add-mask:: works per-line, so mask each line
31+
# to prevent any part of the key from appearing in logs.
32+
if [[ -n "${SSH_PRIVATE_KEY}" ]]; then
33+
echo "::add-mask::${SSH_PRIVATE_KEY}"
34+
while IFS= read -r _line; do
35+
[[ -n "${_line}" ]] && echo "::add-mask::${_line}"
36+
done <<< "${SSH_PRIVATE_KEY}"
37+
fi
2638

2739
SYNCS_CREATED=0
2840
SYNCS_UPDATED=0
@@ -210,6 +222,8 @@ ensure_repository() {
210222
-d "${update_payload}" > /dev/null
211223
log_info "Updated repository credentials"
212224
elif [[ "${AUTH_TYPE}" == "ssh" && -n "${SSH_PRIVATE_KEY}" ]]; then
225+
# Arcane API field names use camelCase (matching existing authType/token convention).
226+
# Backend model: ssh_key -> sshKey, ssh_host_key_verification -> sshHostKeyVerification
213227
local update_payload
214228
update_payload=$(jq -n \
215229
--arg sshKey "${SSH_PRIVATE_KEY}" \

0 commit comments

Comments
 (0)