@hybridlabor-api/aos 4.8.0 → 4.9.0
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.
- package/.agents/agents.md +1 -1
- package/.agents/nodes.json +1 -1
- package/.agents/vendor-manifest.json +23 -1
- package/.claude/agents/godmode-media-eventtech.md +1 -1
- package/.claude/hooks/conventional-commits.mjs +125 -0
- package/.claude/hooks/env-file-protection.mjs +105 -0
- package/.claude/hooks/go-gate.mjs +101 -81
- package/.claude/settings.json +13 -0
- package/.opencode/agents/godmode-media-eventtech.md +1 -1
- package/.opencode/plugins/bdb-aos.js +31 -4
- package/README.de.md +1 -1
- package/README.md +1 -1
- package/README.pt.md +1 -1
- package/THIRD_PARTY_NOTICES.md +88 -0
- package/docs/skills_table.md +1 -1
- package/installer.js +174 -46
- package/package.json +6 -2
- package/packages/aos-cli/README.md +80 -0
- package/packages/aos-cli/bin/aos-cli.mjs +134 -0
- package/packages/aos-cli/core-skills.json +12 -0
- package/packages/aos-cli/extensions/aos.ts +321 -0
- package/packages/aos-cli/package-lock.json +1923 -0
- package/packages/aos-cli/package.json +29 -0
- package/packages/aos-cli/scripts/check-theme.mjs +63 -0
- package/packages/aos-cli/themes/aos.json +97 -0
- package/scripts/build-plugin-manifest.mjs +131 -0
- package/scripts/validate-skills.mjs +81 -6
- package/skills/basic/ao-orchestrator/SKILL.md +116 -0
- package/skills/global_config/agenttrail/SKILL.md +6 -1
- package/skills/global_config/ask-tim/SKILL.md +4 -4
- package/skills/global_config/bash-script-generator/SKILL.md +201 -0
- package/skills/global_config/bash-script-generator/assets/templates/standard-template.sh +96 -0
- package/skills/global_config/bash-script-generator/docs/bash-scripting-guide.md +729 -0
- package/skills/global_config/bash-script-generator/docs/generation-best-practices.md +193 -0
- package/skills/global_config/bash-script-generator/docs/script-patterns.md +566 -0
- package/skills/global_config/bash-script-generator/docs/text-processing-guide.md +437 -0
- package/skills/global_config/bash-script-generator/examples/log-analyzer.sh +92 -0
- package/skills/global_config/bash-script-generator/scripts/generate_script_template.sh +123 -0
- package/skills/global_config/bash-script-generator/scripts/run_ci_checks.sh +172 -0
- package/skills/global_config/bash-script-generator/scripts/test_generator.sh +413 -0
- package/skills/global_config/bash-script-validator/SKILL.md +249 -0
- package/skills/global_config/bash-script-validator/docs/awk-reference.md +449 -0
- package/skills/global_config/bash-script-validator/docs/bash-reference.md +468 -0
- package/skills/global_config/bash-script-validator/docs/common-mistakes.md +623 -0
- package/skills/global_config/bash-script-validator/docs/grep-reference.md +395 -0
- package/skills/global_config/bash-script-validator/docs/regex-reference.md +391 -0
- package/skills/global_config/bash-script-validator/docs/sed-reference.md +454 -0
- package/skills/global_config/bash-script-validator/docs/shell-reference.md +463 -0
- package/skills/global_config/bash-script-validator/docs/shellcheck-reference.md +399 -0
- package/skills/global_config/bash-script-validator/examples/bad-bash.sh +55 -0
- package/skills/global_config/bash-script-validator/examples/bad-shell.sh +54 -0
- package/skills/global_config/bash-script-validator/examples/good-bash.sh +71 -0
- package/skills/global_config/bash-script-validator/examples/good-shell.sh +69 -0
- package/skills/global_config/bash-script-validator/scripts/run_ci_checks.sh +23 -0
- package/skills/global_config/bash-script-validator/scripts/shellcheck_wrapper.sh +174 -0
- package/skills/global_config/bash-script-validator/scripts/test_validate.sh +446 -0
- package/skills/global_config/bash-script-validator/scripts/validate.sh +512 -0
- package/skills/global_config/ci-pipeline/SKILL.md +135 -0
- package/skills/global_config/dispatching-parallel-agents/SKILL.md +170 -0
- package/skills/global_config/dockerfile-generator/SKILL.md +1038 -0
- package/skills/global_config/dockerfile-generator/examples/example.dockerignore +95 -0
- package/skills/global_config/dockerfile-generator/examples/golang-distroless.Dockerfile +34 -0
- package/skills/global_config/dockerfile-generator/examples/java-springboot.Dockerfile +45 -0
- package/skills/global_config/dockerfile-generator/examples/nextjs-production.Dockerfile +49 -0
- package/skills/global_config/dockerfile-generator/examples/nodejs-multistage.Dockerfile +55 -0
- package/skills/global_config/dockerfile-generator/examples/python-fastapi.Dockerfile +48 -0
- package/skills/global_config/dockerfile-generator/references/language_specific_guides.md +510 -0
- package/skills/global_config/dockerfile-generator/references/multistage_builds.md +570 -0
- package/skills/global_config/dockerfile-generator/references/optimization_patterns.md +492 -0
- package/skills/global_config/dockerfile-generator/references/security_best_practices.md +375 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_dockerignore.sh +199 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_golang.sh +172 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_java.sh +185 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_nodejs.sh +279 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_python.sh +218 -0
- package/skills/global_config/dockerfile-generator/scripts/test_generator.sh +210 -0
- package/skills/global_config/dockerfile-validator/SKILL.md +300 -0
- package/skills/global_config/dockerfile-validator/examples/.dockerignore.example +34 -0
- package/skills/global_config/dockerfile-validator/examples/bad-example.Dockerfile +37 -0
- package/skills/global_config/dockerfile-validator/examples/golang-distroless.Dockerfile +50 -0
- package/skills/global_config/dockerfile-validator/examples/good-example.Dockerfile +52 -0
- package/skills/global_config/dockerfile-validator/examples/python-optimized.Dockerfile +53 -0
- package/skills/global_config/dockerfile-validator/examples/security-issues.Dockerfile +42 -0
- package/skills/global_config/dockerfile-validator/references/docker_best_practices.md +348 -0
- package/skills/global_config/dockerfile-validator/references/optimization_guide.md +473 -0
- package/skills/global_config/dockerfile-validator/references/security_checklist.md +208 -0
- package/skills/global_config/dockerfile-validator/scripts/dockerfile-validate.sh +699 -0
- package/skills/global_config/dockerfile-validator/scripts/test_validate.sh +35 -0
- package/skills/global_config/dockerfile-validator/tests/fixtures/copy-before-yarn-lock-read.Dockerfile +6 -0
- package/skills/global_config/dockerfile-validator/tests/fixtures/copy-before-yarn.Dockerfile +6 -0
- package/skills/global_config/dockerfile-validator/tests/fixtures/from-platform-nonroot.Dockerfile +7 -0
- package/skills/global_config/dockerfile-validator/tests/test_regression.sh +164 -0
- package/skills/global_config/finishing-a-development-branch/SKILL.md +228 -0
- package/skills/global_config/github-actions-generator/SKILL.md +353 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/composite/action.yml +82 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/docker/Dockerfile +25 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/docker/action.yml +42 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/docker/entrypoint.sh +27 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/javascript/action.yml +33 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/javascript/index.js +50 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/javascript/package.json +27 -0
- package/skills/global_config/github-actions-generator/assets/templates/workflow/basic_workflow.yml +242 -0
- package/skills/global_config/github-actions-generator/assets/templates/workflow/reusable_workflow.yml +106 -0
- package/skills/global_config/github-actions-generator/examples/README.md +147 -0
- package/skills/global_config/github-actions-generator/examples/actions/setup-node-cached/action.yml +93 -0
- package/skills/global_config/github-actions-generator/examples/caching/docker-buildkit.yml +256 -0
- package/skills/global_config/github-actions-generator/examples/security/dependency-review.yml +62 -0
- package/skills/global_config/github-actions-generator/examples/security/sbom-attestation.yml +119 -0
- package/skills/global_config/github-actions-generator/examples/triggers/chatops-commands.yml +475 -0
- package/skills/global_config/github-actions-generator/examples/triggers/repository-dispatch.yml +418 -0
- package/skills/global_config/github-actions-generator/examples/triggers/workflow-orchestration.yml +404 -0
- package/skills/global_config/github-actions-generator/examples/workflows/docker-build-push.yml +68 -0
- package/skills/global_config/github-actions-generator/examples/workflows/go-ci.yml +161 -0
- package/skills/global_config/github-actions-generator/examples/workflows/monorepo-ci.yml +340 -0
- package/skills/global_config/github-actions-generator/examples/workflows/multi-environment-deploy.yml +406 -0
- package/skills/global_config/github-actions-generator/examples/workflows/nodejs-ci.yml +122 -0
- package/skills/global_config/github-actions-generator/examples/workflows/python-ci.yml +157 -0
- package/skills/global_config/github-actions-generator/examples/workflows/scheduled-tasks.yml +376 -0
- package/skills/global_config/github-actions-generator/references/advanced-triggers.md +917 -0
- package/skills/global_config/github-actions-generator/references/best-practices.md +755 -0
- package/skills/global_config/github-actions-generator/references/common-actions.md +715 -0
- package/skills/global_config/github-actions-generator/references/custom-actions.md +320 -0
- package/skills/global_config/github-actions-generator/references/expressions-and-contexts.md +688 -0
- package/skills/global_config/github-actions-generator/references/modern-features.md +421 -0
- package/skills/global_config/github-actions-generator/scripts/test_generator.sh +344 -0
- package/skills/global_config/github-actions-templates/SKILL.md +7 -0
- package/skills/global_config/github-actions-validator/SKILL.md +576 -0
- package/skills/global_config/github-actions-validator/examples/README.md +88 -0
- package/skills/global_config/github-actions-validator/examples/outdated-versions.yml +76 -0
- package/skills/global_config/github-actions-validator/examples/valid-ci.yml +79 -0
- package/skills/global_config/github-actions-validator/examples/with-errors.yml +47 -0
- package/skills/global_config/github-actions-validator/references/act_usage.md +233 -0
- package/skills/global_config/github-actions-validator/references/action_versions.md +122 -0
- package/skills/global_config/github-actions-validator/references/actionlint_usage.md +343 -0
- package/skills/global_config/github-actions-validator/references/common_errors.md +512 -0
- package/skills/global_config/github-actions-validator/references/modern_features.md +384 -0
- package/skills/global_config/github-actions-validator/references/runners.md +317 -0
- package/skills/global_config/github-actions-validator/scripts/install_tools.sh +113 -0
- package/skills/global_config/github-actions-validator/scripts/validate_workflow.sh +910 -0
- package/skills/global_config/github-actions-validator/tests/test_validate_workflow.sh +237 -0
- package/skills/global_config/makefile-generator/SKILL.md +614 -0
- package/skills/global_config/makefile-generator/assets/templates/.gitkeep +1 -0
- package/skills/global_config/makefile-generator/docs/makefile-structure.md +530 -0
- package/skills/global_config/makefile-generator/docs/optimization-guide.md +784 -0
- package/skills/global_config/makefile-generator/docs/patterns-guide.md +642 -0
- package/skills/global_config/makefile-generator/docs/security-guide.md +361 -0
- package/skills/global_config/makefile-generator/docs/targets-guide.md +642 -0
- package/skills/global_config/makefile-generator/docs/variables-guide.md +596 -0
- package/skills/global_config/makefile-generator/scripts/add_standard_targets.sh +539 -0
- package/skills/global_config/makefile-generator/scripts/generate_makefile_template.sh +690 -0
- package/skills/global_config/makefile-generator/test/test_helper_scripts.sh +190 -0
- package/skills/global_config/makefile-validator/SKILL.md +244 -0
- package/skills/global_config/makefile-validator/docs/bake-tool.md +1000 -0
- package/skills/global_config/makefile-validator/docs/best-practices.md +858 -0
- package/skills/global_config/makefile-validator/docs/common-mistakes.md +944 -0
- package/skills/global_config/makefile-validator/examples/bad-makefile.mk +77 -0
- package/skills/global_config/makefile-validator/examples/good-makefile.mk +103 -0
- package/skills/global_config/makefile-validator/scripts/test_validate.sh +382 -0
- package/skills/global_config/makefile-validator/scripts/validate_makefile.sh +712 -0
- package/skills/global_config/{MCP_Manage → mcp-manage}/SKILL.md +3 -3
- package/skills/global_config/requesting-code-review/SKILL.md +98 -0
- package/skills/global_config/requesting-code-review/code-reviewer.md +198 -0
- package/skills/global_config/using-git-worktrees/SKILL.md +170 -0
- package/skills/global_config/verification-before-completion/SKILL.md +123 -0
- package/skills/global_config/writing-plans/SKILL.md +126 -46
- package/skills/global_config/writing-plans-legacy/SKILL.md +139 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Generate a production-ready Go Dockerfile with multi-stage build
|
|
3
|
+
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
# Default values
|
|
7
|
+
GO_VERSION="${GO_VERSION:-1.21}"
|
|
8
|
+
PORT="${PORT:-8080}"
|
|
9
|
+
OUTPUT_FILE="${OUTPUT_FILE:-Dockerfile}"
|
|
10
|
+
BINARY_NAME="${BINARY_NAME:-app}"
|
|
11
|
+
USE_DISTROLESS="${USE_DISTROLESS:-true}"
|
|
12
|
+
|
|
13
|
+
# Usage
|
|
14
|
+
usage() {
|
|
15
|
+
cat <<EOF
|
|
16
|
+
Usage: $0 [OPTIONS]
|
|
17
|
+
|
|
18
|
+
Generate a production-ready Go Dockerfile with multi-stage build.
|
|
19
|
+
|
|
20
|
+
OPTIONS:
|
|
21
|
+
-v, --version VERSION Go version (default: 1.21)
|
|
22
|
+
-p, --port PORT Port to expose (default: 8080)
|
|
23
|
+
-o, --output FILE Output file (default: Dockerfile)
|
|
24
|
+
-b, --binary NAME Binary name (default: app)
|
|
25
|
+
--alpine Use Alpine instead of distroless
|
|
26
|
+
-h, --help Show this help message
|
|
27
|
+
|
|
28
|
+
EXAMPLES:
|
|
29
|
+
# Basic Go app with distroless
|
|
30
|
+
$0
|
|
31
|
+
|
|
32
|
+
# Go app with Alpine base
|
|
33
|
+
$0 --alpine --port 8080
|
|
34
|
+
|
|
35
|
+
# Custom binary name
|
|
36
|
+
$0 --binary myapp --version 1.22
|
|
37
|
+
|
|
38
|
+
EOF
|
|
39
|
+
exit 0
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
# Parse arguments
|
|
43
|
+
while [[ $# -gt 0 ]]; do
|
|
44
|
+
case $1 in
|
|
45
|
+
-v|--version)
|
|
46
|
+
GO_VERSION="$2"
|
|
47
|
+
shift 2
|
|
48
|
+
;;
|
|
49
|
+
-p|--port)
|
|
50
|
+
PORT="$2"
|
|
51
|
+
shift 2
|
|
52
|
+
;;
|
|
53
|
+
-o|--output)
|
|
54
|
+
OUTPUT_FILE="$2"
|
|
55
|
+
shift 2
|
|
56
|
+
;;
|
|
57
|
+
-b|--binary)
|
|
58
|
+
BINARY_NAME="$2"
|
|
59
|
+
shift 2
|
|
60
|
+
;;
|
|
61
|
+
--alpine)
|
|
62
|
+
USE_DISTROLESS="false"
|
|
63
|
+
shift
|
|
64
|
+
;;
|
|
65
|
+
-h|--help)
|
|
66
|
+
usage
|
|
67
|
+
;;
|
|
68
|
+
*)
|
|
69
|
+
echo "Unknown option: $1"
|
|
70
|
+
usage
|
|
71
|
+
;;
|
|
72
|
+
esac
|
|
73
|
+
done
|
|
74
|
+
|
|
75
|
+
# Generate Dockerfile based on base image choice
|
|
76
|
+
if [ "$USE_DISTROLESS" = "true" ]; then
|
|
77
|
+
cat > "$OUTPUT_FILE" <<'EOF'
|
|
78
|
+
# syntax=docker/dockerfile:1
|
|
79
|
+
|
|
80
|
+
# Build stage
|
|
81
|
+
FROM golang:GO_VERSION-alpine AS builder
|
|
82
|
+
WORKDIR /app
|
|
83
|
+
|
|
84
|
+
# Copy go mod files
|
|
85
|
+
COPY go.mod go.sum ./
|
|
86
|
+
RUN go mod download
|
|
87
|
+
|
|
88
|
+
# Copy source code
|
|
89
|
+
COPY . .
|
|
90
|
+
|
|
91
|
+
# Build the application
|
|
92
|
+
RUN CGO_ENABLED=0 GOOS=linux go build -a -ldflags="-s -w" -o /BINARY_NAME .
|
|
93
|
+
|
|
94
|
+
# Production stage (using distroless for minimal image)
|
|
95
|
+
# gcr.io/distroless/static-debian12 IS a specific tag; hadolint DL3006 is a
|
|
96
|
+
# false positive for non-Docker-Hub registries.
|
|
97
|
+
# hadolint ignore=DL3006
|
|
98
|
+
FROM gcr.io/distroless/static-debian12 AS production
|
|
99
|
+
WORKDIR /
|
|
100
|
+
|
|
101
|
+
# Copy binary from builder
|
|
102
|
+
COPY --from=builder /BINARY_NAME /BINARY_NAME
|
|
103
|
+
|
|
104
|
+
# Expose port
|
|
105
|
+
EXPOSE PORT_NUMBER
|
|
106
|
+
|
|
107
|
+
# Switch to non-root user (distroless runs as nonroot by default)
|
|
108
|
+
USER nonroot:nonroot
|
|
109
|
+
|
|
110
|
+
# Start application
|
|
111
|
+
ENTRYPOINT ["/BINARY_NAME"]
|
|
112
|
+
EOF
|
|
113
|
+
else
|
|
114
|
+
cat > "$OUTPUT_FILE" <<'EOF'
|
|
115
|
+
# syntax=docker/dockerfile:1
|
|
116
|
+
|
|
117
|
+
# Build stage
|
|
118
|
+
FROM golang:GO_VERSION-alpine AS builder
|
|
119
|
+
WORKDIR /app
|
|
120
|
+
|
|
121
|
+
# Copy go mod files
|
|
122
|
+
COPY go.mod go.sum ./
|
|
123
|
+
RUN go mod download
|
|
124
|
+
|
|
125
|
+
# Copy source code
|
|
126
|
+
COPY . .
|
|
127
|
+
|
|
128
|
+
# Build the application
|
|
129
|
+
RUN CGO_ENABLED=0 GOOS=linux go build -a -ldflags="-s -w" -o /BINARY_NAME .
|
|
130
|
+
|
|
131
|
+
# Production stage (using Alpine)
|
|
132
|
+
FROM alpine:3.21 AS production
|
|
133
|
+
WORKDIR /app
|
|
134
|
+
|
|
135
|
+
# Install ca-certificates for HTTPS
|
|
136
|
+
RUN apk --no-cache add ca-certificates
|
|
137
|
+
|
|
138
|
+
# Create non-root user
|
|
139
|
+
RUN addgroup -g 1001 -S appgroup && \
|
|
140
|
+
adduser -S app -u 1001 -G appgroup
|
|
141
|
+
|
|
142
|
+
# Copy binary from builder
|
|
143
|
+
COPY --from=builder /BINARY_NAME /app/BINARY_NAME
|
|
144
|
+
|
|
145
|
+
# Switch to non-root user
|
|
146
|
+
USER app
|
|
147
|
+
|
|
148
|
+
# Expose port
|
|
149
|
+
EXPOSE PORT_NUMBER
|
|
150
|
+
|
|
151
|
+
# Health check
|
|
152
|
+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
153
|
+
CMD wget --no-verbose --tries=1 --spider http://localhost:PORT_NUMBER/health || exit 1
|
|
154
|
+
|
|
155
|
+
# Start application
|
|
156
|
+
ENTRYPOINT ["/app/BINARY_NAME"]
|
|
157
|
+
EOF
|
|
158
|
+
fi
|
|
159
|
+
|
|
160
|
+
# Replace placeholders
|
|
161
|
+
sed -i.bak "s/GO_VERSION/$GO_VERSION/g" "$OUTPUT_FILE"
|
|
162
|
+
sed -i.bak "s/PORT_NUMBER/$PORT/g" "$OUTPUT_FILE"
|
|
163
|
+
sed -i.bak "s/BINARY_NAME/$BINARY_NAME/g" "$OUTPUT_FILE"
|
|
164
|
+
|
|
165
|
+
# Clean up backup files
|
|
166
|
+
rm -f "${OUTPUT_FILE}.bak"
|
|
167
|
+
|
|
168
|
+
echo "✓ Generated Go Dockerfile: $OUTPUT_FILE"
|
|
169
|
+
echo " Go version: $GO_VERSION"
|
|
170
|
+
echo " Port: $PORT"
|
|
171
|
+
echo " Binary name: $BINARY_NAME"
|
|
172
|
+
echo " Base image: $([ "$USE_DISTROLESS" = "true" ] && echo "distroless" || echo "alpine")"
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Generate a production-ready Java Dockerfile with multi-stage build
|
|
3
|
+
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
# Default values
|
|
7
|
+
JAVA_VERSION="${JAVA_VERSION:-21}"
|
|
8
|
+
PORT="${PORT:-8080}"
|
|
9
|
+
OUTPUT_FILE="${OUTPUT_FILE:-Dockerfile}"
|
|
10
|
+
BUILD_TOOL="${BUILD_TOOL:-maven}"
|
|
11
|
+
|
|
12
|
+
# Usage
|
|
13
|
+
usage() {
|
|
14
|
+
cat <<EOF
|
|
15
|
+
Usage: $0 [OPTIONS]
|
|
16
|
+
|
|
17
|
+
Generate a production-ready Java Dockerfile with multi-stage build.
|
|
18
|
+
|
|
19
|
+
OPTIONS:
|
|
20
|
+
-v, --version VERSION Java version (default: 21)
|
|
21
|
+
-p, --port PORT Port to expose (default: 8080)
|
|
22
|
+
-o, --output FILE Output file (default: Dockerfile)
|
|
23
|
+
-t, --tool TOOL Build tool: maven or gradle (default: maven)
|
|
24
|
+
-h, --help Show this help message
|
|
25
|
+
|
|
26
|
+
EXAMPLES:
|
|
27
|
+
# Spring Boot with Maven
|
|
28
|
+
$0
|
|
29
|
+
|
|
30
|
+
# Spring Boot with Gradle
|
|
31
|
+
$0 --tool gradle --version 21
|
|
32
|
+
|
|
33
|
+
# Custom port
|
|
34
|
+
$0 --port 9090 --tool maven
|
|
35
|
+
|
|
36
|
+
EOF
|
|
37
|
+
exit 0
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# Parse arguments
|
|
41
|
+
while [[ $# -gt 0 ]]; do
|
|
42
|
+
case $1 in
|
|
43
|
+
-v|--version)
|
|
44
|
+
JAVA_VERSION="$2"
|
|
45
|
+
shift 2
|
|
46
|
+
;;
|
|
47
|
+
-p|--port)
|
|
48
|
+
PORT="$2"
|
|
49
|
+
shift 2
|
|
50
|
+
;;
|
|
51
|
+
-o|--output)
|
|
52
|
+
OUTPUT_FILE="$2"
|
|
53
|
+
shift 2
|
|
54
|
+
;;
|
|
55
|
+
-t|--tool)
|
|
56
|
+
BUILD_TOOL="$2"
|
|
57
|
+
shift 2
|
|
58
|
+
;;
|
|
59
|
+
-h|--help)
|
|
60
|
+
usage
|
|
61
|
+
;;
|
|
62
|
+
*)
|
|
63
|
+
echo "Unknown option: $1"
|
|
64
|
+
usage
|
|
65
|
+
;;
|
|
66
|
+
esac
|
|
67
|
+
done
|
|
68
|
+
|
|
69
|
+
# Validate build tool
|
|
70
|
+
if [ "$BUILD_TOOL" != "maven" ] && [ "$BUILD_TOOL" != "gradle" ]; then
|
|
71
|
+
echo "Error: Build tool must be 'maven' or 'gradle'"
|
|
72
|
+
exit 1
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
# Generate Dockerfile based on build tool
|
|
76
|
+
if [ "$BUILD_TOOL" = "maven" ]; then
|
|
77
|
+
cat > "$OUTPUT_FILE" <<'EOF'
|
|
78
|
+
# syntax=docker/dockerfile:1
|
|
79
|
+
|
|
80
|
+
# Build stage
|
|
81
|
+
FROM eclipse-temurin:JAVA_VERSION-jdk-jammy AS builder
|
|
82
|
+
WORKDIR /app
|
|
83
|
+
|
|
84
|
+
# Copy Maven wrapper and pom.xml
|
|
85
|
+
COPY mvnw pom.xml ./
|
|
86
|
+
COPY .mvn .mvn
|
|
87
|
+
|
|
88
|
+
# Download dependencies (cached layer)
|
|
89
|
+
RUN ./mvnw dependency:go-offline
|
|
90
|
+
|
|
91
|
+
# Copy source code
|
|
92
|
+
COPY src ./src
|
|
93
|
+
|
|
94
|
+
# Build application
|
|
95
|
+
RUN ./mvnw clean package -DskipTests && \
|
|
96
|
+
mv target/*.jar target/app.jar
|
|
97
|
+
|
|
98
|
+
# Production stage (using JRE instead of JDK)
|
|
99
|
+
FROM eclipse-temurin:JAVA_VERSION-jre-jammy AS production
|
|
100
|
+
WORKDIR /app
|
|
101
|
+
|
|
102
|
+
# Install healthcheck dependency and create non-root user
|
|
103
|
+
# hadolint ignore=DL3008
|
|
104
|
+
RUN apt-get update && apt-get install -y --no-install-recommends curl && \
|
|
105
|
+
rm -rf /var/lib/apt/lists/* && \
|
|
106
|
+
useradd -m -u 1001 app
|
|
107
|
+
|
|
108
|
+
# Copy JAR from builder
|
|
109
|
+
COPY --from=builder --chown=app:app /app/target/app.jar ./app.jar
|
|
110
|
+
|
|
111
|
+
# Switch to non-root user
|
|
112
|
+
USER app
|
|
113
|
+
|
|
114
|
+
# Expose port
|
|
115
|
+
EXPOSE PORT_NUMBER
|
|
116
|
+
|
|
117
|
+
# Health check
|
|
118
|
+
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
|
|
119
|
+
CMD curl -f http://localhost:PORT_NUMBER/actuator/health || exit 1
|
|
120
|
+
|
|
121
|
+
# Start application
|
|
122
|
+
ENTRYPOINT ["java", "-jar", "app.jar"]
|
|
123
|
+
EOF
|
|
124
|
+
else
|
|
125
|
+
cat > "$OUTPUT_FILE" <<'EOF'
|
|
126
|
+
# syntax=docker/dockerfile:1
|
|
127
|
+
|
|
128
|
+
# Build stage
|
|
129
|
+
FROM eclipse-temurin:JAVA_VERSION-jdk-jammy AS builder
|
|
130
|
+
WORKDIR /app
|
|
131
|
+
|
|
132
|
+
# Copy Gradle wrapper and build files
|
|
133
|
+
COPY gradlew ./
|
|
134
|
+
COPY gradle gradle
|
|
135
|
+
COPY build.gradle settings.gradle ./
|
|
136
|
+
|
|
137
|
+
# Download dependencies (cached layer)
|
|
138
|
+
RUN ./gradlew dependencies --no-daemon
|
|
139
|
+
|
|
140
|
+
# Copy source code
|
|
141
|
+
COPY src ./src
|
|
142
|
+
|
|
143
|
+
# Build application
|
|
144
|
+
RUN ./gradlew build -x test --no-daemon && \
|
|
145
|
+
mv build/libs/*.jar build/libs/app.jar
|
|
146
|
+
|
|
147
|
+
# Production stage (using JRE instead of JDK)
|
|
148
|
+
FROM eclipse-temurin:JAVA_VERSION-jre-jammy AS production
|
|
149
|
+
WORKDIR /app
|
|
150
|
+
|
|
151
|
+
# Install healthcheck dependency and create non-root user
|
|
152
|
+
# hadolint ignore=DL3008
|
|
153
|
+
RUN apt-get update && apt-get install -y --no-install-recommends curl && \
|
|
154
|
+
rm -rf /var/lib/apt/lists/* && \
|
|
155
|
+
useradd -m -u 1001 app
|
|
156
|
+
|
|
157
|
+
# Copy JAR from builder
|
|
158
|
+
COPY --from=builder --chown=app:app /app/build/libs/app.jar ./app.jar
|
|
159
|
+
|
|
160
|
+
# Switch to non-root user
|
|
161
|
+
USER app
|
|
162
|
+
|
|
163
|
+
# Expose port
|
|
164
|
+
EXPOSE PORT_NUMBER
|
|
165
|
+
|
|
166
|
+
# Health check
|
|
167
|
+
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
|
|
168
|
+
CMD curl -f http://localhost:PORT_NUMBER/actuator/health || exit 1
|
|
169
|
+
|
|
170
|
+
# Start application
|
|
171
|
+
ENTRYPOINT ["java", "-jar", "app.jar"]
|
|
172
|
+
EOF
|
|
173
|
+
fi
|
|
174
|
+
|
|
175
|
+
# Replace placeholders
|
|
176
|
+
sed -i.bak "s/JAVA_VERSION/$JAVA_VERSION/g" "$OUTPUT_FILE"
|
|
177
|
+
sed -i.bak "s/PORT_NUMBER/$PORT/g" "$OUTPUT_FILE"
|
|
178
|
+
|
|
179
|
+
# Clean up backup files
|
|
180
|
+
rm -f "${OUTPUT_FILE}.bak"
|
|
181
|
+
|
|
182
|
+
echo "✓ Generated Java Dockerfile: $OUTPUT_FILE"
|
|
183
|
+
echo " Java version: $JAVA_VERSION"
|
|
184
|
+
echo " Port: $PORT"
|
|
185
|
+
echo " Build tool: $BUILD_TOOL"
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Generate a production-ready Node.js Dockerfile with multi-stage build
|
|
3
|
+
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
# Default values
|
|
7
|
+
NODE_VERSION="${NODE_VERSION:-20}"
|
|
8
|
+
PORT="${PORT:-3000}"
|
|
9
|
+
OUTPUT_FILE="${OUTPUT_FILE:-Dockerfile}"
|
|
10
|
+
LEGACY_ENTRY="${APP_ENTRY:-index.js}"
|
|
11
|
+
LEGACY_ENTRY_SET="false"
|
|
12
|
+
ENTRY_CMD="${ENTRY_CMD:-}"
|
|
13
|
+
ENTRY_ARGS=()
|
|
14
|
+
BUILD_STAGE="${BUILD_STAGE:-false}"
|
|
15
|
+
|
|
16
|
+
# Usage
|
|
17
|
+
usage() {
|
|
18
|
+
cat <<EOF
|
|
19
|
+
Usage: $0 [OPTIONS]
|
|
20
|
+
|
|
21
|
+
Generate a production-ready Node.js Dockerfile with multi-stage build.
|
|
22
|
+
|
|
23
|
+
OPTIONS:
|
|
24
|
+
-v, --version VERSION Node.js version (default: 20)
|
|
25
|
+
-p, --port PORT Port to expose (default: 3000)
|
|
26
|
+
-o, --output FILE Output file (default: Dockerfile)
|
|
27
|
+
-e, --entry COMMAND Legacy entry syntax (simple whitespace split only)
|
|
28
|
+
--entry-cmd COMMAND Preferred command binary/executable
|
|
29
|
+
--entry-arg ARG Preferred command argument (repeatable; preserves spaces)
|
|
30
|
+
-b, --build Include build stage for compilation (installs all deps, runs npm run build, prunes dev deps)
|
|
31
|
+
-h, --help Show this help message
|
|
32
|
+
|
|
33
|
+
EXAMPLES:
|
|
34
|
+
# Basic Node.js app
|
|
35
|
+
$0
|
|
36
|
+
|
|
37
|
+
# Next.js app with build stage
|
|
38
|
+
$0 --version 20 --port 3000 --build --entry "npm start"
|
|
39
|
+
|
|
40
|
+
# Preferred structured entrypoint (preserves quoted args exactly)
|
|
41
|
+
$0 --entry-cmd node --entry-arg server.js --entry-arg --message --entry-arg "hello world"
|
|
42
|
+
|
|
43
|
+
# Custom port and legacy entry point
|
|
44
|
+
$0 --port 8080 --entry "server.js"
|
|
45
|
+
|
|
46
|
+
EOF
|
|
47
|
+
exit 0
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# Parse arguments
|
|
51
|
+
while [[ $# -gt 0 ]]; do
|
|
52
|
+
case $1 in
|
|
53
|
+
-v|--version)
|
|
54
|
+
NODE_VERSION="$2"
|
|
55
|
+
shift 2
|
|
56
|
+
;;
|
|
57
|
+
-p|--port)
|
|
58
|
+
PORT="$2"
|
|
59
|
+
shift 2
|
|
60
|
+
;;
|
|
61
|
+
-o|--output)
|
|
62
|
+
OUTPUT_FILE="$2"
|
|
63
|
+
shift 2
|
|
64
|
+
;;
|
|
65
|
+
-e|--entry)
|
|
66
|
+
LEGACY_ENTRY="$2"
|
|
67
|
+
LEGACY_ENTRY_SET="true"
|
|
68
|
+
shift 2
|
|
69
|
+
;;
|
|
70
|
+
--entry-cmd)
|
|
71
|
+
ENTRY_CMD="$2"
|
|
72
|
+
shift 2
|
|
73
|
+
;;
|
|
74
|
+
--entry-arg)
|
|
75
|
+
ENTRY_ARGS+=("$2")
|
|
76
|
+
shift 2
|
|
77
|
+
;;
|
|
78
|
+
-b|--build)
|
|
79
|
+
BUILD_STAGE="true"
|
|
80
|
+
shift
|
|
81
|
+
;;
|
|
82
|
+
-h|--help)
|
|
83
|
+
usage
|
|
84
|
+
;;
|
|
85
|
+
*)
|
|
86
|
+
echo "Unknown option: $1"
|
|
87
|
+
usage
|
|
88
|
+
;;
|
|
89
|
+
esac
|
|
90
|
+
done
|
|
91
|
+
|
|
92
|
+
# Escape values that are inserted into JSON-form CMD arrays.
|
|
93
|
+
escape_json_string() {
|
|
94
|
+
local input="$1"
|
|
95
|
+
input="${input//\\/\\\\}"
|
|
96
|
+
input="${input//\"/\\\"}"
|
|
97
|
+
printf '%s' "$input"
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# Escape values that are inserted into sed replacement strings.
|
|
101
|
+
escape_sed_replacement() {
|
|
102
|
+
local input="$1"
|
|
103
|
+
input="${input//\\/\\\\}"
|
|
104
|
+
input="${input//&/\\&}"
|
|
105
|
+
input="${input//|/\\|}"
|
|
106
|
+
printf '%s' "$input"
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
# Validate mutually exclusive entrypoint interfaces.
|
|
110
|
+
if [[ -n "$ENTRY_CMD" && "$LEGACY_ENTRY_SET" == "true" ]]; then
|
|
111
|
+
echo "ERROR: use either --entry or --entry-cmd/--entry-arg, not both." >&2
|
|
112
|
+
exit 1
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
if [[ -z "$ENTRY_CMD" && ${#ENTRY_ARGS[@]} -gt 0 ]]; then
|
|
116
|
+
echo "ERROR: --entry-arg requires --entry-cmd." >&2
|
|
117
|
+
exit 1
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
# Build CMD instruction.
|
|
121
|
+
# Preferred mode:
|
|
122
|
+
# --entry-cmd <cmd> --entry-arg <arg> --entry-arg <arg>
|
|
123
|
+
# Legacy mode:
|
|
124
|
+
# --entry "<simple whitespace-delimited command>"
|
|
125
|
+
# Quoted legacy entries are rejected because they cannot be parsed safely.
|
|
126
|
+
if [[ -n "$ENTRY_CMD" ]]; then
|
|
127
|
+
CMD_PARTS=("$ENTRY_CMD" "${ENTRY_ARGS[@]}")
|
|
128
|
+
else
|
|
129
|
+
if [[ "$LEGACY_ENTRY" == *"\""* || "$LEGACY_ENTRY" == *"'"* ]]; then
|
|
130
|
+
echo "ERROR: quoted --entry values are not supported. Use --entry-cmd/--entry-arg." >&2
|
|
131
|
+
exit 1
|
|
132
|
+
fi
|
|
133
|
+
|
|
134
|
+
if [[ "$LEGACY_ENTRY" =~ [[:space:]] ]]; then
|
|
135
|
+
read -r -a CMD_PARTS <<< "$LEGACY_ENTRY"
|
|
136
|
+
else
|
|
137
|
+
CMD_PARTS=("node" "$LEGACY_ENTRY")
|
|
138
|
+
fi
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
if [[ -z "${CMD_PARTS[0]:-}" ]]; then
|
|
142
|
+
echo "ERROR: entry command cannot be empty." >&2
|
|
143
|
+
exit 1
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
_json_parts=()
|
|
147
|
+
for _token in "${CMD_PARTS[@]}"; do
|
|
148
|
+
_json_parts+=("\"$(escape_json_string "$_token")\"")
|
|
149
|
+
done
|
|
150
|
+
CMD_INSTRUCTION="CMD [$(IFS=', '; echo "${_json_parts[*]}")]"
|
|
151
|
+
CMD_INSTRUCTION_SED="$(escape_sed_replacement "$CMD_INSTRUCTION")"
|
|
152
|
+
|
|
153
|
+
# Generate Dockerfile — two templates to avoid complex sed escaping around &&.
|
|
154
|
+
# The build template installs ALL deps (including dev) so that build tools like
|
|
155
|
+
# tsc, vite, webpack etc. are available, then prunes dev deps after the build so
|
|
156
|
+
# the production stage receives a clean node_modules.
|
|
157
|
+
if [ "$BUILD_STAGE" = "true" ]; then
|
|
158
|
+
cat > "$OUTPUT_FILE" <<'EOF'
|
|
159
|
+
# syntax=docker/dockerfile:1
|
|
160
|
+
|
|
161
|
+
# Build stage — install all deps (including devDependencies) required by the
|
|
162
|
+
# build step, compile the application, then prune to production-only deps.
|
|
163
|
+
FROM node:NODE_VERSION-alpine AS builder
|
|
164
|
+
WORKDIR /app
|
|
165
|
+
|
|
166
|
+
# Copy dependency files for caching
|
|
167
|
+
COPY package*.json ./
|
|
168
|
+
|
|
169
|
+
# Install all dependencies (including devDependencies needed for build)
|
|
170
|
+
RUN npm ci && \
|
|
171
|
+
npm cache clean --force
|
|
172
|
+
|
|
173
|
+
# Copy application code
|
|
174
|
+
COPY . .
|
|
175
|
+
|
|
176
|
+
# Build application and prune dev dependencies so the production stage
|
|
177
|
+
# receives only what is needed at runtime.
|
|
178
|
+
RUN npm run build && \
|
|
179
|
+
npm prune --omit=dev
|
|
180
|
+
|
|
181
|
+
# Production stage
|
|
182
|
+
FROM node:NODE_VERSION-alpine AS production
|
|
183
|
+
WORKDIR /app
|
|
184
|
+
|
|
185
|
+
# Set production environment
|
|
186
|
+
ENV NODE_ENV=production
|
|
187
|
+
|
|
188
|
+
# Create non-root user
|
|
189
|
+
RUN addgroup -g 1001 -S nodejs && \
|
|
190
|
+
adduser -S nodejs -u 1001
|
|
191
|
+
|
|
192
|
+
# Copy pruned node_modules and built application from builder
|
|
193
|
+
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
|
|
194
|
+
COPY --from=builder --chown=nodejs:nodejs /app .
|
|
195
|
+
|
|
196
|
+
# Switch to non-root user
|
|
197
|
+
USER nodejs
|
|
198
|
+
|
|
199
|
+
# Expose port
|
|
200
|
+
EXPOSE PORT_NUMBER
|
|
201
|
+
|
|
202
|
+
# Health check
|
|
203
|
+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
204
|
+
CMD node -e "require('http').get('http://localhost:PORT_NUMBER/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})" || exit 1
|
|
205
|
+
|
|
206
|
+
# Start application
|
|
207
|
+
CMD_INSTRUCTION_PLACEHOLDER
|
|
208
|
+
EOF
|
|
209
|
+
else
|
|
210
|
+
cat > "$OUTPUT_FILE" <<'EOF'
|
|
211
|
+
# syntax=docker/dockerfile:1
|
|
212
|
+
|
|
213
|
+
# Build stage
|
|
214
|
+
FROM node:NODE_VERSION-alpine AS builder
|
|
215
|
+
WORKDIR /app
|
|
216
|
+
|
|
217
|
+
# Copy dependency files for caching
|
|
218
|
+
COPY package*.json ./
|
|
219
|
+
|
|
220
|
+
# Install production dependencies only
|
|
221
|
+
RUN npm ci --omit=dev && \
|
|
222
|
+
npm cache clean --force
|
|
223
|
+
|
|
224
|
+
# Copy application code
|
|
225
|
+
COPY . .
|
|
226
|
+
|
|
227
|
+
# Production stage
|
|
228
|
+
FROM node:NODE_VERSION-alpine AS production
|
|
229
|
+
WORKDIR /app
|
|
230
|
+
|
|
231
|
+
# Set production environment
|
|
232
|
+
ENV NODE_ENV=production
|
|
233
|
+
|
|
234
|
+
# Create non-root user
|
|
235
|
+
RUN addgroup -g 1001 -S nodejs && \
|
|
236
|
+
adduser -S nodejs -u 1001
|
|
237
|
+
|
|
238
|
+
# Copy dependencies from builder
|
|
239
|
+
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
|
|
240
|
+
|
|
241
|
+
# Copy application from builder
|
|
242
|
+
COPY --chown=nodejs:nodejs . .
|
|
243
|
+
|
|
244
|
+
# Switch to non-root user
|
|
245
|
+
USER nodejs
|
|
246
|
+
|
|
247
|
+
# Expose port
|
|
248
|
+
EXPOSE PORT_NUMBER
|
|
249
|
+
|
|
250
|
+
# Health check
|
|
251
|
+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
252
|
+
CMD node -e "require('http').get('http://localhost:PORT_NUMBER/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})" || exit 1
|
|
253
|
+
|
|
254
|
+
# Start application
|
|
255
|
+
CMD_INSTRUCTION_PLACEHOLDER
|
|
256
|
+
EOF
|
|
257
|
+
fi
|
|
258
|
+
|
|
259
|
+
# Replace placeholders
|
|
260
|
+
sed -i.bak "s/NODE_VERSION/$NODE_VERSION/g" "$OUTPUT_FILE"
|
|
261
|
+
sed -i.bak "s/PORT_NUMBER/$PORT/g" "$OUTPUT_FILE"
|
|
262
|
+
sed -i.bak "s|CMD_INSTRUCTION_PLACEHOLDER|$CMD_INSTRUCTION_SED|g" "$OUTPUT_FILE"
|
|
263
|
+
|
|
264
|
+
# Clean up backup files
|
|
265
|
+
rm -f "${OUTPUT_FILE}.bak"
|
|
266
|
+
|
|
267
|
+
echo "✓ Generated Node.js Dockerfile: $OUTPUT_FILE"
|
|
268
|
+
echo " Node version: $NODE_VERSION"
|
|
269
|
+
echo " Port: $PORT"
|
|
270
|
+
if [[ -n "$ENTRY_CMD" ]]; then
|
|
271
|
+
ENTRY_DISPLAY="$ENTRY_CMD"
|
|
272
|
+
for _arg in "${ENTRY_ARGS[@]}"; do
|
|
273
|
+
ENTRY_DISPLAY+=" $(printf '%q' "$_arg")"
|
|
274
|
+
done
|
|
275
|
+
else
|
|
276
|
+
ENTRY_DISPLAY="$LEGACY_ENTRY"
|
|
277
|
+
fi
|
|
278
|
+
echo " Entry point: $ENTRY_DISPLAY"
|
|
279
|
+
echo " Build stage: $BUILD_STAGE"
|