Skip to content

Commit b31cbbc

Browse files
committed
Enhance configuration and Docker setup: update .gitignore, refactor Dockerfile for container2wasm, and remove deprecated entrypoint script. Add detailed configuration schema and usage instructions in README.md.
1 parent ccd1789 commit b31cbbc

11 files changed

Lines changed: 973 additions & 338 deletions

File tree

.github/dependabot.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# ─────────────────────────────────────────────────────────────────────────────
2+
# Dependabot Configuration
3+
# ─────────────────────────────────────────────────────────────────────────────
4+
# Keeps GitHub Actions up to date automatically
5+
# ─────────────────────────────────────────────────────────────────────────────
6+
7+
version: 2
8+
9+
updates:
10+
- package-ecosystem: "github-actions"
11+
directory: "/"
12+
schedule:
13+
interval: "weekly"
14+
day: "monday"
15+
commit-message:
16+
prefix: "ci"
17+
labels:
18+
- "dependencies"
19+
- "github-actions"
20+
open-pull-requests-limit: 5
21+

.github/workflows/build.yml

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
# ─────────────────────────────────────────────────────────────────────────────
2+
# Release WASM Containers
3+
# ─────────────────────────────────────────────────────────────────────────────
4+
# Manual workflow to build containers and create a GitHub release
5+
# Trigger from: Actions → Release WASM Containers → Run workflow
6+
# ─────────────────────────────────────────────────────────────────────────────
7+
8+
name: Release WASM Containers
9+
10+
on:
11+
workflow_dispatch:
12+
inputs:
13+
release_tag:
14+
description: 'Release tag (e.g., v1.0.0)'
15+
required: true
16+
type: string
17+
prerelease:
18+
description: 'Mark as pre-release'
19+
required: false
20+
default: false
21+
type: boolean
22+
23+
env:
24+
IMAGE_NAME: c4c2w:latest
25+
26+
jobs:
27+
release:
28+
name: Build & Release
29+
runs-on: ubuntu-latest
30+
timeout-minutes: 120 # container2wasm can be slow
31+
32+
permissions:
33+
contents: write # For creating releases
34+
35+
steps:
36+
- name: Validate tag format
37+
run: |
38+
TAG="${{ inputs.release_tag }}"
39+
if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-.*)?$ ]]; then
40+
echo "⚠️ Warning: Tag '$TAG' doesn't follow semver (vX.Y.Z)"
41+
echo "Continuing anyway..."
42+
fi
43+
echo "Release tag: $TAG"
44+
45+
- name: Checkout repository
46+
uses: actions/checkout@v4
47+
48+
- name: Free up disk space
49+
run: |
50+
# container2wasm needs significant disk space
51+
sudo rm -rf /usr/share/dotnet
52+
sudo rm -rf /usr/local/lib/android
53+
sudo rm -rf /opt/ghc
54+
sudo rm -rf /opt/hostedtoolcache/CodeQL
55+
df -h
56+
57+
- name: Set up Docker Buildx
58+
uses: docker/setup-buildx-action@v3
59+
60+
- name: Build c4c2w image
61+
uses: docker/build-push-action@v5
62+
with:
63+
context: .
64+
push: false
65+
load: true
66+
tags: ${{ env.IMAGE_NAME }}
67+
cache-from: type=gha
68+
cache-to: type=gha,mode=max
69+
70+
- name: Create output directory
71+
run: mkdir -p ./out
72+
73+
- name: Run container2wasm conversion
74+
run: |
75+
echo "🚀 Starting conversion..."
76+
docker run --rm --privileged \
77+
-v $(pwd)/out:/out \
78+
-v /var/lib/docker \
79+
-v $(pwd)/config.yaml:/work/config.yaml:ro \
80+
${{ env.IMAGE_NAME }}
81+
echo "✅ Conversion complete!"
82+
83+
- name: List outputs
84+
run: |
85+
echo "📦 Output artifacts:"
86+
find ./out -type f -name "manifest.json" -exec sh -c '
87+
dir=$(dirname "$1")
88+
name=$(jq -r ".name" "$1")
89+
mode=$(jq -r ".mode" "$1")
90+
size=$(jq -r ".total_size" "$1")
91+
size_mb=$(echo "scale=2; $size / 1048576" | bc)
92+
echo " • $name ($mode) - ${size_mb}MB"
93+
echo " Files: $(ls -1 "$dir" | wc -l)"
94+
' sh {} \;
95+
96+
- name: Upload artifacts
97+
uses: actions/upload-artifact@v4
98+
with:
99+
name: wasm-containers-${{ inputs.release_tag }}
100+
path: out/
101+
retention-days: 90
102+
compression-level: 0
103+
104+
- name: Generate release notes
105+
run: |
106+
{
107+
echo "## 📦 WASM Container Artifacts"
108+
echo ""
109+
echo "**Tag:** \`${{ inputs.release_tag }}\`"
110+
echo "**Commit:** \`${{ github.sha }}\`"
111+
echo "**Built:** $(date -u +'%Y-%m-%d %H:%M:%S UTC')"
112+
echo ""
113+
echo "### Containers"
114+
echo ""
115+
find ./out -type f -name "manifest.json" -exec sh -c '
116+
name=$(jq -r ".name" "$1")
117+
mode=$(jq -r ".mode" "$1")
118+
arch=$(jq -r ".arch // \"amd64\"" "$1")
119+
size=$(jq -r ".total_size" "$1")
120+
size_mb=$(echo "scale=2; $size / 1048576" | bc)
121+
parts=$(jq -r ".parts | length // 1" "$1")
122+
echo "| **$name** | \`$arch\` | \`$mode\` | ${size_mb}MB | $parts part(s) |"
123+
' sh {} \;
124+
echo ""
125+
echo "### Usage"
126+
echo ""
127+
echo "Download and reassemble WASI containers:"
128+
echo ""
129+
echo "\`\`\`bash"
130+
echo "# Download release assets"
131+
echo "gh release download ${{ inputs.release_tag }} -D ./wasm"
132+
echo ""
133+
echo "# Reassemble"
134+
echo "cd wasm/<container-name>"
135+
echo "./reassemble.sh output.wasm"
136+
echo ""
137+
echo "# Run"
138+
echo "wasmtime output.wasm"
139+
echo "\`\`\`"
140+
} > release_notes.md
141+
cat release_notes.md
142+
143+
- name: Create GitHub Release
144+
uses: softprops/action-gh-release@v2
145+
with:
146+
tag_name: ${{ inputs.release_tag }}
147+
name: ${{ inputs.release_tag }}
148+
body_path: release_notes.md
149+
prerelease: ${{ inputs.prerelease }}
150+
files: |
151+
out/**/*
152+
fail_on_unmatched_files: false

.github/workflows/validate.yml

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# ─────────────────────────────────────────────────────────────────────────────
2+
# Validate Configuration
3+
# ─────────────────────────────────────────────────────────────────────────────
4+
# Quick validation of config.yaml and Dockerfile syntax
5+
# Runs on all PRs - faster than full build
6+
# ─────────────────────────────────────────────────────────────────────────────
7+
8+
name: Validate
9+
10+
on:
11+
pull_request:
12+
branches: [main]
13+
push:
14+
branches: [main]
15+
paths:
16+
- 'config.yaml'
17+
- 'Dockerfile'
18+
- 'entrypoint.sh'
19+
20+
jobs:
21+
validate:
22+
name: Validate Configuration
23+
runs-on: ubuntu-latest
24+
timeout-minutes: 5
25+
26+
steps:
27+
- name: Checkout repository
28+
uses: actions/checkout@v4
29+
30+
- name: Validate YAML syntax
31+
run: |
32+
echo "Validating config.yaml..."
33+
python3 -c "import yaml; yaml.safe_load(open('config.yaml'))"
34+
echo "✅ YAML syntax is valid"
35+
36+
- name: Validate config schema
37+
run: |
38+
echo "Checking required fields..."
39+
40+
# Check that containers array exists and has entries
41+
containers=$(yq '.containers | length' config.yaml)
42+
if [ "$containers" -eq 0 ]; then
43+
echo "❌ Error: No containers defined in config.yaml"
44+
exit 1
45+
fi
46+
echo "✅ Found $containers container(s)"
47+
48+
# Validate each container entry
49+
for i in $(seq 0 $((containers - 1))); do
50+
name=$(yq ".containers[$i].name" config.yaml)
51+
52+
if [ "$name" == "null" ] || [ -z "$name" ]; then
53+
echo "❌ Error: Container at index $i missing 'name' field"
54+
exit 1
55+
fi
56+
57+
image=$(yq ".containers[$i].image" config.yaml)
58+
dockerfile=$(yq ".containers[$i].dockerfile" config.yaml)
59+
60+
if [ "$image" == "null" ] && [ "$dockerfile" == "null" ]; then
61+
echo "❌ Error: Container '$name' must have either 'image' or 'dockerfile'"
62+
exit 1
63+
fi
64+
65+
if [ "$image" != "null" ] && [ "$dockerfile" != "null" ]; then
66+
echo "❌ Error: Container '$name' cannot have both 'image' and 'dockerfile'"
67+
exit 1
68+
fi
69+
70+
mode=$(yq ".containers[$i].mode // \"wasi\"" config.yaml)
71+
if [ "$mode" != "wasi" ] && [ "$mode" != "emscripten" ]; then
72+
echo "❌ Error: Container '$name' has invalid mode '$mode' (must be 'wasi' or 'emscripten')"
73+
exit 1
74+
fi
75+
76+
arch=$(yq ".containers[$i].arch // \"amd64\"" config.yaml)
77+
if [ "$arch" != "amd64" ] && [ "$arch" != "arm64" ]; then
78+
echo "❌ Error: Container '$name' has invalid arch '$arch' (must be 'amd64' or 'arm64')"
79+
exit 1
80+
fi
81+
82+
echo "✅ Container '$name' ($arch, $mode) is valid"
83+
done
84+
85+
- name: Validate Dockerfile syntax
86+
run: |
87+
echo "Validating Dockerfile..."
88+
docker build --check .
89+
echo "✅ Dockerfile syntax is valid"
90+
91+
- name: Check entrypoint.sh
92+
run: |
93+
echo "Checking entrypoint.sh..."
94+
bash -n entrypoint.sh
95+
echo "✅ entrypoint.sh syntax is valid"
96+

.gitignore

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,16 @@
1+
# Output directory
2+
out/
3+
4+
# Docker artifacts
5+
*.tar
6+
*.tgz
7+
8+
# macOS
19
.DS_Store
2-
out
10+
11+
# Editor
12+
.vscode/
13+
.idea/
14+
*.swp
15+
*.swo
16+

Dockerfile

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,48 @@
1-
FROM alpine:latest
1+
# c4c2w - Container for Container2Wasm
2+
# Base: Official Docker-in-Docker image (no openrc dance needed)
3+
FROM docker:27-dind
24

3-
# Install necessary packages
4-
RUN apk update && apk add --no-cache \
5-
docker \
6-
openrc \
5+
# Tools for config parsing and file operations
6+
RUN apk add --no-cache \
77
bash \
88
curl \
9-
iptables \
10-
e2fsprogs \
11-
fuse-overlayfs \
12-
linux-headers \
13-
util-linux \
14-
shadow \
159
git \
16-
tar \
17-
wget \
1810
jq \
19-
yq
20-
21-
# Install c2w binaries
22-
ENV C2W_VERSION="v0.6.4"
23-
RUN wget https://github.com/ktock/container2wasm/releases/download/${C2W_VERSION}/container2wasm-${C2W_VERSION}-linux-amd64.tar.gz && \
24-
echo "Downloaded container2wasm-${C2W_VERSION}-linux-amd64.tar.gz" && \
25-
tar -xzvf container2wasm-${C2W_VERSION}-linux-amd64.tar.gz && \
26-
echo "Extracted container2wasm-${C2W_VERSION}-linux-amd64.tar.gz" && \
27-
mv c2w /usr/local/bin/c2w && \
28-
echo "Moved c2w to /usr/local/bin/" && \
29-
mv c2w-net /usr/local/bin/c2w-net && \
30-
echo "Moved c2w-net to /usr/local/bin/" && \
31-
rm -rf container2wasm-${C2W_VERSION}-linux-amd64.tar.gz && \
32-
echo "Cleaned up downloaded tar.gz file"
33-
34-
# Add docker_entrypoint.sh script
35-
RUN mkdir -p /usr/local/bin/
36-
COPY docker_entrypoint.sh /usr/local/bin/docker_entrypoint.sh
37-
RUN chmod +x /usr/local/bin/docker_entrypoint.sh
38-
39-
# Copy the config.yaml file
40-
COPY config.yaml /usr/local/bin/config.yaml
41-
42-
# Expose port 8080
43-
EXPOSE 8080
44-
45-
# Set the entrypoint
46-
ENTRYPOINT ["/usr/local/bin/docker_entrypoint.sh"]
47-
CMD ["sh"]
11+
yq \
12+
tar \
13+
gzip \
14+
coreutils \
15+
fuse-overlayfs \
16+
ca-certificates
17+
18+
# Install container2wasm (c2w + c2w-net)
19+
# Detect architecture and download appropriate binary
20+
ARG C2W_VERSION=v0.8.3
21+
RUN ARCH=$(uname -m) && \
22+
case "$ARCH" in \
23+
x86_64) C2W_ARCH="amd64" ;; \
24+
aarch64) C2W_ARCH="arm64" ;; \
25+
*) echo "Unsupported architecture: $ARCH" && exit 1 ;; \
26+
esac && \
27+
curl -fsSL -o /tmp/c2w.tgz \
28+
"https://github.com/ktock/container2wasm/releases/download/${C2W_VERSION}/container2wasm-${C2W_VERSION}-linux-${C2W_ARCH}.tar.gz" \
29+
&& tar -xzf /tmp/c2w.tgz -C /usr/local/bin c2w c2w-net \
30+
&& rm -f /tmp/c2w.tgz \
31+
&& chmod +x /usr/local/bin/c2w /usr/local/bin/c2w-net
32+
33+
# Docker daemon config: use vfs storage driver for maximum compatibility in nested Docker
34+
# (slower but works reliably in DinD scenarios)
35+
RUN mkdir -p /etc/docker \
36+
&& printf '{\n "storage-driver": "vfs"\n}\n' > /etc/docker/daemon.json
37+
38+
WORKDIR /work
39+
40+
COPY config.yaml /work/config.yaml
41+
COPY entrypoint.sh /work/entrypoint.sh
42+
RUN chmod +x /work/entrypoint.sh
43+
44+
# /out will be a bind mount from host
45+
VOLUME ["/out"]
46+
47+
ENTRYPOINT ["/work/entrypoint.sh"]
48+

0 commit comments

Comments
 (0)