rpm-cli 0.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. rpm_cli-0.1.3/.claude/settings.json +131 -0
  2. rpm_cli-0.1.3/.devcontainer/.devcontainer.postcreate.sh +459 -0
  3. rpm_cli-0.1.3/.devcontainer/VERSION +1 -0
  4. rpm_cli-0.1.3/.devcontainer/catalog-entry.json +13 -0
  5. rpm_cli-0.1.3/.devcontainer/devcontainer-functions.sh +304 -0
  6. rpm_cli-0.1.3/.devcontainer/devcontainer.json +213 -0
  7. rpm_cli-0.1.3/.devcontainer/fix-line-endings.py +117 -0
  8. rpm_cli-0.1.3/.devcontainer/nix-family-os/README.md +364 -0
  9. rpm_cli-0.1.3/.devcontainer/nix-family-os/tinyproxy-daemon.sh +435 -0
  10. rpm_cli-0.1.3/.devcontainer/nix-family-os/tinyproxy.conf.template +45 -0
  11. rpm_cli-0.1.3/.devcontainer/postcreate-wrapper.sh +55 -0
  12. rpm_cli-0.1.3/.devcontainer/project-setup.sh +29 -0
  13. rpm_cli-0.1.3/.devcontainer/wsl-family-os/README.md +331 -0
  14. rpm_cli-0.1.3/.devcontainer/wsl-family-os/tinyproxy-daemon.sh +440 -0
  15. rpm_cli-0.1.3/.devcontainer/wsl-family-os/tinyproxy.conf.template +45 -0
  16. rpm_cli-0.1.3/.github/CODEOWNERS +6 -0
  17. rpm_cli-0.1.3/.github/workflows/codeql-analysis.yml +31 -0
  18. rpm_cli-0.1.3/.github/workflows/main-validation.yml +350 -0
  19. rpm_cli-0.1.3/.github/workflows/pr-validation.yml +152 -0
  20. rpm_cli-0.1.3/.github/workflows/publish.yml +152 -0
  21. rpm_cli-0.1.3/.gitignore +20 -0
  22. rpm_cli-0.1.3/.pre-commit-config.yaml +29 -0
  23. rpm_cli-0.1.3/.tool-versions +2 -0
  24. rpm_cli-0.1.3/.yamllint +20 -0
  25. rpm_cli-0.1.3/CHANGELOG.md +107 -0
  26. rpm_cli-0.1.3/CLAUDE.md +1057 -0
  27. rpm_cli-0.1.3/CONTRIBUTING.md +203 -0
  28. rpm_cli-0.1.3/LICENSE +201 -0
  29. rpm_cli-0.1.3/Makefile +67 -0
  30. rpm_cli-0.1.3/PKG-INFO +739 -0
  31. rpm_cli-0.1.3/README.md +719 -0
  32. rpm_cli-0.1.3/docs/claude-marketplaces-guide.md +185 -0
  33. rpm_cli-0.1.3/docs/configuration.md +60 -0
  34. rpm_cli-0.1.3/docs/creating-manifest-repos.md +154 -0
  35. rpm_cli-0.1.3/docs/creating-packages.md +126 -0
  36. rpm_cli-0.1.3/docs/how-it-works.md +173 -0
  37. rpm_cli-0.1.3/docs/lifecycle.md +58 -0
  38. rpm_cli-0.1.3/docs/multi-source-guide.md +129 -0
  39. rpm_cli-0.1.3/docs/pipeline-integration.md +176 -0
  40. rpm_cli-0.1.3/docs/setup-guide.md +117 -0
  41. rpm_cli-0.1.3/docs/version-resolution.md +39 -0
  42. rpm_cli-0.1.3/git-hooks/pre-commit +14 -0
  43. rpm_cli-0.1.3/git-hooks/pre-push +34 -0
  44. rpm_cli-0.1.3/pyproject.toml +101 -0
  45. rpm_cli-0.1.3/requirements-dev.txt +9 -0
  46. rpm_cli-0.1.3/requirements.txt +1 -0
  47. rpm_cli-0.1.3/src/rpm_cli/__init__.py +3 -0
  48. rpm_cli-0.1.3/src/rpm_cli/__main__.py +5 -0
  49. rpm_cli-0.1.3/src/rpm_cli/catalog/gradle/build.gradle +42 -0
  50. rpm_cli-0.1.3/src/rpm_cli/catalog/gradle/rpm-bootstrap.gradle +70 -0
  51. rpm_cli-0.1.3/src/rpm_cli/catalog/make/Makefile +74 -0
  52. rpm_cli-0.1.3/src/rpm_cli/cli.py +67 -0
  53. rpm_cli-0.1.3/src/rpm_cli/commands/__init__.py +0 -0
  54. rpm_cli-0.1.3/src/rpm_cli/commands/bootstrap.py +70 -0
  55. rpm_cli-0.1.3/src/rpm_cli/commands/clean.py +40 -0
  56. rpm_cli-0.1.3/src/rpm_cli/commands/configure.py +109 -0
  57. rpm_cli-0.1.3/src/rpm_cli/commands/validate.py +133 -0
  58. rpm_cli-0.1.3/src/rpm_cli/core/__init__.py +0 -0
  59. rpm_cli-0.1.3/src/rpm_cli/core/bootstrap.py +159 -0
  60. rpm_cli-0.1.3/src/rpm_cli/core/catalog.py +134 -0
  61. rpm_cli-0.1.3/src/rpm_cli/core/clean.py +111 -0
  62. rpm_cli-0.1.3/src/rpm_cli/core/configure.py +347 -0
  63. rpm_cli-0.1.3/src/rpm_cli/core/marketplace.py +433 -0
  64. rpm_cli-0.1.3/src/rpm_cli/core/marketplace_validator.py +237 -0
  65. rpm_cli-0.1.3/src/rpm_cli/core/rpmenv.py +320 -0
  66. rpm_cli-0.1.3/src/rpm_cli/core/xml_validator.py +94 -0
  67. rpm_cli-0.1.3/src/rpm_cli/version.py +132 -0
  68. rpm_cli-0.1.3/tests/__init__.py +0 -0
  69. rpm_cli-0.1.3/tests/conftest.py +37 -0
  70. rpm_cli-0.1.3/tests/functional/__init__.py +0 -0
  71. rpm_cli-0.1.3/tests/functional/test_clean_lifecycle.py +94 -0
  72. rpm_cli-0.1.3/tests/functional/test_cli_entry_point.py +84 -0
  73. rpm_cli-0.1.3/tests/functional/test_configure_lifecycle.py +120 -0
  74. rpm_cli-0.1.3/tests/functional/test_validate_lifecycle.py +134 -0
  75. rpm_cli-0.1.3/tests/unit/__init__.py +0 -0
  76. rpm_cli-0.1.3/tests/unit/test_bootstrap.py +128 -0
  77. rpm_cli-0.1.3/tests/unit/test_catalog.py +160 -0
  78. rpm_cli-0.1.3/tests/unit/test_clean.py +111 -0
  79. rpm_cli-0.1.3/tests/unit/test_clean_command.py +22 -0
  80. rpm_cli-0.1.3/tests/unit/test_cli.py +67 -0
  81. rpm_cli-0.1.3/tests/unit/test_configure.py +195 -0
  82. rpm_cli-0.1.3/tests/unit/test_configure_command.py +42 -0
  83. rpm_cli-0.1.3/tests/unit/test_marketplace.py +357 -0
  84. rpm_cli-0.1.3/tests/unit/test_marketplace_validator.py +124 -0
  85. rpm_cli-0.1.3/tests/unit/test_rpmenv.py +189 -0
  86. rpm_cli-0.1.3/tests/unit/test_validate_command.py +48 -0
  87. rpm_cli-0.1.3/tests/unit/test_version.py +107 -0
  88. rpm_cli-0.1.3/tests/unit/test_xml_validator.py +64 -0
@@ -0,0 +1,131 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Read",
5
+ "Glob",
6
+ "Grep",
7
+ "WebFetch",
8
+ "Edit",
9
+ "Write",
10
+ "Bash(git status*)",
11
+ "Bash(git log*)",
12
+ "Bash(git show*)",
13
+ "Bash(git diff*)",
14
+ "Bash(git describe*)",
15
+ "Bash(git branch*)",
16
+ "Bash(git remote*)",
17
+ "Bash(git config --list*)",
18
+ "Bash(git tag --list*)",
19
+ "Bash(aws sso login*)",
20
+ "Bash(aws sts get-caller-identity*)",
21
+ "Bash(aws * describe-*)",
22
+ "Bash(aws * list-*)",
23
+ "Bash(aws * get-*)",
24
+ "Bash(aws s3 ls*)",
25
+ "Bash(argocd login*)",
26
+ "Bash(argocd * list*)",
27
+ "Bash(argocd * get*)",
28
+ "Bash(argocd * diff*)",
29
+ "Bash(argocd * logs*)",
30
+ "Bash(argocd * manifests*)",
31
+ "Bash(fly*login*)",
32
+ "Bash(fly pipelines*)",
33
+ "Bash(fly jobs*)",
34
+ "Bash(fly builds*)",
35
+ "Bash(fly workers*)",
36
+ "Bash(fly targets*)",
37
+ "Bash(fly status*)",
38
+ "Bash(gh auth login*)",
39
+ "Bash(gh auth status*)",
40
+ "Bash(gh * view*)",
41
+ "Bash(gh * list*)",
42
+ "Bash(gh * diff*)",
43
+ "Bash(jfrog config add*)",
44
+ "Bash(jfrog config show*)",
45
+ "Bash(jfrog rt search*)",
46
+ "Bash(jf config add*)",
47
+ "Bash(jf config show*)",
48
+ "Bash(jf rt search*)",
49
+ "Bash(snyk auth*)",
50
+ "Bash(snyk config*)",
51
+ "Bash(snyk test*)",
52
+ "Bash(snyk monitor*)",
53
+ "Bash(snyk --version*)",
54
+ "Bash(crane ls*)",
55
+ "Bash(crane manifest*)",
56
+ "Bash(crane config*)",
57
+ "Bash(crane digest*)",
58
+ "Bash(crane version*)",
59
+ "Bash(kubectl get*)",
60
+ "Bash(kubectl describe*)",
61
+ "Bash(kubectl logs*)",
62
+ "Bash(kubectl explain*)",
63
+ "Bash(kubectl api-resources*)",
64
+ "Bash(kubectl cluster-info*)",
65
+ "Bash(kubectl top*)",
66
+ "Bash(kubectl config view*)",
67
+ "Bash(helm list*)",
68
+ "Bash(helm status*)",
69
+ "Bash(helm get*)",
70
+ "Bash(helm history*)",
71
+ "Bash(helm show*)",
72
+ "Bash(helm search*)",
73
+ "Bash(helm repo list*)",
74
+ "Bash(ls*)",
75
+ "Bash(cat *)",
76
+ "Bash(head *)",
77
+ "Bash(tail *)",
78
+ "Bash(grep *)",
79
+ "Bash(find *)",
80
+ "Bash(tree*)",
81
+ "Bash(wc *)",
82
+ "Bash(diff *)",
83
+ "Bash(file *)",
84
+ "Bash(stat *)",
85
+ "Bash(pwd*)",
86
+ "Bash(which *)",
87
+ "Bash(env*)",
88
+ "Bash(printenv*)",
89
+ "Bash(xargs *)",
90
+ "Bash(code --list-extensions*)",
91
+ "Bash(asdf plugin list*)",
92
+ "Bash(asdf plugin add*)",
93
+ "Bash(asdf list all*)",
94
+ "Bash(asdf install*)",
95
+ "Bash(asdf reshim*)",
96
+ "Bash(asdf current*)",
97
+ "Bash(mkdir *)",
98
+ "Bash(cp *)",
99
+ "Bash(source ~/.bashrc*)",
100
+ "Bash(mv *)",
101
+ "Bash(rm *)",
102
+ "Bash(git add*)",
103
+ "Bash(git commit*)",
104
+ "Bash(git push*)"
105
+ ],
106
+ "deny": [
107
+ "Bash(sed *)",
108
+ "Bash(awk *)",
109
+ "Bash(vi *)",
110
+ "Bash(vim *)",
111
+ "Bash(nano *)",
112
+ "Bash(emacs *)",
113
+ "Bash(tee *)",
114
+ "Bash(git merge*)",
115
+ "Bash(git rebase*)",
116
+ "Bash(docker build*)",
117
+ "Bash(docker run*)",
118
+ "Bash(docker push*)",
119
+ "Bash(kubectl apply*)",
120
+ "Bash(kubectl delete*)",
121
+ "Bash(kubectl edit*)",
122
+ "Bash(kubectl patch*)",
123
+ "Bash(helm install*)",
124
+ "Bash(helm upgrade*)",
125
+ "Bash(helm delete*)",
126
+ "Bash(aws s3 cp*)",
127
+ "Bash(aws s3 sync*)",
128
+ "Bash(aws s3 rm*)"
129
+ ]
130
+ }
131
+ }
@@ -0,0 +1,459 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+
5
+ WORK_DIR=$(pwd)
6
+ CONTAINER_USER=$1
7
+ BASH_RC="/home/${CONTAINER_USER}/.bashrc"
8
+ ZSH_RC="/home/${CONTAINER_USER}/.zshrc"
9
+ WARNINGS=()
10
+
11
+ # Source shared functions
12
+ source "${WORK_DIR}/.devcontainer/devcontainer-functions.sh"
13
+
14
+ # Configure and log CICD environment
15
+ CICD_VALUE="${CICD:-false}"
16
+ if [ "$CICD_VALUE" = "true" ]; then
17
+ log_info "CICD environment variable: $CICD_VALUE"
18
+ log_info "Devcontainer configured to run in CICD mode (not a local dev environment)"
19
+ else
20
+ log_info "CICD environment variable: ${CICD:-not set}"
21
+ log_info "Devcontainer configured to run as a local developer environment"
22
+ fi
23
+
24
+ log_info "Starting post-create setup..."
25
+
26
+ ############################
27
+ # Create Python Symlink #
28
+ ############################
29
+ if ! command -v python &> /dev/null; then
30
+ log_info "Creating python symlink to python3"
31
+ sudo ln -sf /usr/bin/python3 /usr/bin/python
32
+ fi
33
+
34
+ # Add Python tools to PATH for script execution
35
+ export PATH="/usr/local/py-utils/bin:/usr/local/python/current/bin:$HOME/.local/bin:$PATH"
36
+
37
+ #########################
38
+ # Require Critical Envs #
39
+ #########################
40
+ if [ -z "${DEFAULT_GIT_BRANCH:-}" ]; then
41
+ exit_with_error "❌ DEFAULT_GIT_BRANCH is not set in the environment"
42
+ fi
43
+
44
+ if [ "$CICD_VALUE" != "true" ]; then
45
+ AWS_CONFIG_ENABLED="${AWS_CONFIG_ENABLED:-true}"
46
+ AWS_PROFILE_MAP_FILE="${WORK_DIR}/.devcontainer/aws-profile-map.json"
47
+
48
+ if [ "${AWS_CONFIG_ENABLED,,}" = "true" ]; then
49
+ if [ ! -f "$AWS_PROFILE_MAP_FILE" ]; then
50
+ exit_with_error "❌ Missing AWS profile config: $AWS_PROFILE_MAP_FILE (required when AWS_CONFIG_ENABLED=true)"
51
+ fi
52
+
53
+ AWS_PROFILE_MAP_JSON=$(<"$AWS_PROFILE_MAP_FILE")
54
+
55
+ if ! jq empty <<< "$AWS_PROFILE_MAP_JSON" >/dev/null 2>&1; then
56
+ log_error "$AWS_PROFILE_MAP_JSON"
57
+ exit_with_error "❌ AWS_PROFILE_MAP_JSON is not valid JSON"
58
+ fi
59
+ else
60
+ log_info "AWS configuration disabled (AWS_CONFIG_ENABLED=${AWS_CONFIG_ENABLED})"
61
+ fi
62
+ else
63
+ log_info "CICD mode enabled - skipping AWS configuration validation"
64
+ fi
65
+
66
+ #################
67
+ # Configure ENV #
68
+ #################
69
+ log_info "Configuring ENV vars..."
70
+
71
+ # Configure shell.env sourcing for all shells (interactive and non-interactive)
72
+ log_info "Configuring shell.env sourcing for all shells"
73
+
74
+ # Verify shell.env exists before configuring shells
75
+ if [ ! -f "${WORK_DIR}/shell.env" ]; then
76
+ exit_with_error "❌ shell.env not found at ${WORK_DIR}/shell.env"
77
+ fi
78
+
79
+ # For bash: source in .bashrc (interactive) and via BASH_ENV (non-interactive)
80
+ echo "# Source project shell.env" >> "${BASH_RC}"
81
+ echo "source \"${WORK_DIR}/shell.env\"" >> "${BASH_RC}"
82
+ echo "export BASH_ENV=\"${WORK_DIR}/shell.env\"" >> "${BASH_RC}"
83
+ echo "export PATH=\"\$HOME/.local/bin:\$PATH\"" >> "${BASH_RC}"
84
+ echo "alias python=python3" >> "${BASH_RC}"
85
+ echo "alias pip=pip3" >> "${BASH_RC}"
86
+
87
+ # For zsh: source in .zshenv (covers all zsh shells - interactive and non-interactive)
88
+ echo "source \"${WORK_DIR}/shell.env\"" > /home/${CONTAINER_USER}/.zshenv
89
+ echo "export PATH=\"\$HOME/.local/bin:\$PATH\"" >> /home/${CONTAINER_USER}/.zshenv
90
+ echo "alias python=python3" >> /home/${CONTAINER_USER}/.zshenv
91
+ echo "alias pip=pip3" >> /home/${CONTAINER_USER}/.zshenv
92
+
93
+ ##############################
94
+ # Install asdf & Tool Versions
95
+ ##############################
96
+ log_info "Installing asdf..."
97
+ mkdir -p /home/${CONTAINER_USER}/.asdf
98
+ if ! git clone https://github.com/asdf-vm/asdf.git /home/${CONTAINER_USER}/.asdf --branch v0.15.0; then
99
+ exit_with_error "Failed to clone asdf repository — check network connectivity and proxy settings"
100
+ fi
101
+
102
+ # Source asdf for the current script
103
+ export ASDF_DIR="/home/${CONTAINER_USER}/.asdf"
104
+ export ASDF_DATA_DIR="/home/${CONTAINER_USER}/.asdf"
105
+ . "/home/${CONTAINER_USER}/.asdf/asdf.sh"
106
+
107
+ # Make asdf available system-wide for AI agents
108
+ log_info "Configuring system-wide asdf access for AI agents..."
109
+
110
+ # Create plugins directory if it doesn't exist
111
+ mkdir -p /home/${CONTAINER_USER}/.asdf/plugins
112
+
113
+ # Create wrapper scripts for asdf tools in /usr/local/bin for direct access
114
+ log_info "Creating asdf wrapper scripts for direct access..."
115
+
116
+ # Create asdf wrapper script
117
+ if uname -r | grep -i microsoft > /dev/null; then
118
+ # WSL compatibility: Use sudo for /usr/local/bin access
119
+ sudo tee /usr/local/bin/asdf > /dev/null << ASDF_WRAPPER
120
+ #!/bin/bash
121
+ # Wrapper script for asdf that ensures proper environment
122
+ export ASDF_DIR="/home/${CONTAINER_USER}/.asdf"
123
+ export ASDF_DATA_DIR="/home/${CONTAINER_USER}/.asdf"
124
+ if [ -f "/home/${CONTAINER_USER}/.asdf/asdf.sh" ]; then
125
+ . "/home/${CONTAINER_USER}/.asdf/asdf.sh"
126
+ fi
127
+ exec /home/${CONTAINER_USER}/.asdf/bin/asdf "\$@"
128
+ ASDF_WRAPPER
129
+ sudo chmod +x /usr/local/bin/asdf
130
+ else
131
+ # Non-WSL: Direct write to /usr/local/bin
132
+ cat > /usr/local/bin/asdf << ASDF_WRAPPER
133
+ #!/bin/bash
134
+ # Wrapper script for asdf that ensures proper environment
135
+ export ASDF_DIR="/home/${CONTAINER_USER}/.asdf"
136
+ export ASDF_DATA_DIR="/home/${CONTAINER_USER}/.asdf"
137
+ if [ -f "/home/${CONTAINER_USER}/.asdf/asdf.sh" ]; then
138
+ . "/home/${CONTAINER_USER}/.asdf/asdf.sh"
139
+ fi
140
+ exec /home/${CONTAINER_USER}/.asdf/bin/asdf "\$@"
141
+ ASDF_WRAPPER
142
+ chmod +x /usr/local/bin/asdf
143
+ fi
144
+
145
+ # Create pip wrapper script that sources asdf environment
146
+ if uname -r | grep -i microsoft > /dev/null; then
147
+ # WSL compatibility: Use sudo for /usr/local/bin access
148
+ sudo tee /usr/local/bin/pip-asdf > /dev/null << PIP_WRAPPER
149
+ #!/bin/bash
150
+ # Wrapper script for pip that ensures asdf environment is loaded
151
+ export ASDF_DIR="/home/${CONTAINER_USER}/.asdf"
152
+ export ASDF_DATA_DIR="/home/${CONTAINER_USER}/.asdf"
153
+ if [ -f "/home/${CONTAINER_USER}/.asdf/asdf.sh" ]; then
154
+ . "/home/${CONTAINER_USER}/.asdf/asdf.sh"
155
+ fi
156
+ exec /home/${CONTAINER_USER}/.asdf/shims/pip "\$@"
157
+ PIP_WRAPPER
158
+ sudo chmod +x /usr/local/bin/pip-asdf
159
+ else
160
+ # Non-WSL: Direct write to /usr/local/bin
161
+ cat > /usr/local/bin/pip-asdf << PIP_WRAPPER
162
+ #!/bin/bash
163
+ # Wrapper script for pip that ensures asdf environment is loaded
164
+ export ASDF_DIR="/home/${CONTAINER_USER}/.asdf"
165
+ export ASDF_DATA_DIR="/home/${CONTAINER_USER}/.asdf"
166
+ if [ -f "/home/${CONTAINER_USER}/.asdf/asdf.sh" ]; then
167
+ . "/home/${CONTAINER_USER}/.asdf/asdf.sh"
168
+ fi
169
+ exec /home/${CONTAINER_USER}/.asdf/shims/pip "\$@"
170
+ PIP_WRAPPER
171
+ chmod +x /usr/local/bin/pip-asdf
172
+ fi
173
+
174
+ #################
175
+ # Oh My Zsh #
176
+ #################
177
+ if [ ! -d "/home/${CONTAINER_USER}/.oh-my-zsh" ]; then
178
+ log_info "Installing Oh My Zsh..."
179
+ OMZ_INSTALL_SCRIPT="/tmp/ohmyzsh-install-${RANDOM}.sh"
180
+ if ! curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh -o "${OMZ_INSTALL_SCRIPT}"; then
181
+ exit_with_error "Failed to download Oh My Zsh install script — check network connectivity and proxy settings"
182
+ fi
183
+ if [ ! -s "${OMZ_INSTALL_SCRIPT}" ]; then
184
+ exit_with_error "Oh My Zsh install script is empty or missing at ${OMZ_INSTALL_SCRIPT}"
185
+ fi
186
+ if ! sh "${OMZ_INSTALL_SCRIPT}" --unattended; then
187
+ rm -f "${OMZ_INSTALL_SCRIPT}"
188
+ exit_with_error "Oh My Zsh installation failed"
189
+ fi
190
+ rm -f "${OMZ_INSTALL_SCRIPT}"
191
+ else
192
+ log_info "Oh My Zsh already installed — skipping"
193
+ fi
194
+
195
+ cat <<'EOF' >> ${ZSH_RC}
196
+ export ZSH="$HOME/.oh-my-zsh"
197
+ ZSH_THEME="obraun"
198
+ ENABLE_CORRECTION="false"
199
+ HIST_STAMPS="%m/%d/%Y - %H:%M:%S"
200
+ source $ZSH/oh-my-zsh.sh
201
+ EOF
202
+
203
+ #################
204
+ # Configure AWS #
205
+ #################
206
+ if [ "$CICD_VALUE" != "true" ]; then
207
+ if [ "${AWS_CONFIG_ENABLED,,}" = "true" ]; then
208
+ log_info "Configuring AWS profiles..."
209
+ mkdir -p /home/${CONTAINER_USER}/.aws
210
+ mkdir -p /home/${CONTAINER_USER}/.aws/amazonq/cache
211
+ chown -R ${CONTAINER_USER}:${CONTAINER_USER} /home/${CONTAINER_USER}/.aws/amazonq
212
+
213
+ AWS_OUTPUT_FORMAT="${AWS_DEFAULT_OUTPUT:-json}"
214
+ jq -r 'to_entries[] |
215
+ "[profile \(.key)]\n" +
216
+ "sso_start_url = \(.value.sso_start_url)\n" +
217
+ "sso_region = \(.value.sso_region)\n" +
218
+ "sso_account_name = \(.value.account_name)\n" +
219
+ "sso_account_id = \(.value.account_id)\n" +
220
+ "sso_role_name = \(.value.role_name)\n" +
221
+ "region = \(.value.region)\n" +
222
+ "output = '"$AWS_OUTPUT_FORMAT"'\n" +
223
+ "sso_auto_populated = true\n"' <<< "$AWS_PROFILE_MAP_JSON" \
224
+ > /home/${CONTAINER_USER}/.aws/config
225
+ else
226
+ log_info "Skipping AWS profile configuration (AWS_CONFIG_ENABLED=${AWS_CONFIG_ENABLED})"
227
+ fi
228
+ else
229
+ log_info "CICD mode enabled - skipping AWS profile configuration"
230
+ fi
231
+
232
+ #####################
233
+ # Install Base Tools
234
+ #####################
235
+ log_info "Installing core packages..."
236
+ log_info "Proxy environment: HTTP_PROXY=${HTTP_PROXY:-unset} http_proxy=${http_proxy:-unset}"
237
+ if ! sudo apt-get update -qq; then
238
+ exit_with_error "apt-get update failed. Check proxy settings and network connectivity. HTTP_PROXY=${HTTP_PROXY:-unset}"
239
+ fi
240
+ if ! sudo apt-get install -y -qq curl vim-tiny git gh nmap sipcalc wget unzip zip netcat-openbsd bc; then
241
+ exit_with_error "apt-get install failed for core packages"
242
+ fi
243
+
244
+ ##############################
245
+ # Install Optional Extra Tools
246
+ ##############################
247
+ if [ -n "${EXTRA_APT_PACKAGES:-}" ]; then
248
+ log_info "Installing extra packages: ${EXTRA_APT_PACKAGES}"
249
+ if ! sudo apt-get install -y ${EXTRA_APT_PACKAGES}; then
250
+ exit_with_error "apt-get install failed for extra packages: ${EXTRA_APT_PACKAGES}"
251
+ fi
252
+ fi
253
+
254
+ if [ -f "${WORK_DIR}/.tool-versions" ] && grep -qE '^[a-zA-Z]' "${WORK_DIR}/.tool-versions"; then
255
+ log_info "Installing asdf plugins from .tool-versions..."
256
+ grep -E '^[a-zA-Z]' "${WORK_DIR}/.tool-versions" | cut -d' ' -f1 | while read -r plugin; do
257
+ install_asdf_plugin "$plugin"
258
+ done
259
+
260
+ log_info "Installing tools from .tool-versions..."
261
+ if ! asdf install; then
262
+ log_warn "❌ asdf install failed — tool versions may not be fully installed"
263
+ fi
264
+
265
+ log_info "Running asdf reshim..."
266
+ if ! asdf reshim; then
267
+ exit_with_error "❌ asdf reshim failed"
268
+ fi
269
+ else
270
+ log_info "No .tool-versions file found (or file is empty) — skipping asdf install"
271
+ fi
272
+
273
+ # Create symlinks in /usr/local/bin for direct access by AI agents
274
+ log_info "Creating symlinks for AI agent direct access..."
275
+ if [ -d "/home/${CONTAINER_USER}/.asdf/shims" ]; then
276
+ for shim in /home/${CONTAINER_USER}/.asdf/shims/*; do
277
+ if [ -f "$shim" ] && [ -x "$shim" ]; then
278
+ shim_name=$(basename "$shim")
279
+ if [ ! -e "/usr/local/bin/$shim_name" ]; then
280
+ if uname -r | grep -i microsoft > /dev/null; then
281
+ # WSL compatibility: Use sudo for /usr/local/bin access
282
+ sudo ln -s "$shim" "/usr/local/bin/$shim_name"
283
+ else
284
+ # Non-WSL: Direct symlink creation
285
+ ln -s "$shim" "/usr/local/bin/$shim_name"
286
+ fi
287
+ log_info "Created symlink: /usr/local/bin/$shim_name -> $shim"
288
+ fi
289
+ fi
290
+ done
291
+ fi
292
+
293
+ # Install Caylent Devcontainer CLI
294
+ log_info "Installing Caylent Devcontainer CLI..."
295
+ if [ -n "${CLI_VERSION:-}" ]; then
296
+ if [[ "${CLI_VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
297
+ log_info "Installing specific CLI version: ${CLI_VERSION}"
298
+ CLI_INSTALL_CMD="caylent-devcontainer-cli==${CLI_VERSION}"
299
+ else
300
+ exit_with_error "Invalid CLI_VERSION format: ${CLI_VERSION}. Expected format: X.Y.Z (e.g., 1.2.3)"
301
+ fi
302
+ else
303
+ log_info "Installing latest CLI version"
304
+ CLI_INSTALL_CMD="caylent-devcontainer-cli"
305
+ fi
306
+
307
+ install_with_pipx "${CLI_INSTALL_CMD}"
308
+
309
+ # Verify asdf is working properly (only if tools were configured)
310
+ if [ -f "${WORK_DIR}/.tool-versions" ] && grep -qE '^[a-zA-Z]' "${WORK_DIR}/.tool-versions"; then
311
+ log_info "Verifying asdf installation..."
312
+ if ! asdf current; then
313
+ exit_with_error "❌ asdf current failed - installation may be incomplete"
314
+ fi
315
+ else
316
+ log_info "No asdf tools configured — skipping verification"
317
+ fi
318
+
319
+ ##############
320
+ # Host Proxy #
321
+ ##############
322
+ # Proxy environment variables are sourced from shell.env (generated by write_shell_env).
323
+ # This section validates that host proxy is accessible when HOST_PROXY=true.
324
+
325
+ if [ "${HOST_PROXY:-false}" = "true" ]; then
326
+ if [ -z "${HOST_PROXY_URL:-}" ]; then
327
+ exit_with_error "❌ HOST_PROXY=true but HOST_PROXY_URL is not set. Set HOST_PROXY_URL in shell.env (e.g., http://host.docker.internal:3128)"
328
+ fi
329
+
330
+ parse_proxy_host_port "${HOST_PROXY_URL}"
331
+
332
+ if is_wsl; then
333
+ validate_host_proxy "${PROXY_PARSED_HOST}" "${PROXY_PARSED_PORT}" "${HOST_PROXY_TIMEOUT:-10}" "wsl-family-os/README.md"
334
+ else
335
+ validate_host_proxy "${PROXY_PARSED_HOST}" "${PROXY_PARSED_PORT}" "${HOST_PROXY_TIMEOUT:-10}" "nix-family-os/README.md"
336
+ fi
337
+ else
338
+ log_info "Host proxy not enabled (HOST_PROXY=${HOST_PROXY:-false}) - skipping validation"
339
+ fi
340
+
341
+ #############
342
+ # AWS Tools #
343
+ #############
344
+ log_info "Installing AWS SSO utilities..."
345
+ install_with_pipx "aws-sso-util"
346
+
347
+ ###################
348
+ # Claude Code CLI #
349
+ ###################
350
+ log_info "Installing Claude Code CLI..."
351
+
352
+ # Download install script first to ensure it succeeds before piping to bash
353
+ CLAUDE_INSTALL_SCRIPT="/tmp/claude-install-${RANDOM}.sh"
354
+
355
+ if ! sudo -u "${CONTAINER_USER}" curl -fsSL https://claude.ai/install.sh -o "${CLAUDE_INSTALL_SCRIPT}"; then
356
+ exit_with_error "❌ Failed to download Claude Code install script from https://claude.ai/install.sh - check network connectivity and proxy settings"
357
+ fi
358
+
359
+ # Verify script was downloaded and is not empty
360
+ if [ ! -s "${CLAUDE_INSTALL_SCRIPT}" ]; then
361
+ exit_with_error "❌ Claude Code install script is empty or missing at ${CLAUDE_INSTALL_SCRIPT}"
362
+ fi
363
+
364
+ # Execute install script
365
+ log_info "Executing Claude Code install script..."
366
+ if uname -r | grep -i microsoft > /dev/null; then
367
+ # WSL compatibility: Run directly without sudo -u
368
+ if ! PATH="/home/${CONTAINER_USER}/.local/bin:$PATH" bash "${CLAUDE_INSTALL_SCRIPT}"; then
369
+ rm -f "${CLAUDE_INSTALL_SCRIPT}"
370
+ exit_with_error "❌ Failed to execute Claude Code install script"
371
+ fi
372
+ else
373
+ # Non-WSL: Install as container user
374
+ if ! sudo -u "${CONTAINER_USER}" PATH="/home/${CONTAINER_USER}/.local/bin:$PATH" bash "${CLAUDE_INSTALL_SCRIPT}"; then
375
+ rm -f "${CLAUDE_INSTALL_SCRIPT}"
376
+ exit_with_error "❌ Failed to execute Claude Code install script"
377
+ fi
378
+ fi
379
+
380
+ # Clean up install script
381
+ rm -f "${CLAUDE_INSTALL_SCRIPT}"
382
+
383
+ log_info "Verifying Claude Code CLI installation..."
384
+ CLAUDE_BIN="/home/${CONTAINER_USER}/.local/bin/claude"
385
+ if [ ! -f "$CLAUDE_BIN" ]; then
386
+ exit_with_error "❌ Claude Code binary not found at expected location: $CLAUDE_BIN"
387
+ fi
388
+
389
+ if [ ! -x "$CLAUDE_BIN" ]; then
390
+ exit_with_error "❌ Claude Code binary exists but is not executable: $CLAUDE_BIN"
391
+ fi
392
+
393
+ CLAUDE_VERSION=$(sudo -u "${CONTAINER_USER}" "${CLAUDE_BIN}" --version 2>&1 || echo "unknown")
394
+ log_success "Claude Code CLI installed successfully: ${CLAUDE_VERSION}"
395
+
396
+ #################
397
+ # Configure Git #
398
+ #################
399
+ if [ "$CICD_VALUE" != "true" ]; then
400
+ log_info "Setting up Git credentials..."
401
+
402
+ if [ -z "${GIT_AUTH_METHOD:-}" ]; then
403
+ exit_with_error "❌ GIT_AUTH_METHOD is required. Please regenerate project files."
404
+ fi
405
+
406
+ # Shared git config (both methods)
407
+ configure_git_shared "${CONTAINER_USER}" "${GIT_USER}" "${GIT_USER_EMAIL}"
408
+
409
+ case "${GIT_AUTH_METHOD}" in
410
+ token)
411
+ configure_git_token "${CONTAINER_USER}" "${GIT_PROVIDER_URL}" "${GIT_USER}" "${GIT_TOKEN}"
412
+ ;;
413
+ ssh)
414
+ configure_git_ssh "${CONTAINER_USER}" "${GIT_PROVIDER_URL}" "${WORK_DIR}"
415
+ ;;
416
+ *)
417
+ exit_with_error "❌ Invalid GIT_AUTH_METHOD: '${GIT_AUTH_METHOD}'. Must be 'token' or 'ssh'."
418
+ ;;
419
+ esac
420
+ else
421
+ log_info "CICD mode enabled - skipping Git configuration"
422
+ fi
423
+
424
+ ###########
425
+ # Cleanup #
426
+ ###########
427
+ log_info "Fixing ownership for ${CONTAINER_USER}"
428
+ chown -R ${CONTAINER_USER}:${CONTAINER_USER} /home/${CONTAINER_USER}
429
+
430
+ ####################
431
+ # Warning Summary #
432
+ ####################
433
+ if [ ${#WARNINGS[@]} -ne 0 ]; then
434
+ echo -e "\n⚠️ Completed with warnings:"
435
+ for warning in "${WARNINGS[@]}"; do
436
+ echo " - $warning"
437
+ done
438
+ else
439
+ log_success "Dev container setup completed with no warnings"
440
+ fi
441
+
442
+ #########################
443
+ # Project-Specific Setup #
444
+ #########################
445
+ log_info "Running project-specific setup script..."
446
+ if [ -f "${WORK_DIR}/.devcontainer/project-setup.sh" ]; then
447
+ if uname -r | grep -i microsoft > /dev/null; then
448
+ # WSL compatibility: Run directly without sudo -u
449
+ bash -c "source '${WORK_DIR}/shell.env' && source /home/${CONTAINER_USER}/.asdf/asdf.sh && cd '${WORK_DIR}' && BASH_ENV='${WORK_DIR}/.devcontainer/devcontainer-functions.sh' bash '${WORK_DIR}/.devcontainer/project-setup.sh'"
450
+ else
451
+ # Non-WSL: Use sudo -u to run as container user
452
+ sudo -u "${CONTAINER_USER}" bash -c "source '${WORK_DIR}/shell.env' && source /home/${CONTAINER_USER}/.asdf/asdf.sh && cd '${WORK_DIR}' && BASH_ENV='${WORK_DIR}/.devcontainer/devcontainer-functions.sh' bash '${WORK_DIR}/.devcontainer/project-setup.sh'"
453
+ fi
454
+ else
455
+ log_warn "No project-specific setup script found at ${WORK_DIR}/.devcontainer/project-setup.sh"
456
+ WARNINGS+=("No project-specific setup script found at ${WORK_DIR}/.devcontainer/project-setup.sh")
457
+ fi
458
+
459
+ exit 0
@@ -0,0 +1 @@
1
+ 2.0.0
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "default",
3
+ "description": "General-purpose Caylent development environment with Python, Node.js, AWS CLI, Docker, and Kubernetes tools.",
4
+ "tags": [
5
+ "general",
6
+ "multi-language",
7
+ "aws",
8
+ "kubernetes"
9
+ ],
10
+ "maintainer": "Caylent Platform Team",
11
+ "min_cli_version": "2.0.0",
12
+ "catalog_url": "https://github.com/caylent-solutions/devcontainer.git@2.0.4"
13
+ }