commit 7a27c89067ee54b90f914c92d62ef054771ff932 Author: ningning Date: Fri Jun 26 12:02:15 2026 +0800 feat: add local cicd demo app diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..b3967e7 --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +APP_NAME=demo-app +APP_VERSION=local +PORT=8080 diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..7ab5ad4 --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -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" < "$DEPLOY_DIR/.env" <> "$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 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2207ed2 --- /dev/null +++ b/Dockerfile @@ -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"] diff --git a/__pycache__/app.cpython-314.pyc b/__pycache__/app.cpython-314.pyc new file mode 100644 index 0000000..e499073 Binary files /dev/null and b/__pycache__/app.cpython-314.pyc differ diff --git a/app.py b/app.py new file mode 100644 index 0000000..b706dc7 --- /dev/null +++ b/app.py @@ -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()