-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathaction.yml
More file actions
119 lines (102 loc) · 4.22 KB
/
Copy pathaction.yml
File metadata and controls
119 lines (102 loc) · 4.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
name: Mirror to Git Forge
description: >
Push all branches and tags from the current working directory to a remote
git forge. Supports HTTPS (token) and SSH (private key) authentication.
Call after actions/checkout with fetch-depth: 0.
inputs:
destination:
description: >
Remote URL to push to. HTTPS (https://host/org/repo.git) uses token
auth; SCP-style SSH (git@host:org/repo) or ssh:// uses key auth.
Scheme is auto-detected. DO NOT EMBED CREDENTIALS in this URL.
required: true
token:
description: >
OAuth2 or personal access token for HTTPS destinations. Injected into
the URL as the password; never echoed or stored in git config.
required: false
default: ''
token_username:
description: >
Username injected into the HTTPS URL alongside the token. Default
"oauth2" works for GitLab. Use the actual account username for
Gitea, Forgejo, and Codeberg.
required: false
default: 'oauth2'
ssh_private_key:
description: >
PEM private key (ED25519 or RSA) for SSH destinations. Written to a
temporary file in RUNNER_TEMP with mode 0600 and deleted after the push.
required: false
default: ''
ssh_known_hosts:
description: >
Known-hosts entries for the destination host (output of ssh-keyscan).
Strongly recommended; omitting this falls back to ssh-keyscan at push
time, which does not verify host identity (TOFU).
required: false
default: ''
runs:
using: composite
steps:
- name: Mirror push
shell: bash
run: |
set -euo pipefail
DEST="${{ inputs.destination }}"
if [[ "$DEST" == https://* ]]; then
TOKEN="${{ inputs.token }}"
USERNAME="${{ inputs.token_username }}"
if [[ -z "$TOKEN" ]]; then
echo "::error::inputs.token is required for HTTPS destinations"
exit 1
fi
REST="${DEST#https://}"
if [[ "$REST" == *@* ]]; then
echo "::error::inputs.destination must not contain embedded credentials"
exit 1
fi
AUTH_URL="https://${USERNAME}:${TOKEN}@${REST}"
git remote remove _mirror_dest 2>/dev/null || true
git remote add _mirror_dest "$AUTH_URL"
git push --force --prune _mirror_dest \
+refs/heads/*:refs/heads/* \
+refs/tags/*:refs/tags/*
git remote remove _mirror_dest
elif [[ "$DEST" == git@* || "$DEST" == ssh://* ]]; then
KEY="${{ inputs.ssh_private_key }}"
KNOWN_HOSTS_INPUT="${{ inputs.ssh_known_hosts }}"
if [[ -z "$KEY" ]]; then
echo "::error::inputs.ssh_private_key is required for SSH destinations"
exit 1
fi
KEY_FILE="${RUNNER_TEMP}/mirror_ssh_key_$$"
KH_FILE="${RUNNER_TEMP}/mirror_known_hosts_$$"
# printf preserves the trailing newline that SSH private key files require
printf '%s\n' "$KEY" > "$KEY_FILE"
chmod 600 "$KEY_FILE"
if [[ -n "$KNOWN_HOSTS_INPUT" ]]; then
printf '%s\n' "$KNOWN_HOSTS_INPUT" > "$KH_FILE"
else
echo "::warning::ssh_known_hosts not provided; using ssh-keyscan (TOFU — host identity not verified)"
HOST=$(printf '%s' "$DEST" | sed 's|.*@||; s|[:/].*||')
ssh-keyscan -t ed25519,rsa,ecdsa "$HOST" > "$KH_FILE" 2>/dev/null
if [[ ! -s "$KH_FILE" ]]; then
echo "::error::ssh-keyscan returned no results for $HOST"
rm -f "$KEY_FILE" "$KH_FILE"
exit 1
fi
fi
export GIT_SSH_COMMAND="ssh -i $KEY_FILE -o UserKnownHostsFile=$KH_FILE -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes"
git remote remove _mirror_dest 2>/dev/null || true
git remote add _mirror_dest "$DEST"
git push --force --prune _mirror_dest \
+refs/heads/*:refs/heads/* \
+refs/tags/*:refs/tags/*
git remote remove _mirror_dest
rm -f "$KEY_FILE" "$KH_FILE"
else
echo "::error::Unrecognized URL scheme in destination: $DEST"
echo "::error::Use https:// for token auth or git@host:org/repo (or ssh://) for SSH auth."
exit 1
fi