Skip to content

Commit 438dcbd

Browse files
committed
Replaced shell script by mix task for post start.
1 parent 0ed24cc commit 438dcbd

File tree

3 files changed

+176
-76
lines changed

3 files changed

+176
-76
lines changed

.devcontainer/devcontainer.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
"context": ".."
66
},
77
"remoteEnv": {
8-
"MIX_ENV": "dev"
8+
"MIX_ENV": "dev",
9+
"GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}"
910
},
1011
"customizations": {
1112
"vscode": {
@@ -29,7 +30,7 @@
2930
}
3031
},
3132
"postCreateCommand": "mix deps.get",
32-
"postStartCommand": "/bin/sh /workspace/.devcontainer/scripts/post_start.sh",
33+
"postStartCommand": "mix post_start",
3334
"mounts": [
3435
"source=${localWorkspaceFolder},target=/workspace,type=bind",
3536
"source=${localEnv:HOME}/.gitconfig,target=/root/.gitconfig,type=bind,consistency=cached",

.devcontainer/scripts/post_start.sh

Lines changed: 0 additions & 74 deletions
This file was deleted.

lib/mix/tasks/post_start.ex

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
defmodule Mix.Tasks.PostStart do
2+
@shortdoc "Run post-start configuration"
3+
4+
@moduledoc false
5+
use Mix.Task
6+
7+
require Logger
8+
9+
def run(_args) do
10+
Logger.info("Starting post-start configuration...")
11+
12+
log_step("Loading environment variables", &load_environment_variables/0)
13+
log_step("Validating Git configuration", &validate_git_configuration/0)
14+
log_step("Configuring SSH", &configure_ssh/0)
15+
log_step("Setting up GitHub authentication", &setup_github_authentication/0)
16+
17+
Logger.info("Post-start configuration complete!")
18+
end
19+
20+
defp log_step(step_description, func) do
21+
Logger.info("Step: #{step_description}")
22+
23+
try do
24+
func.()
25+
rescue
26+
e -> Logger.error("#{step_description} failed: #{inspect(e)}")
27+
end
28+
end
29+
30+
defp load_environment_variables do
31+
if File.exists?(".env") do
32+
".env"
33+
|> File.read!()
34+
|> String.split("\n")
35+
|> Enum.reject(&String.starts_with?(&1, "#"))
36+
|> Enum.each(&load_env_var/1)
37+
38+
Logger.info("Environment variables loaded from .env")
39+
else
40+
Logger.info("No .env file found. Falling back to defaults.")
41+
end
42+
end
43+
44+
defp load_env_var(line) do
45+
trimmed_line = String.trim(line)
46+
47+
if trimmed_line == "" or String.starts_with?(trimmed_line, "#") do
48+
:ok
49+
else
50+
case String.split(trimmed_line, "=", parts: 2) do
51+
[key, value] -> System.put_env(key, value)
52+
_ -> Mix.shell().error("Invalid .env line: #{line}")
53+
end
54+
end
55+
rescue
56+
e -> Mix.shell().error("Error processing .env line: #{inspect(e)}")
57+
end
58+
59+
defp validate_git_configuration do
60+
Mix.shell().info("Validating Git configuration...")
61+
62+
try do
63+
user_name = get_git_config("user.name") || "Unknown User"
64+
Mix.shell().info("Git user.name: #{user_name}")
65+
user_email = get_git_config("user.email") || "[email protected]"
66+
Mix.shell().info("Git user.email: #{user_email}")
67+
rescue
68+
e -> Mix.shell().error("Error validating Git configuration: #{inspect(e)}")
69+
end
70+
end
71+
72+
defp get_git_config(key) do
73+
case System.cmd("git", ["config", "--global", key]) do
74+
{result, 0} -> String.trim(result)
75+
_ -> nil
76+
end
77+
rescue
78+
e ->
79+
Mix.shell().error("Failed to retrieve Git config for #{key}: #{inspect(e)}")
80+
nil
81+
end
82+
83+
defp configure_ssh do
84+
System.cmd("ssh-agent", ["-s"])
85+
ssh_dir = Path.expand("~/.ssh")
86+
87+
if File.dir?(ssh_dir) do
88+
ssh_dir
89+
|> File.ls!()
90+
|> Enum.each(&set_ssh_key_permissions(&1, ssh_dir))
91+
92+
ssh_add("id_ed25519")
93+
ssh_add("id_rsa")
94+
else
95+
Logger.info("No SSH key found. Please ensure keys are available in ~/.ssh.")
96+
end
97+
98+
test_ssh_connection()
99+
end
100+
101+
defp set_ssh_key_permissions(file, ssh_dir) do
102+
File.chmod!(Path.join(ssh_dir, file), 0o600)
103+
rescue
104+
e -> Logger.error("Error setting permissions for SSH key #{file}: #{inspect(e)}")
105+
end
106+
107+
defp ssh_add(key) do
108+
key_path = Path.expand("~/.ssh/#{key}")
109+
110+
if File.exists?(key_path) do
111+
System.cmd("ssh-add", [key_path])
112+
Logger.info("Added #{key} to SSH agent.")
113+
end
114+
rescue
115+
e -> Logger.error("Error adding SSH key #{key}: #{inspect(e)}")
116+
end
117+
118+
defp test_ssh_connection do
119+
Mix.shell().info("Testing SSH connection to GitHub...")
120+
121+
case System.cmd("ssh", ["-T", "[email protected]"], stderr_to_stdout: true) do
122+
{output, _} ->
123+
if String.contains?(output, "successfully authenticated") do
124+
Mix.shell().info("#{output}")
125+
else
126+
Mix.shell().error("SSH connection failed: #{output}")
127+
fallback_to_https()
128+
end
129+
end
130+
rescue
131+
e -> Mix.shell().error("Error testing SSH connection: #{inspect(e)}")
132+
end
133+
134+
defp fallback_to_https do
135+
case System.cmd("git", ["remote", "get-url", "origin"]) do
136+
{remote_url, 0} ->
137+
if String.starts_with?(remote_url, "[email protected]") do
138+
https_url = String.replace(remote_url, ~r/^git@github\\.com:/, "https://github.com/")
139+
System.cmd("git", ["remote", "set-url", "origin", String.trim(https_url)])
140+
Logger.info("Updated remote URL to HTTPS: #{https_url}")
141+
else
142+
Logger.info("Remote URL does not use SSH. No changes made.")
143+
end
144+
145+
_ ->
146+
Logger.info("No remote URL to update.")
147+
end
148+
end
149+
150+
defp setup_github_authentication do
151+
Mix.shell().info("Setting up GitHub authentication...")
152+
153+
if System.find_executable("gh") do
154+
github_token = System.get_env("GITHUB_TOKEN")
155+
authenticate_github_cli(github_token)
156+
else
157+
Mix.shell().info("GitHub CLI not installed. Skipping authentication.")
158+
end
159+
end
160+
161+
defp authenticate_github_cli(nil) do
162+
Mix.shell().error("No GITHUB_TOKEN found in the environment. Please provide one in the .env file.")
163+
end
164+
165+
defp authenticate_github_cli(github_token) do
166+
case System.cmd("gh", ["auth", "login", "--with-token"], input: github_token) do
167+
{_result, 0} -> Mix.shell().info("Authenticated with GitHub CLI.")
168+
_ -> Mix.shell().error("GitHub CLI authentication failed.")
169+
end
170+
rescue
171+
e -> Mix.shell().error("Error during GitHub CLI authentication: #{inspect(e)}")
172+
end
173+
end

0 commit comments

Comments
 (0)