Skip to content

Commit ce52756

Browse files
committed
Regoranized and centralized functions
1 parent 05d01df commit ce52756

File tree

7 files changed

+415
-127
lines changed

7 files changed

+415
-127
lines changed

lib/actions/base64.sh

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,6 @@ action_base64() {
99
local action=$1
1010
local input=$2
1111

12-
if [[ "$(uname -s)" == "Darwin" ]]; then
13-
local base64_encode_cmd="base64 -i"
14-
local base64_decode_cmd="base64 -D"
15-
else
16-
local base64_encode_cmd="base64"
17-
local base64_decode_cmd="base64 -d"
18-
fi
19-
2012
case "$action" in
2113
encode | -e)
2214
# Check if the file exists for encoding
@@ -25,16 +17,16 @@ action_base64() {
2517
return 1
2618
fi
2719
# Encode the file with base64
28-
$base64_encode_cmd "$input"
20+
base64_encode "$input"
2921
;;
3022
decode | -d)
3123
# Decode the input
3224
if [ -f "$input" ]; then
3325
# If it's a file, decode the file contents
34-
cat "$input" | $base64_decode_cmd
26+
base64_decode - < "$input"
3527
else
3628
# If it's not a file, assume it's a base64 string and try to decode it
37-
echo "$input" | $base64_decode_cmd 2>/dev/null
29+
echo "$input" | base64_decode - 2>/dev/null
3830
if [ $? -ne 0 ]; then
3931
echo "Error: Input is not a valid base64 string."
4032
return 1

lib/actions/configure.sh

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
#!/usr/bin/env bash
2+
3+
#################################
4+
# Main Action Handler
5+
#################################
6+
action_configure() {
7+
case "$1" in
8+
gha)
9+
shift
10+
configure_gha "$@"
11+
;;
12+
*)
13+
show_usage "$1"
14+
exit 1
15+
;;
16+
esac
17+
18+
}
19+
20+
#################################
21+
# Helper Functions
22+
#################################
23+
configure_gha() {
24+
if [ $# -eq 0 ]; then
25+
echo "${BOLD}${RED}❌ No environment specified${RESET}"
26+
echo "Usage: spin configure gha <environment>"
27+
echo "Example: spin configure gha production"
28+
return 1
29+
fi
30+
31+
local gha_environment="$1"
32+
shift # Remove the first argument
33+
local gha_environment_uppercase=$(echo "$gha_environment" | tr '[:lower:]' '[:upper:]')
34+
35+
validate_repository_setup || exit 1
36+
37+
local environment_file
38+
environment_file=$(validate_environment_file "$gha_environment") || exit 1
39+
40+
gh_set_env --base64 --variable "${gha_environment_uppercase}_ENV_FILE_BASE64" --file "$environment_file"
41+
42+
configure_gha_deployment_key "$@"
43+
configure_gha_authorized_keys
44+
45+
}
46+
47+
configure_gha_deployment_key() {
48+
local inventory_file="${SPIN_INVENTORY_FILE:-"/etc/ansible/collections/ansible_collections/serversideup/spin/plugins/inventory/spin-dynamic-inventory.sh"}"
49+
local infrastructure_folder=".infrastructure"
50+
51+
if [ ! -d "$infrastructure_folder" ]; then
52+
echo "${BOLD}${RED}❌ Infrastructure folder not found${RESET}"
53+
echo "Please ensure you're in the root of your project."
54+
return 1
55+
fi
56+
57+
if [ ! -d "$infrastructure_folder/deploy-keys" ] || [ ! -f "$infrastructure_folder/deploy-keys/.gitignore" ]; then
58+
mkdir -p "$infrastructure_folder/deploy-keys"
59+
echo "*" > "$infrastructure_folder/deploy-keys/.gitignore"
60+
echo "!.gitignore" >> "$infrastructure_folder/deploy-keys/.gitignore"
61+
fi
62+
63+
if [ ! -f "$infrastructure_folder/deploy-keys/id_ed25519_deploy" ]; then
64+
echo "🔑 Generating deployment key"
65+
ssh-keygen -t ed25519 -C "deploy-key" -f "$infrastructure_folder/deploy-keys/id_ed25519_deploy" -N ""
66+
echo "${BOLD}${GREEN}✅ Deployment key generated${RESET}"
67+
else
68+
echo "🔑 Using existing deployment key found at \"$infrastructure_folder/deploy-keys/id_ed25519_deploy\""
69+
fi
70+
71+
# Read the public key content
72+
local deploy_public_key
73+
deploy_public_key=$(cat "$infrastructure_folder/deploy-keys/id_ed25519_deploy.pub")
74+
75+
echo "🔑 Adding deployment key to GitHub repository"
76+
gh_set_env --variable "SSH_DEPLOY_PRIVATE_KEY" --file "$infrastructure_folder/deploy-keys/id_ed25519_deploy"
77+
78+
echo "🔐 Adding deployment key to servers"
79+
prepare_ansible_args "$@"
80+
run_ansible --allow-ssh --mount-path "$(pwd)" \
81+
ansible-playbook serversideup.spin.update_deploy_key \
82+
--inventory "$inventory_file" \
83+
--extra-vars @./.spin.yml \
84+
--extra-vars "deploy_public_key='$deploy_public_key'" \
85+
"${SPIN_ANSIBLE_ARGS[@]}" \
86+
"${SPIN_UNPROCESSED_ARGS[@]}"
87+
88+
echo "${BOLD}${GREEN}✅ Deployment key added to servers${RESET}"
89+
}
90+
91+
configure_gha_authorized_keys() {
92+
echo "🔑 Gathering authorized keys for sudo users"
93+
local authorized_keys
94+
authorized_keys=$(run_ansible --minimal-output --mount-path "$(pwd)" \
95+
ansible-playbook serversideup.spin.get_sudo_keys \
96+
--extra-vars @./.spin.yml \
97+
| sed -n 's/.*"msg": "\(.*\)".*/\1/p' \
98+
| sed 's/\\\\n/\n/g') # Handle the double escaped newlines
99+
100+
echo "🔑 Adding authorized keys to GitHub repository"
101+
echo "$authorized_keys"
102+
103+
# Add the authorized keys to GitHub secrets
104+
gh_set_env --variable "AUTHORIZED_KEYS" --value "$authorized_keys"
105+
106+
}
107+
108+
gh_set_env() {
109+
local base64_encode=false
110+
local variable=""
111+
local file=""
112+
local value=""
113+
114+
# Parse arguments
115+
while [[ "$#" -gt 0 ]]; do
116+
case "$1" in
117+
--base64)
118+
base64_encode=true
119+
shift
120+
;;
121+
--variable)
122+
variable="$2"
123+
shift 2
124+
;;
125+
--file)
126+
file="$2"
127+
shift 2
128+
;;
129+
--value)
130+
value="$2"
131+
shift 2
132+
;;
133+
*)
134+
echo "${BOLD}${RED}❌ Invalid argument: $1${RESET}"
135+
return 1
136+
;;
137+
esac
138+
done
139+
140+
# Validate required arguments
141+
if [ -z "$variable" ] || { [ -z "$file" ] && [ -z "$value" ]; }; then
142+
echo "${BOLD}${RED}❌ Missing required arguments. Need --variable and either --file or --value.${RESET}"
143+
return 1
144+
fi
145+
146+
if [ -n "$file" ] && [ -n "$value" ]; then
147+
echo "${BOLD}${RED}❌ Cannot specify both --file and --value.${RESET}"
148+
return 1
149+
fi
150+
151+
# Get content from either file or value
152+
local content
153+
if [ -n "$file" ]; then
154+
if [ "$base64_encode" = true ]; then
155+
content=$(base64_encode "$file")
156+
else
157+
content=$(<"$file")
158+
fi
159+
else
160+
if [ "$base64_encode" = true ]; then
161+
content=$(echo -n "$value" | base64_encode -)
162+
else
163+
content="$value"
164+
fi
165+
fi
166+
167+
# Set the secret using the gh CLI
168+
echo "$content" | run_gh secret set "$variable"
169+
170+
echo "${BOLD}${GREEN}✅ Successfully set $variable secret for GitHub Actions${RESET}"
171+
}
172+
173+
is_gh_cli_authenticated() {
174+
run_gh auth status >/dev/null 2>&1
175+
}
176+
177+
is_github_repository() {
178+
run_gh repo view --json name >/dev/null 2>&1
179+
}
180+
181+
show_usage() {
182+
echo "${BOLD}${RED}❌ Invalid command: $1${RESET}"
183+
echo
184+
echo "Usage: spin configure <command>"
185+
echo
186+
echo "Commands:"
187+
echo " gha <environment> Configure GitHub Actions settings for specified environment"
188+
}
189+
190+
repository_exists() {
191+
git rev-parse --is-inside-work-tree >/dev/null 2>&1
192+
}
193+
194+
validate_environment_file() {
195+
local gha_environment="$1"
196+
local env_file=".env.$gha_environment"
197+
198+
if [ -f "$env_file" ]; then
199+
echo "$env_file" # Return the path if file exists
200+
return 0
201+
else
202+
echo "${BOLD}${RED}❌ Environment file not found ($env_file)${RESET}" >&2
203+
echo "Please ensure you have an environment variable file for the \"$gha_environment\" environment." >&2
204+
echo "Create a file called $env_file and add your environment variables to it." >&2
205+
echo "You can also change the environment by running \`spin configure gha <environment>\`." >&2
206+
return 1
207+
fi
208+
}
209+
210+
validate_repository_setup() {
211+
if ! repository_exists; then
212+
echo "${BOLD}${RED}❌ Repository not detected.${RESET}"
213+
echo "Please ensure you're in the root of your project. If you need to create a repository, run \`git init\` then \`spin gh repo create\` to create one."
214+
return 1
215+
fi
216+
217+
if ! is_gh_cli_authenticated; then
218+
echo "${BOLD}${RED}❌ GitHub CLI is not authenticated${RESET}"
219+
echo
220+
echo "Please authenticate with GitHub CLI by running \`spin gh auth login\`"
221+
return 1
222+
fi
223+
224+
if ! is_github_repository; then
225+
echo "${BOLD}${RED}❌ Repository is not connected to GitHub.${RESET}"
226+
echo "This project must be connected to a GitHub repository to use GitHub Actions."
227+
echo "Add a GitHub remote or run \`spin gh repo create\` to create a GitHub repository."
228+
return 1
229+
fi
230+
231+
return 0
232+
}

lib/actions/gh.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/usr/bin/env bash
2+
action_gh() {
3+
# Run GH CLI via Docker
4+
run_gh "$@"
5+
}

lib/actions/init.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ action_init() {
4646
".github" \
4747
".git" \
4848
".infrastructure" \
49+
"!.infrastructure/**/local-ca.pem" \
4950
"Dockerfile" \
5051
"docker-*.yml" \
5152
".gitlab-ci.yml" \

lib/actions/maintain.sh

Lines changed: 3 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,13 @@
11
#!/usr/bin/env bash
22
action_maintain(){
3-
additional_ansible_args=()
4-
spin_remote_user="$USER" # Default to the current user who runs the command
5-
force_ansible_upgrade=false
6-
unprocessed_args=()
73
local inventory_file="${SPIN_INVENTORY_FILE:-"/etc/ansible/collections/ansible_collections/serversideup/spin/plugins/inventory/spin-dynamic-inventory.sh"}"
84

9-
# Process arguments
10-
while [[ "$#" -gt 0 ]]; do
11-
case "$1" in
12-
--host|-h)
13-
additional_ansible_args+=("--extra-vars" "target=$2")
14-
shift 2
15-
;;
16-
--user|-u)
17-
spin_remote_user="$2" # Override default user with specified user
18-
shift 2
19-
;;
20-
--port|-p)
21-
additional_ansible_args+=("--extra-vars" "ansible_port=$2")
22-
shift 2
23-
;;
24-
--upgrade|-U)
25-
force_ansible_upgrade=true
26-
shift
27-
;;
28-
*)
29-
unprocessed_args+=("$1")
30-
shift
31-
;;
32-
esac
33-
done
5+
prepare_ansible_args "$@"
346

35-
echo "Starting Ansible..."
36-
# Check if the Docker image exists and pull if it doesn't
37-
if ! docker image inspect "${SPIN_ANSIBLE_IMAGE}" &> /dev/null; then
38-
echo "Docker image ${SPIN_ANSIBLE_IMAGE} not found. Pulling..."
39-
docker pull "${SPIN_ANSIBLE_IMAGE}"
40-
fi
41-
42-
# Set Ansible User
43-
additional_ansible_args+=("--extra-vars" "spin_remote_user=$spin_remote_user")
44-
local use_passwordless_sudo
45-
if ! use_passwordless_sudo=$(get_ansible_variable "use_passwordless_sudo"); then
46-
echo "${BOLD}${RED}❌ Error: Failed to get ansible variable.${RESET}" >&2
47-
exit 1
48-
fi
49-
use_passwordless_sudo=${use_passwordless_sudo:-"false"}
50-
if [ "$spin_remote_user" != "root" ] && [ "$use_passwordless_sudo" = 'false' ]; then
51-
additional_ansible_args+=("--ask-become-pass")
52-
fi
53-
54-
# Append vault args to additional ansible args
55-
IFS=' ' read -r -a vault_args < <(set_ansible_vault_args)
56-
additional_ansible_args+=("${vault_args[@]}")
57-
58-
check_galaxy_pull "$force_ansible_upgrade"
597
run_ansible --allow-ssh --mount-path "$(pwd)" \
608
ansible-playbook serversideup.spin.maintain \
619
--inventory "$inventory_file" \
6210
--extra-vars @./.spin.yml \
63-
"${additional_ansible_args[@]}" \
64-
"${unprocessed_args[@]}"
11+
"${SPIN_ANSIBLE_ARGS[@]}" \
12+
"${SPIN_UNPROCESSED_ARGS[@]}"
6513
}

0 commit comments

Comments
 (0)