From a6208689986cc5ef300957b311b84a6fe5dff208 Mon Sep 17 00:00:00 2001 From: Platform Engineer Date: Tue, 31 Mar 2026 19:55:17 +0300 Subject: [PATCH] feat: add reusable CI/CD pipeline templates Reusable Gitea Actions workflows for lint, test, build, and deploy: - lint-python, lint-node, lint-rust - test-python, test-node, test-rust - build-push (Docker build + push to Gitea registry) - deploy-k8s (GitOps image tag update in cluster repo) Plus example caller workflows for python-fullstack, rust-service, and node-frontend stacks. Branch refs aligned to staging per CON-570 standards. --- .gitea/workflows/build-push.yaml | 93 ++++++++++++ .gitea/workflows/deploy-k8s.yaml | 61 ++++++++ .gitea/workflows/lint-node.yaml | 54 +++++++ .gitea/workflows/lint-python.yaml | 37 +++++ .gitea/workflows/lint-rust.yaml | 51 +++++++ .gitea/workflows/test-node.yaml | 45 ++++++ .gitea/workflows/test-python.yaml | 51 +++++++ .gitea/workflows/test-rust.yaml | 47 ++++++ README.md | 159 ++++++++++++++++++++- examples/node-frontend/build-deploy.yml | 35 +++++ examples/node-frontend/ci.yml | 24 ++++ examples/python-fullstack/build-deploy.yml | 35 +++++ examples/python-fullstack/ci.yml | 34 +++++ examples/rust-service/build-deploy.yml | 35 +++++ examples/rust-service/ci.yml | 24 ++++ 15 files changed, 783 insertions(+), 2 deletions(-) create mode 100644 .gitea/workflows/build-push.yaml create mode 100644 .gitea/workflows/deploy-k8s.yaml create mode 100644 .gitea/workflows/lint-node.yaml create mode 100644 .gitea/workflows/lint-python.yaml create mode 100644 .gitea/workflows/lint-rust.yaml create mode 100644 .gitea/workflows/test-node.yaml create mode 100644 .gitea/workflows/test-python.yaml create mode 100644 .gitea/workflows/test-rust.yaml create mode 100644 examples/node-frontend/build-deploy.yml create mode 100644 examples/node-frontend/ci.yml create mode 100644 examples/python-fullstack/build-deploy.yml create mode 100644 examples/python-fullstack/ci.yml create mode 100644 examples/rust-service/build-deploy.yml create mode 100644 examples/rust-service/ci.yml diff --git a/.gitea/workflows/build-push.yaml b/.gitea/workflows/build-push.yaml new file mode 100644 index 0000000..3f8c0bc --- /dev/null +++ b/.gitea/workflows/build-push.yaml @@ -0,0 +1,93 @@ +# Reusable workflow: Build Docker image and push to Gitea registry +# Usage: uses: wectrl-net/ci-templates/.gitea/workflows/build-push.yaml@main +name: Build & Push Docker Image + +on: + workflow_call: + inputs: + image-name: + description: "Full image name (e.g. git.wectrl.net/wectrl-net/my-service)" + required: true + type: string + context: + description: "Docker build context path" + required: false + type: string + default: "." + dockerfile: + description: "Path to Dockerfile (relative to context)" + required: false + type: string + default: "Dockerfile" + platforms: + description: "Target platforms (e.g. linux/arm64, linux/amd64)" + required: false + type: string + default: "linux/arm64" + build-args: + description: "Docker build args (newline-separated KEY=VALUE)" + required: false + type: string + default: "" + secrets: + REGISTRY_USER: + required: true + REGISTRY_TOKEN: + required: true + outputs: + image-tag: + description: "The sha-based image tag that was pushed" + value: ${{ jobs.build.outputs.image-tag }} + +jobs: + build: + name: Build & Push + runs-on: ubuntu-latest + container: + image: catthehacker/ubuntu:act-latest + options: --privileged + outputs: + image-tag: ${{ steps.tag.outputs.tag }} + steps: + - uses: actions/checkout@v4 + + - name: Compute image tag + id: tag + run: | + SHORT_SHA="${{ gitea.sha }}" + SHORT_SHA="${SHORT_SHA:0:7}" + echo "tag=sha-${SHORT_SHA}" >> "$GITEA_OUTPUT" + + - name: Log in to Gitea registry + uses: docker/login-action@v3 + with: + registry: git.wectrl.net + username: ${{ secrets.REGISTRY_USER }} + password: ${{ secrets.REGISTRY_TOKEN }} + + - name: Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ inputs.image-name }} + tags: | + type=sha,prefix=sha- + type=raw,value=latest,enable={{is_default_branch}} + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: ${{ inputs.context }} + file: ${{ inputs.context }}/${{ inputs.dockerfile }} + platforms: ${{ inputs.platforms }} + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + build-args: ${{ inputs.build-args }} + cache-from: type=registry,ref=${{ inputs.image-name }}:buildcache + cache-to: type=registry,ref=${{ inputs.image-name }}:buildcache,mode=max diff --git a/.gitea/workflows/deploy-k8s.yaml b/.gitea/workflows/deploy-k8s.yaml new file mode 100644 index 0000000..502c1d2 --- /dev/null +++ b/.gitea/workflows/deploy-k8s.yaml @@ -0,0 +1,61 @@ +# Reusable workflow: Update image tag in wectrl-k8s-cluster repo (GitOps deploy) +# Usage: uses: wectrl-net/ci-templates/.gitea/workflows/deploy-k8s.yaml@main +name: Deploy to K8s (GitOps) + +on: + workflow_call: + inputs: + image-name: + description: "Full image name (e.g. git.wectrl.net/wectrl-net/my-service)" + required: true + type: string + deploy-paths: + description: "Space-separated paths to deployment manifests in the k8s cluster repo" + required: true + type: string + service-name: + description: "Service name for commit message (e.g. h1per-pms)" + required: true + type: string + k8s-repo: + description: "K8s cluster repo (org/repo)" + required: false + type: string + default: "wectrl-net/wectrl-k8s-cluster" + secrets: + GIT_USER: + required: true + GIT_TOKEN: + required: true + +jobs: + deploy: + name: Update k8s Cluster Repo + runs-on: ubuntu-latest + if: gitea.ref == 'refs/heads/main' + steps: + - name: Update image tag in cluster repo + run: | + SHA="${{ gitea.sha }}" + SHORT_SHA="${SHA:0:7}" + IMAGE_TAG="sha-${SHORT_SHA}" + + git clone https://${{ secrets.GIT_USER }}:${{ secrets.GIT_TOKEN }}@git.wectrl.net/${{ inputs.k8s-repo }}.git + cd wectrl-k8s-cluster + + git config user.email "ci@wectrl.net" + git config user.name "Gitea CI" + + for DEPLOY_PATH in ${{ inputs.deploy-paths }}; do + sed -i "s|image: ${{ inputs.image-name }}:.*|image: ${{ inputs.image-name }}:${IMAGE_TAG}|g" \ + "${DEPLOY_PATH}" + git add "${DEPLOY_PATH}" + done + + if git diff --staged --quiet; then + echo "No image tag changes to commit" + else + git commit -m "deploy: ${{ inputs.service-name }} ${IMAGE_TAG}" + git push origin main + echo "Cluster repo updated — ArgoCD will sync within ~3 min" + fi diff --git a/.gitea/workflows/lint-node.yaml b/.gitea/workflows/lint-node.yaml new file mode 100644 index 0000000..0674c63 --- /dev/null +++ b/.gitea/workflows/lint-node.yaml @@ -0,0 +1,54 @@ +# Reusable workflow: Node.js/TypeScript linting with ESLint + type-check +# Usage: uses: wectrl-net/ci-templates/.gitea/workflows/lint-node.yaml@main +name: Lint Node (ESLint + tsc) + +on: + workflow_call: + inputs: + node-version: + description: "Node.js version to use" + required: false + type: string + default: "22" + working-directory: + description: "Directory containing the Node.js project (with package.json)" + required: false + type: string + default: "." + package-manager: + description: "Package manager (npm or pnpm)" + required: false + type: string + default: "npm" + lint-script: + description: "npm script name for linting" + required: false + type: string + default: "lint" + typecheck-script: + description: "npm script name for type-checking (leave empty to skip)" + required: false + type: string + default: "typecheck" + +jobs: + lint: + name: ESLint + TypeScript + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: ${{ inputs.node-version }} + cache: ${{ inputs.package-manager }} + cache-dependency-path: ${{ inputs.working-directory }}/package-lock.json + - name: Install dependencies + run: npm ci + working-directory: ${{ inputs.working-directory }} + - name: ESLint + run: npm run ${{ inputs.lint-script }} + working-directory: ${{ inputs.working-directory }} + - name: TypeScript type-check + if: inputs.typecheck-script != '' + run: npm run ${{ inputs.typecheck-script }} + working-directory: ${{ inputs.working-directory }} diff --git a/.gitea/workflows/lint-python.yaml b/.gitea/workflows/lint-python.yaml new file mode 100644 index 0000000..5242bc4 --- /dev/null +++ b/.gitea/workflows/lint-python.yaml @@ -0,0 +1,37 @@ +# Reusable workflow: Python linting with Ruff +# Usage: uses: wectrl-net/ci-templates/.gitea/workflows/lint-python.yaml@main +name: Lint Python (Ruff) + +on: + workflow_call: + inputs: + python-version: + description: "Python version to use" + required: false + type: string + default: "3.13" + ruff-version: + description: "Ruff version constraint" + required: false + type: string + default: ">=0.9.0" + working-directory: + description: "Directory containing the Python project" + required: false + type: string + default: "." + +jobs: + lint: + name: Ruff + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: ${{ inputs.python-version }} + - name: Install Ruff + run: pip install "ruff${{ inputs.ruff-version }}" + - name: Run Ruff + run: ruff check --output-format=github . + working-directory: ${{ inputs.working-directory }} diff --git a/.gitea/workflows/lint-rust.yaml b/.gitea/workflows/lint-rust.yaml new file mode 100644 index 0000000..8d45b64 --- /dev/null +++ b/.gitea/workflows/lint-rust.yaml @@ -0,0 +1,51 @@ +# Reusable workflow: Rust linting with Clippy + format check +# Usage: uses: wectrl-net/ci-templates/.gitea/workflows/lint-rust.yaml@main +name: Lint Rust (Clippy) + +on: + workflow_call: + inputs: + rust-toolchain: + description: "Rust toolchain (stable, nightly, or specific version)" + required: false + type: string + default: "stable" + working-directory: + description: "Directory containing the Rust project (with Cargo.toml)" + required: false + type: string + default: "." + clippy-args: + description: "Additional clippy arguments" + required: false + type: string + default: "-- -D warnings" + +jobs: + lint: + name: Clippy + fmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ inputs.rust-toolchain }} + components: clippy, rustfmt + - name: Cache cargo + uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + ${{ inputs.working-directory }}/target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: ${{ runner.os }}-cargo- + - name: Check formatting + run: cargo fmt --check + working-directory: ${{ inputs.working-directory }} + - name: Run Clippy + run: cargo clippy --all-targets --all-features ${{ inputs.clippy-args }} + working-directory: ${{ inputs.working-directory }} diff --git a/.gitea/workflows/test-node.yaml b/.gitea/workflows/test-node.yaml new file mode 100644 index 0000000..607407d --- /dev/null +++ b/.gitea/workflows/test-node.yaml @@ -0,0 +1,45 @@ +# Reusable workflow: Node.js testing +# Usage: uses: wectrl-net/ci-templates/.gitea/workflows/test-node.yaml@main +name: Test Node + +on: + workflow_call: + inputs: + node-version: + description: "Node.js version to use" + required: false + type: string + default: "22" + working-directory: + description: "Directory containing the Node.js project" + required: false + type: string + default: "." + test-script: + description: "npm script name for testing" + required: false + type: string + default: "test" + test-args: + description: "Additional args appended after -- (e.g. --passWithNoTests)" + required: false + type: string + default: "--passWithNoTests" + +jobs: + test: + name: Tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: ${{ inputs.node-version }} + cache: npm + cache-dependency-path: ${{ inputs.working-directory }}/package-lock.json + - name: Install dependencies + run: npm ci + working-directory: ${{ inputs.working-directory }} + - name: Run tests + run: npm run ${{ inputs.test-script }} -- ${{ inputs.test-args }} + working-directory: ${{ inputs.working-directory }} diff --git a/.gitea/workflows/test-python.yaml b/.gitea/workflows/test-python.yaml new file mode 100644 index 0000000..7dab52e --- /dev/null +++ b/.gitea/workflows/test-python.yaml @@ -0,0 +1,51 @@ +# Reusable workflow: Python testing with pytest +# Usage: uses: wectrl-net/ci-templates/.gitea/workflows/test-python.yaml@main +name: Test Python (pytest) + +on: + workflow_call: + inputs: + python-version: + description: "Python version to use" + required: false + type: string + default: "3.13" + working-directory: + description: "Directory containing the Python project" + required: false + type: string + default: "." + install-command: + description: "Command to install dependencies (empty = pip install pytest pytest-asyncio)" + required: false + type: string + default: "" + pytest-args: + description: "Additional pytest arguments" + required: false + type: string + default: "--ignore=venv -q" + +jobs: + test: + name: pytest + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: ${{ inputs.python-version }} + - name: Install dependencies + run: | + if [ -n "${{ inputs.install-command }}" ]; then + ${{ inputs.install-command }} + elif [ -f "${{ inputs.working-directory }}/requirements.txt" ]; then + pip install -r ${{ inputs.working-directory }}/requirements.txt + pip install pytest pytest-asyncio + else + pip install pytest pytest-asyncio + fi + working-directory: ${{ inputs.working-directory }} + - name: Run tests + run: pytest ${{ inputs.pytest-args }} + working-directory: ${{ inputs.working-directory }} diff --git a/.gitea/workflows/test-rust.yaml b/.gitea/workflows/test-rust.yaml new file mode 100644 index 0000000..a423a2f --- /dev/null +++ b/.gitea/workflows/test-rust.yaml @@ -0,0 +1,47 @@ +# Reusable workflow: Rust testing with cargo test +# Usage: uses: wectrl-net/ci-templates/.gitea/workflows/test-rust.yaml@main +name: Test Rust (cargo) + +on: + workflow_call: + inputs: + rust-toolchain: + description: "Rust toolchain" + required: false + type: string + default: "stable" + working-directory: + description: "Directory containing the Rust project" + required: false + type: string + default: "." + cargo-test-args: + description: "Additional cargo test arguments" + required: false + type: string + default: "--all-features" + +jobs: + test: + name: cargo test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ inputs.rust-toolchain }} + - name: Cache cargo + uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + ${{ inputs.working-directory }}/target/ + key: ${{ runner.os }}-cargo-test-${{ hashFiles('**/Cargo.lock') }} + restore-keys: ${{ runner.os }}-cargo-test- + - name: Run tests + run: cargo test ${{ inputs.cargo-test-args }} + working-directory: ${{ inputs.working-directory }} diff --git a/README.md b/README.md index 54feb80..03118a1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,158 @@ -# ci-templates +# wectrl CI Pipeline Templates -Reusable CI/CD pipeline templates for Gitea Actions \ No newline at end of file +Reusable Gitea Actions workflows for all wectrl services. These live in the `wectrl-net/ci-templates` repository and are called from each service repo. + +## Setup + +### 1. Create the `ci-templates` repo on Gitea + +Create a new repo at `git.wectrl.net/wectrl-net/ci-templates` and push the `.gitea/workflows/` directory from this template. + +### 2. Required secrets per service repo + +Each service repo needs these secrets configured in Gitea (Settings > Actions > Secrets): + +| Secret | Description | +|--------|-------------| +| `REGISTRY_USER` | Gitea username for pushing images | +| `REGISTRY_TOKEN` | Gitea token with `packages:write` scope | +| `GIT_USER` | Gitea username for pushing to k8s cluster repo | +| `GIT_TOKEN` | Gitea token with `repo:write` scope on `wectrl-k8s-cluster` | + +### 3. Add workflows to your service repo + +Copy the appropriate example from `examples/` into your repo's `.gitea/workflows/` directory and customize the parameters. + +## Available Templates + +### Lint workflows + +| Template | Language | Tool | +|----------|----------|------| +| `lint-python.yaml` | Python | Ruff | +| `lint-node.yaml` | Node/TS | ESLint + tsc | +| `lint-rust.yaml` | Rust | Clippy + rustfmt | + +### Test workflows + +| Template | Language | Tool | +|----------|----------|------| +| `test-python.yaml` | Python | pytest | +| `test-node.yaml` | Node/TS | npm test (Vitest/Jest) | +| `test-rust.yaml` | Rust | cargo test | + +### Build & Deploy workflows + +| Template | Purpose | +|----------|---------| +| `build-push.yaml` | Build Docker image, push to `git.wectrl.net` registry | +| `deploy-k8s.yaml` | Update image tag in `wectrl-k8s-cluster` repo (ArgoCD GitOps) | + +## Examples + +### Python + React fullstack (h1per-pms pattern) + +```yaml +# .gitea/workflows/ci.yml +name: CI +on: + pull_request: + branches: [main, dev] + push: + branches: [main, dev] + +jobs: + lint-backend: + uses: wectrl-net/ci-templates/.gitea/workflows/lint-python.yaml@main + lint-frontend: + uses: wectrl-net/ci-templates/.gitea/workflows/lint-node.yaml@main + with: + working-directory: web + test-backend: + uses: wectrl-net/ci-templates/.gitea/workflows/test-python.yaml@main + test-frontend: + uses: wectrl-net/ci-templates/.gitea/workflows/test-node.yaml@main + with: + working-directory: web +``` + +### Rust service (wectrl-telemetry pattern) + +```yaml +# .gitea/workflows/ci.yml +name: CI +on: + pull_request: + branches: [main, dev] + push: + branches: [main, dev] + +jobs: + lint: + uses: wectrl-net/ci-templates/.gitea/workflows/lint-rust.yaml@main + test: + uses: wectrl-net/ci-templates/.gitea/workflows/test-rust.yaml@main +``` + +## Pipeline flow + +``` +PR / push to dev push to main + │ │ + ▼ ▼ + ┌───────┐ ┌───────┐ + │ Lint │ │ Lint │ + │ Test │ │ Test │ + └───────┘ └───┬───┘ + │ + ▼ + ┌───────────┐ + │ Build & │ + │ Push Image│ + └─────┬─────┘ + │ + ▼ + ┌───────────┐ + │ Update │ + │ k8s repo │ + └─────┬─────┘ + │ + ▼ + ┌───────────┐ + │ ArgoCD │ + │ auto-sync │ + └───────────┘ +``` + +## Service mapping + +| Service | Repo | Stack | Deploy path in k8s-cluster | +|---------|------|-------|---------------------------| +| h1per-pms | `wectrl-net/h1per-pms` | Python + React/TS | `saas/h1per/backend/deployment.yaml` | +| clok1-landing | `wectrl-net/clok1-landing` | Node/TS | `saas/clok1/app/deployment.yaml` | +| solar-platform | `wectrl-net/solar-platform` | TBD | `platform/components/wectrl-solar-platform/api-deployment.yaml` | +| solar-web | `wectrl-net/solar-web` | TBD | `platform/components/wectrl-solar-platform/web-deployment.yaml` | +| client-portal API | `wectrl-net/wectrl-client-portal` | TBD | `platform/components/wectrl-client-portal/api-deployment.yaml` | +| client-portal frontend | `wectrl-net/wectrl-client-portal-frontend` | TBD | `platform/components/wectrl-client-portal/frontend-deployment.yaml` | +| wectrl-telemetry | `wectrl-net/wectrl-telemetry` | Rust | TBD (needs k8s manifests) | + +## Customization + +All templates accept inputs with sensible defaults. Override only what differs from the standard: + +```yaml +jobs: + lint: + uses: wectrl-net/ci-templates/.gitea/workflows/lint-python.yaml@main + with: + python-version: "3.12" # override default 3.13 + working-directory: backend # if Python code is in a subdirectory +``` + +## Notes + +- All workflows trigger on both `main` and `dev` branches (per CON-569 branching strategy) +- Build & deploy only runs on push to `main` (production deploy) +- Dev/staging deploys can be added by extending `deploy-k8s.yaml` with a branch condition +- The runner is ARM64 (`linux/arm64`) matching the Hetzner CAX cluster nodes +- Semantic versioning tags (`v1.2.3`) are supported by `build-push.yaml` via the metadata action diff --git a/examples/node-frontend/build-deploy.yml b/examples/node-frontend/build-deploy.yml new file mode 100644 index 0000000..94b174a --- /dev/null +++ b/examples/node-frontend/build-deploy.yml @@ -0,0 +1,35 @@ +# Example build & deploy workflow for a Node.js frontend +# Place in your repo at: .gitea/workflows/build-deploy.yml +name: Build & Deploy + +on: + push: + branches: [main] + +concurrency: + group: deploy-${{ gitea.ref }} + cancel-in-progress: true + +jobs: + ci: + uses: ./.gitea/workflows/ci.yml + + build: + needs: ci + uses: wectrl-net/ci-templates/.gitea/workflows/build-push.yaml@main + with: + image-name: git.wectrl.net/wectrl-net/clok1-landing + secrets: + REGISTRY_USER: ${{ secrets.REGISTRY_USER }} + REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} + + deploy: + needs: build + uses: wectrl-net/ci-templates/.gitea/workflows/deploy-k8s.yaml@main + with: + image-name: git.wectrl.net/wectrl-net/clok1-landing + service-name: clok1-landing + deploy-paths: "saas/clok1/app/deployment.yaml" + secrets: + GIT_USER: ${{ secrets.GIT_USER }} + GIT_TOKEN: ${{ secrets.GIT_TOKEN }} diff --git a/examples/node-frontend/ci.yml b/examples/node-frontend/ci.yml new file mode 100644 index 0000000..9cc6db5 --- /dev/null +++ b/examples/node-frontend/ci.yml @@ -0,0 +1,24 @@ +# Example CI workflow for a Node.js/TypeScript frontend service (e.g. clok1-landing) +# Place in your repo at: .gitea/workflows/ci.yml +name: CI + +on: + pull_request: + branches: [main, staging] + push: + branches: [main, staging] + +concurrency: + group: ci-${{ gitea.ref }} + cancel-in-progress: true + +jobs: + lint: + uses: wectrl-net/ci-templates/.gitea/workflows/lint-node.yaml@main + with: + node-version: "22" + + test: + uses: wectrl-net/ci-templates/.gitea/workflows/test-node.yaml@main + with: + node-version: "22" diff --git a/examples/python-fullstack/build-deploy.yml b/examples/python-fullstack/build-deploy.yml new file mode 100644 index 0000000..9913885 --- /dev/null +++ b/examples/python-fullstack/build-deploy.yml @@ -0,0 +1,35 @@ +# Example build & deploy workflow for a Python fullstack service +# Place in your repo at: .gitea/workflows/build-deploy.yml +name: Build & Deploy + +on: + push: + branches: [main] + +concurrency: + group: deploy-${{ gitea.ref }} + cancel-in-progress: true + +jobs: + ci: + uses: ./.gitea/workflows/ci.yml + + build: + needs: ci + uses: wectrl-net/ci-templates/.gitea/workflows/build-push.yaml@main + with: + image-name: git.wectrl.net/wectrl-net/h1per-pms + secrets: + REGISTRY_USER: ${{ secrets.REGISTRY_USER }} + REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} + + deploy: + needs: build + uses: wectrl-net/ci-templates/.gitea/workflows/deploy-k8s.yaml@main + with: + image-name: git.wectrl.net/wectrl-net/h1per-pms + service-name: h1per-pms + deploy-paths: "saas/h1per/backend/deployment.yaml" + secrets: + GIT_USER: ${{ secrets.GIT_USER }} + GIT_TOKEN: ${{ secrets.GIT_TOKEN }} diff --git a/examples/python-fullstack/ci.yml b/examples/python-fullstack/ci.yml new file mode 100644 index 0000000..3069c11 --- /dev/null +++ b/examples/python-fullstack/ci.yml @@ -0,0 +1,34 @@ +# Example CI workflow for a Python backend + Node.js frontend service (e.g. h1per-pms) +# Place in your repo at: .gitea/workflows/ci.yml +name: CI + +on: + pull_request: + branches: [main, staging] + push: + branches: [main, staging] + +concurrency: + group: ci-${{ gitea.ref }} + cancel-in-progress: true + +jobs: + lint-backend: + uses: wectrl-net/ci-templates/.gitea/workflows/lint-python.yaml@main + with: + python-version: "3.13" + + lint-frontend: + uses: wectrl-net/ci-templates/.gitea/workflows/lint-node.yaml@main + with: + working-directory: web + + test-backend: + uses: wectrl-net/ci-templates/.gitea/workflows/test-python.yaml@main + with: + python-version: "3.13" + + test-frontend: + uses: wectrl-net/ci-templates/.gitea/workflows/test-node.yaml@main + with: + working-directory: web diff --git a/examples/rust-service/build-deploy.yml b/examples/rust-service/build-deploy.yml new file mode 100644 index 0000000..8f840c3 --- /dev/null +++ b/examples/rust-service/build-deploy.yml @@ -0,0 +1,35 @@ +# Example build & deploy workflow for a Rust service +# Place in your repo at: .gitea/workflows/build-deploy.yml +name: Build & Deploy + +on: + push: + branches: [main] + +concurrency: + group: deploy-${{ gitea.ref }} + cancel-in-progress: true + +jobs: + ci: + uses: ./.gitea/workflows/ci.yml + + build: + needs: ci + uses: wectrl-net/ci-templates/.gitea/workflows/build-push.yaml@main + with: + image-name: git.wectrl.net/wectrl-net/wectrl-telemetry + secrets: + REGISTRY_USER: ${{ secrets.REGISTRY_USER }} + REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} + + deploy: + needs: build + uses: wectrl-net/ci-templates/.gitea/workflows/deploy-k8s.yaml@main + with: + image-name: git.wectrl.net/wectrl-net/wectrl-telemetry + service-name: wectrl-telemetry + deploy-paths: "platform/components/wectrl-telemetry/deployment.yaml" + secrets: + GIT_USER: ${{ secrets.GIT_USER }} + GIT_TOKEN: ${{ secrets.GIT_TOKEN }} diff --git a/examples/rust-service/ci.yml b/examples/rust-service/ci.yml new file mode 100644 index 0000000..713045e --- /dev/null +++ b/examples/rust-service/ci.yml @@ -0,0 +1,24 @@ +# Example CI workflow for a Rust service (e.g. wectrl-telemetry) +# Place in your repo at: .gitea/workflows/ci.yml +name: CI + +on: + pull_request: + branches: [main, staging] + push: + branches: [main, staging] + +concurrency: + group: ci-${{ gitea.ref }} + cancel-in-progress: true + +jobs: + lint: + uses: wectrl-net/ci-templates/.gitea/workflows/lint-rust.yaml@main + with: + rust-toolchain: stable + + test: + uses: wectrl-net/ci-templates/.gitea/workflows/test-rust.yaml@main + with: + rust-toolchain: stable