Skip to content

Commit 0d0665c

Browse files
committed
feat: add distroless multi-arch Docker build with security hardening
- Add optimized multi-stage Dockerfile with distroless runtime - Build wheelhouse in base stage, install in venv for portability - Distroless final stage (~311MB vs 542MB before optimization) - Custom entrypoint runs Alembic migrations then Uvicorn - Add GitHub Actions workflow for multi-arch builds (amd64, arm64) - Publishes to GHCR with commit SHA and timestamp tags - Actions pinned to full commit SHAs for security - Security fixes per Codacy analysis - Bump python-jose to 3.4.0 (CVE-2024-33663, CVE-2024-33664) - Bump python-multipart to 0.0.18 (CVE-2024-24762, CVE-2024-53981) - Bump black to 24.3.0 (CVE-2024-21503) - Remove insecure hash algorithms (MD5/SHA1) from helpers - Docker Compose improvements - Remove obsolete version key - Parameterize image name/tag via env vars - Use distroless build target - Makefile enhancements - Add sizes target to show image sizes - Fix duplicate clean rule - Add date-based tagging support - Modernize to use docker compose - Generate ALMOps v4 deliverables (Excel, DOCX, PPTX, ZIP) - Code quality: fix trailing whitespace, unused imports
1 parent e17063c commit 0d0665c

17 files changed

Lines changed: 442 additions & 33 deletions

.codacy/cli.sh

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
#!/usr/bin/env bash
2+
3+
4+
set -e +o pipefail
5+
6+
# Set up paths first
7+
bin_name="codacy-cli-v2"
8+
9+
# Determine OS-specific paths
10+
os_name=$(uname)
11+
arch=$(uname -m)
12+
13+
case "$arch" in
14+
"x86_64")
15+
arch="amd64"
16+
;;
17+
"x86")
18+
arch="386"
19+
;;
20+
"aarch64"|"arm64")
21+
arch="arm64"
22+
;;
23+
esac
24+
25+
if [ -z "$CODACY_CLI_V2_TMP_FOLDER" ]; then
26+
if [ "$(uname)" = "Linux" ]; then
27+
CODACY_CLI_V2_TMP_FOLDER="$HOME/.cache/codacy/codacy-cli-v2"
28+
elif [ "$(uname)" = "Darwin" ]; then
29+
CODACY_CLI_V2_TMP_FOLDER="$HOME/Library/Caches/Codacy/codacy-cli-v2"
30+
else
31+
CODACY_CLI_V2_TMP_FOLDER=".codacy-cli-v2"
32+
fi
33+
fi
34+
35+
version_file="$CODACY_CLI_V2_TMP_FOLDER/version.yaml"
36+
37+
38+
get_version_from_yaml() {
39+
if [ -f "$version_file" ]; then
40+
local version=$(grep -o 'version: *"[^"]*"' "$version_file" | cut -d'"' -f2)
41+
if [ -n "$version" ]; then
42+
echo "$version"
43+
return 0
44+
fi
45+
fi
46+
return 1
47+
}
48+
49+
get_latest_version() {
50+
local response
51+
if [ -n "$GH_TOKEN" ]; then
52+
response=$(curl -Lq --header "Authorization: Bearer $GH_TOKEN" "https://api.github.com/repos/codacy/codacy-cli-v2/releases/latest" 2>/dev/null)
53+
else
54+
response=$(curl -Lq "https://api.github.com/repos/codacy/codacy-cli-v2/releases/latest" 2>/dev/null)
55+
fi
56+
57+
handle_rate_limit "$response"
58+
local version=$(echo "$response" | grep -m 1 tag_name | cut -d'"' -f4)
59+
echo "$version"
60+
}
61+
62+
handle_rate_limit() {
63+
local response="$1"
64+
if echo "$response" | grep -q "API rate limit exceeded"; then
65+
fatal "Error: GitHub API rate limit exceeded. Please try again later"
66+
fi
67+
}
68+
69+
download_file() {
70+
local url="$1"
71+
72+
echo "Downloading from URL: ${url}"
73+
if command -v curl > /dev/null 2>&1; then
74+
curl -# -LS "$url" -O
75+
elif command -v wget > /dev/null 2>&1; then
76+
wget "$url"
77+
else
78+
fatal "Error: Could not find curl or wget, please install one."
79+
fi
80+
}
81+
82+
download() {
83+
local url="$1"
84+
local output_folder="$2"
85+
86+
( cd "$output_folder" && download_file "$url" )
87+
}
88+
89+
download_cli() {
90+
# OS name lower case
91+
suffix=$(echo "$os_name" | tr '[:upper:]' '[:lower:]')
92+
93+
local bin_folder="$1"
94+
local bin_path="$2"
95+
local version="$3"
96+
97+
if [ ! -f "$bin_path" ]; then
98+
echo "📥 Downloading CLI version $version..."
99+
100+
remote_file="codacy-cli-v2_${version}_${suffix}_${arch}.tar.gz"
101+
url="https://github.com/codacy/codacy-cli-v2/releases/download/${version}/${remote_file}"
102+
103+
download "$url" "$bin_folder"
104+
tar xzfv "${bin_folder}/${remote_file}" -C "${bin_folder}"
105+
fi
106+
}
107+
108+
# Warn if CODACY_CLI_V2_VERSION is set and update is requested
109+
if [ -n "$CODACY_CLI_V2_VERSION" ] && [ "$1" = "update" ]; then
110+
echo "⚠️ Warning: Performing update with forced version $CODACY_CLI_V2_VERSION"
111+
echo " Unset CODACY_CLI_V2_VERSION to use the latest version"
112+
fi
113+
114+
# Ensure version.yaml exists and is up to date
115+
if [ ! -f "$version_file" ] || [ "$1" = "update" ]; then
116+
echo "ℹ️ Fetching latest version..."
117+
version=$(get_latest_version)
118+
mkdir -p "$CODACY_CLI_V2_TMP_FOLDER"
119+
echo "version: \"$version\"" > "$version_file"
120+
fi
121+
122+
# Set the version to use
123+
if [ -n "$CODACY_CLI_V2_VERSION" ]; then
124+
version="$CODACY_CLI_V2_VERSION"
125+
else
126+
version=$(get_version_from_yaml)
127+
fi
128+
129+
130+
# Set up version-specific paths
131+
bin_folder="${CODACY_CLI_V2_TMP_FOLDER}/${version}"
132+
133+
mkdir -p "$bin_folder"
134+
bin_path="$bin_folder"/"$bin_name"
135+
136+
# Download the tool if not already installed
137+
download_cli "$bin_folder" "$bin_path" "$version"
138+
chmod +x "$bin_path"
139+
140+
run_command="$bin_path"
141+
if [ -z "$run_command" ]; then
142+
fatal "Codacy cli v2 binary could not be found."
143+
fi
144+
145+
if [ "$#" -eq 1 ] && [ "$1" = "download" ]; then
146+
echo "Codacy cli v2 download succeeded"
147+
else
148+
eval "$run_command $*"
149+
fi

.codacy/codacy.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
runtimes:
2+
- dart@3.7.2
3+
- go@1.22.3
4+
- java@17.0.10
5+
- node@22.2.0
6+
- python@3.11.11
7+
tools:
8+
- dartanalyzer@3.7.2
9+
- eslint@8.57.0
10+
- lizard@1.17.31
11+
- pmd@7.11.0
12+
- pylint@3.3.6
13+
- revive@1.7.0
14+
- semgrep@1.78.0
15+
- trivy@0.66.0
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
name: Docker Multi-Arch Build & Push
2+
3+
on:
4+
push:
5+
branches: [ main, copilot/add-database-router ]
6+
workflow_dispatch:
7+
8+
jobs:
9+
build:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: read
13+
packages: write
14+
env:
15+
REGISTRY: ghcr.io
16+
IMAGE_NAME: ${{ github.repository_owner }}/database-router
17+
steps:
18+
- name: Checkout
19+
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
20+
21+
- name: Set up QEMU
22+
uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0
23+
24+
- name: Set up Docker Buildx
25+
uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3.6.1
26+
27+
- name: Login to GHCR
28+
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
29+
with:
30+
registry: ghcr.io
31+
username: ${{ github.repository_owner }}
32+
password: ${{ secrets.GITHUB_TOKEN }}
33+
34+
- name: Docker metadata
35+
id: meta
36+
uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1
37+
with:
38+
images: |
39+
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
40+
tags: |
41+
type=raw,value=${{ github.sha }}
42+
type=raw,value={{date 'YYYYMMDD-HHmmss' tz='UTC'}}
43+
type=ref,event=branch
44+
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
45+
46+
- name: Build and push (distroless)
47+
uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 # v6.7.0
48+
with:
49+
context: .
50+
file: Dockerfile.optimized
51+
target: distroless
52+
platforms: linux/amd64,linux/arm64
53+
push: true
54+
tags: ${{ steps.meta.outputs.tags }}
55+
labels: ${{ steps.meta.outputs.labels }}

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,7 @@ minio-data/
142142
# Logs
143143
logs/
144144
*.log
145+
146+
147+
#Ignore vscode AI rules
148+
.github/instructions/codacy.instructions.md
9 KB
Binary file not shown.
35.9 KB
Binary file not shown.
47.2 KB
Binary file not shown.
35.9 KB
Binary file not shown.
35.9 KB
Binary file not shown.

ALMOps_v4_Deliverables.zip

135 KB
Binary file not shown.

0 commit comments

Comments
 (0)