feat: add local cicd demo app
Some checks failed
Build and deploy demo app / deploy (push) Has been cancelled

This commit is contained in:
ningning 2026-06-26 12:02:15 +08:00
commit 7a27c89067
5 changed files with 149 additions and 0 deletions

3
.env.example Normal file
View File

@ -0,0 +1,3 @@
APP_NAME=demo-app
APP_VERSION=local
PORT=8080

View File

@ -0,0 +1,86 @@
name: Build and deploy demo app
on:
push:
branches:
- main
workflow_dispatch:
env:
APP_NAME: demo-app
DEPLOY_DIR: /workspace/apps/demo-app
REGISTRY: localhost:5001
IMAGE_NAME: localhost:5001/${{ github.repository }}
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Show context
run: |
set -eu
echo "repository=${{ github.repository }}"
echo "sha=${{ github.sha }}"
docker version
- name: Build image
run: |
set -eu
docker build \
--label "org.opencontainers.image.revision=${{ github.sha }}" \
-t "$IMAGE_NAME:${{ github.sha }}" \
-t "$IMAGE_NAME:latest" \
.
- name: Push image
run: |
set -eu
docker push "$IMAGE_NAME:${{ github.sha }}"
docker push "$IMAGE_NAME:latest"
- name: Deploy with local Docker Compose
run: |
set -eu
mkdir -p "$DEPLOY_DIR"
cat > "$DEPLOY_DIR/docker-compose.yml" <<EOF
services:
demo-app:
image: $IMAGE_NAME:${{ github.sha }}
container_name: local-demo-app
env_file:
- .env
ports:
- "8088:8080"
restart: unless-stopped
EOF
if [ ! -f "$DEPLOY_DIR/.env" ]; then
cat > "$DEPLOY_DIR/.env" <<EOF
APP_NAME=demo-app
APP_VERSION=${{ github.sha }}
PORT=8080
EOF
else
if grep -q '^APP_VERSION=' "$DEPLOY_DIR/.env"; then
sed -i "s/^APP_VERSION=.*/APP_VERSION=${{ github.sha }}/" "$DEPLOY_DIR/.env"
else
printf '\nAPP_VERSION=%s\n' "${{ github.sha }}" >> "$DEPLOY_DIR/.env"
fi
fi
docker compose -f "$DEPLOY_DIR/docker-compose.yml" pull
docker compose -f "$DEPLOY_DIR/docker-compose.yml" up -d
- name: Health check
run: |
set -eu
for i in $(seq 1 30); do
if curl -fsS http://host.docker.internal:8088/health; then
exit 0
fi
sleep 2
done
docker compose -f "$DEPLOY_DIR/docker-compose.yml" ps
docker logs local-demo-app --tail=100 || true
exit 1

9
Dockerfile Normal file
View File

@ -0,0 +1,9 @@
FROM docker.m.daocloud.io/library/python:3.12-slim
WORKDIR /app
COPY app.py /app/app.py
ENV PORT=8080
EXPOSE 8080
CMD ["python", "/app/app.py"]

Binary file not shown.

51
app.py Normal file
View File

@ -0,0 +1,51 @@
import json
import os
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
APP_NAME = os.environ.get("APP_NAME", "demo-app")
APP_VERSION = os.environ.get("APP_VERSION", "local")
PORT = int(os.environ.get("PORT", "8080"))
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == "/health":
self._send_json(200, {"status": "ok", "app": APP_NAME, "version": APP_VERSION})
return
if self.path == "/":
body = f"{APP_NAME} is running\nversion={APP_VERSION}\n"
self._send_text(200, body)
return
self._send_json(404, {"error": "not found"})
def log_message(self, fmt, *args):
print("%s - %s" % (self.address_string(), fmt % args))
def _send_json(self, status, payload):
body = json.dumps(payload, separators=(",", ":")).encode("utf-8")
self.send_response(status)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def _send_text(self, status, body_text):
body = body_text.encode("utf-8")
self.send_response(status)
self.send_header("Content-Type", "text/plain; charset=utf-8")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def main():
server = ThreadingHTTPServer(("0.0.0.0", PORT), Handler)
print(f"{APP_NAME} listening on 0.0.0.0:{PORT}")
server.serve_forever()
if __name__ == "__main__":
main()