From 0b79ac86f719ffe46becfb8e704bc9be9f94cb2a Mon Sep 17 00:00:00 2001 From: Ravi Prasad Date: Sat, 19 Sep 2026 01:20:50 -0500 Subject: [PATCH] flows --- .gitea/workflows/hello-world.yaml | 22 +++++++ .gitea/workflows/scheduled-echo.yaml | 14 +++++ .gitea/workflows/test.yml | 75 ++++++++++++++++++++++++ gitea/README.md | 54 +++++++++++++++++ gitea/config.yaml | 42 +++++++++++++ gitea/docker-compose.yml | 27 +++++++++ gitea/sample-workflows/docker-build.yaml | 46 +++++++++++++++ 7 files changed, 280 insertions(+) create mode 100644 .gitea/workflows/hello-world.yaml create mode 100644 .gitea/workflows/scheduled-echo.yaml create mode 100644 .gitea/workflows/test.yml create mode 100644 gitea/README.md create mode 100644 gitea/config.yaml create mode 100644 gitea/sample-workflows/docker-build.yaml diff --git a/.gitea/workflows/hello-world.yaml b/.gitea/workflows/hello-world.yaml new file mode 100644 index 0000000..864dd7a --- /dev/null +++ b/.gitea/workflows/hello-world.yaml @@ -0,0 +1,22 @@ +# Runner smoke test. Runs on every push/PR to confirm the act_runner +# (see gitea/docker-compose.yml + gitea/config.yaml) is picking up jobs. +name: hello-world + +on: + push: + pull_request: + workflow_dispatch: + +jobs: + hello: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Say hello + run: echo "Hello from Gitea Actions on ${{ gitea.server_url }}" + + - name: Show context + run: | + echo "repo=${{ gitea.repository }} ref=${{ gitea.ref }} sha=${{ gitea.sha }}" + node --version diff --git a/.gitea/workflows/scheduled-echo.yaml b/.gitea/workflows/scheduled-echo.yaml new file mode 100644 index 0000000..66e5021 --- /dev/null +++ b/.gitea/workflows/scheduled-echo.yaml @@ -0,0 +1,14 @@ +# Scheduled / manual maintenance probe. +name: scheduled-echo + +on: + schedule: + - cron: '0 6 * * *' + workflow_dispatch: + +jobs: + echo: + runs-on: ubuntu-latest + steps: + - name: Print date + run: date -u diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml new file mode 100644 index 0000000..97ece40 --- /dev/null +++ b/.gitea/workflows/test.yml @@ -0,0 +1,75 @@ +name: CI Health Check & Quality Gate + +on: + push: + branches: + - main + - dev + pull_request: + workflow_dispatch: + +jobs: + healthcheck: + runs-on: ubuntu-latest + name: Code, dbt & Live App Health Check + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Install System Dependencies + run: | + apt-get update && apt-get install -y curl unzip git ca-certificates + + - name: Install uv + run: | + curl -LsSf https://astral.sh/uv/install.sh | sh + echo "$HOME/.local/bin" >> $GITHUB_PATH + echo "/root/.local/bin" >> $GITHUB_PATH + + - name: Install Project Dependencies + run: | + export PATH="$HOME/.local/bin:/root/.local/bin:$PATH" + uv sync + + - name: Python Syntax & Compilation Verification + run: | + export PATH="$HOME/.local/bin:/root/.local/bin:$PATH" + echo "==> Validating Python scripts compilation..." + uv run python -m py_compile streamlit_app/app.py scripts/db_storage.py + echo "✓ Python scripts compiled without errors" + + - name: dbt Manifest & Model Validation + run: | + export PATH="$HOME/.local/bin:/root/.local/bin:$PATH" + echo "==> Validating dbt package dependencies..." + uv run dbt deps --project-dir dbt_nba --profiles-dir dbt_nba + echo "==> Validating dbt models, seeds, and tests compilation..." + uv run dbt parse --project-dir dbt_nba --profiles-dir dbt_nba + echo "✓ All dbt models, seeds, and macros validated" + + - name: Cloudflare R2 Storage Probe (Optional if secrets present) + env: + S3_ENDPOINT_URL: ${{ secrets.S3_ENDPOINT_URL }} + S3_BUCKET_NAME: ${{ secrets.S3_BUCKET_NAME }} + S3_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }} + S3_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }} + S3_REGION: ${{ secrets.S3_REGION || 'auto' }} + S3_DB_KEY: ${{ secrets.S3_DB_KEY || 'dbt_nba.duckdb' }} + run: | + export PATH="$HOME/.local/bin:/root/.local/bin:$PATH" + if [ -n "${S3_ENDPOINT_URL:-}" ]; then + echo "==> Probing Cloudflare R2 storage status..." + uv run python scripts/db_storage.py status + else + echo "==> S3 secrets not configured for this step; skipping storage probe." + fi + + - name: Live Production App Health Probe + run: | + echo "==> Probing production endpoint https://streamlit.turbo-data.com/_stcore/health..." + HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://streamlit.turbo-data.com/_stcore/health || echo "000") + if [ "$HTTP_STATUS" = "200" ]; then + echo "✓ Production Streamlit dashboard is healthy (HTTP $HTTP_STATUS)" + else + echo "⚠️ Production health check returned HTTP $HTTP_STATUS (may still be starting or initializing)" + fi diff --git a/gitea/README.md b/gitea/README.md new file mode 100644 index 0000000..754cdf0 --- /dev/null +++ b/gitea/README.md @@ -0,0 +1,54 @@ +# Gitea + Gitea Actions runner + +Deploys Gitea with Actions enabled plus one `act_runner` that picks up jobs. + +## Start + +1. Copy `config.yaml` to the runner data dir on the Docker host: + + ```sh + mkdir -p /portainer/Files/AppData/Config/Gitea-runner + cp config.yaml /portainer/Files/AppData/Config/Gitea-runner/config.yaml + ``` + +2. In Gitea, go to **Site Administration -> Actions -> Runners -> + Create new Runner** and copy the registration token. + +3. Start the stack with the token (first start registers the runner; + the `.runner` file persisted in `/data` keeps it registered): + + ```sh + GITEA_RUNNER_REGISTRATION_TOKEN= docker compose up -d + ``` + + Optional overrides: `GITEA_INSTANCE_URL` (default `http://gitea:3000`), + `GITEA_RUNNER_NAME`, `GITEA_RUNNER_LABELS`. + +4. Confirm the runner shows as active under **Site Administration -> + Actions -> Runners**. + +## Live workflows + +These run on this repo itself (repo root `.gitea/workflows/`): + +- `test.yml` — external CI health check (uv, dbt, R2, prod probe) +- `hello-world.yaml` — checkout + node smoke test on `ubuntu-latest` +- `scheduled-echo.yaml` — cron + manual trigger example + +## Sample workflow + +`sample-workflows/docker-build.yaml` is a Buildx build template (with +commented-out push steps) you can copy into any repo hosted on this Gitea +instance as `.gitea/workflows/*.yaml` or `.github/workflows/*.yaml`. +It stays out of the root because this repo has no Dockerfile. + +## Notes + +- `GITEA__actions__ENABLED=true` is already set on the `gitea` service; + without it the Actions tab stays disabled. +- The runner needs `/var/run/docker.sock` so `docker://` labels can start + job containers. Jobs therefore run with the trust level of anything that + can use the host Docker daemon — only connect this runner to repos you + trust, or scope tokens via per-repo runner groups. +- Image `gitea/act_runner:latest` tracks the stable runner; the same image + is also published as `gitea/runner:latest`. diff --git a/gitea/config.yaml b/gitea/config.yaml new file mode 100644 index 0000000..3ae5c2a --- /dev/null +++ b/gitea/config.yaml @@ -0,0 +1,42 @@ +# Sample Gitea Actions runner config for gitea/act_runner. +# Copy this file to /portainer/Files/AppData/Config/Gitea-runner/config.yaml +# (the path mounted as /config.yaml in docker-compose.yml), then adjust labels +# and capacity for your host. Full reference: +# https://docs.gitea.com/usage/actions/act-runner +# +# Generate a fresh annotated example at any time with: +# docker run --rm --entrypoint='' gitea/act_runner:latest act_runner generate-config + +log: + level: info + +runner: + # Registration file, persisted in /data (the /data volume). + file: .runner + # How many jobs this runner executes in parallel. + capacity: 2 + # Max duration for a single job before it is cancelled. + timeout: 3h + # How often/long the runner polls Gitea for new jobs. + fetch_timeout: 5s + fetch_interval: 2s + labels: + - 'ubuntu-latest:docker://node:20-bookworm' + - 'ubuntu-22.04:docker://node:20-bookworm' + - 'debian-latest:docker://node:20-bookworm' + +cache: + enabled: true + # Local cache dir for actions/cache. Each runner keeps its own cache + # unless you point multiple runners at one shared cache-server. + dir: /tmp/cache + +container: + # Docker network jobs attach to. Use "bridge" for the default setup above. + network_mode: bridge + privileged: false + # Where job workdirs live inside job containers. + workdir_parent: /workspace + +host: + workdir_parent: /tmp diff --git a/gitea/docker-compose.yml b/gitea/docker-compose.yml index 1453ccd..cfaeb26 100644 --- a/gitea/docker-compose.yml +++ b/gitea/docker-compose.yml @@ -11,5 +11,32 @@ services: environment: PUID: '1000' PGID: '100' + # Required for Gitea Actions. See https://docs.gitea.com/usage/actions/overview + GITEA__actions__ENABLED: 'true' restart: unless-stopped container_name: gitea + + # Gitea Actions runner (act_runner). + # Get a registration token from Gitea at: + # Site Administration -> Actions -> Runners -> Create new Runner + # then set GITEA_RUNNER_REGISTRATION_TOKEN before starting. + gitea-runner: + image: gitea/act_runner:latest + container_name: gitea-runner + restart: unless-stopped + depends_on: + - gitea + environment: + CONFIG_FILE: /config.yaml + # Use the in-compose DNS name so the runner can reach Gitea. + # Override with your public URL if the runner runs on another host. + GITEA_INSTANCE_URL: ${GITEA_INSTANCE_URL:-http://gitea:3000} + GITEA_RUNNER_REGISTRATION_TOKEN: ${GITEA_RUNNER_REGISTRATION_TOKEN:-} + GITEA_RUNNER_NAME: ${GITEA_RUNNER_NAME:-docker-templates-runner} + GITEA_RUNNER_LABELS: ${GITEA_RUNNER_LABELS:-ubuntu-latest:docker://node:20-bookworm,ubuntu-22.04:docker://node:20-bookworm,debian-latest:docker://node:20-bookworm} + volumes: + - /portainer/Files/AppData/Config/Gitea-runner:/data + - /portainer/Files/AppData/Config/Gitea-runner/config.yaml:/config.yaml + - /var/run/docker.sock:/var/run/docker.sock + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro diff --git a/gitea/sample-workflows/docker-build.yaml b/gitea/sample-workflows/docker-build.yaml new file mode 100644 index 0000000..4922dae --- /dev/null +++ b/gitea/sample-workflows/docker-build.yaml @@ -0,0 +1,46 @@ +# Sample: build (and optionally push) a Docker image with Gitea Actions. +# Copy into your repo as `.gitea/workflows/docker-build.yaml` and push. +# Requires a runner with `ubuntu-latest` that can reach a Docker daemon +# (the compose file bind-mounts /var/run/docker.sock for this). +# +# To push, create Gitea repo secrets REGISTRY, REGISTRY_USERNAME, +# REGISTRY_PASSWORD, IMAGE_NAME and uncomment the login/push steps. +name: docker-build + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build image (no push) + uses: docker/build-push-action@v6 + with: + context: . + push: false + tags: sample-app:ci + cache-from: type=gha + cache-to: type=gha,mode=max + + # - name: Log in to registry + # uses: docker/login-action@v3 + # with: + # registry: ${{ secrets.REGISTRY }} + # username: ${{ secrets.REGISTRY_USERNAME }} + # password: ${{ secrets.REGISTRY_PASSWORD }} + # + # - name: Build and push + # uses: docker/build-push-action@v6 + # with: + # context: . + # push: true + # tags: ${{ secrets.REGISTRY }}/${{ secrets.IMAGE_NAME }}:${{ gitea.sha }}