From 537a97cecc321b02e6c400bd4cff233060eb3f1b Mon Sep 17 00:00:00 2001 From: Schuwi Date: Sat, 20 Sep 2025 12:24:50 +0200 Subject: [PATCH] ci: add gitea ci/cd pipeline --- .gitea/workflows/README.md | 121 ++++++++++++++++++++++++++++++ .gitea/workflows/code-quality.yml | 75 ++++++++++++++++++ .gitea/workflows/docker-build.yml | 69 +++++++++++++++++ config/test.exs | 2 +- 4 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 .gitea/workflows/README.md create mode 100644 .gitea/workflows/code-quality.yml create mode 100644 .gitea/workflows/docker-build.yml diff --git a/.gitea/workflows/README.md b/.gitea/workflows/README.md new file mode 100644 index 0000000..f6980e1 --- /dev/null +++ b/.gitea/workflows/README.md @@ -0,0 +1,121 @@ +# Gitea CI/CD Pipeline + +This directory contains Gitea Actions workflows for automated code quality checks and Docker image publishing. + +## Workflows + +### 1. Code Quality (`code-quality.yml`) + +Runs on every push to main and pull requests targeting main. This workflow: + +- Sets up Elixir 1.15 with OTP 26 +- Installs dependencies and restores caches for faster builds +- Checks for unused dependencies +- Compiles with warnings as errors (enforces clean compilation) +- Validates code formatting (`mix format --check-formatted`) +- Runs the full test suite +- Executes `mix precommit` to ensure all quality checks pass + +**Important**: This workflow will fail if `mix precommit` hasn't been run locally, ensuring code quality standards are maintained. + +### 2. Docker Build and Publish (`docker-build.yml`) + +Publishes Docker images to the Gitea container registry: + +- **Snapshot builds**: For every commit to main branch + - Tagged as: `latest`, `main`, `snapshot-{sha}` +- **Release builds**: For every tagged commit (e.g., `v1.0.0`) + - Tagged as: `{tag-name}`, `latest` + +Features: +- Multi-platform builds (linux/amd64, linux/arm64) +- Build caching for faster subsequent builds +- Comprehensive metadata and labels + +## Setup Requirements + +### 1. Gitea Configuration + +Update the `REGISTRY` environment variable in `docker-build.yml`: +```yaml +env: + REGISTRY: your-gitea-instance.com # Replace with your Gitea URL +``` + +### 2. Required Secrets + +Create the following secret in your Gitea repository settings: + +- `GITEAX_TOKEN`: Personal Access Token with package write permissions + - Go to your Gitea instance → Settings → Applications → Generate New Token + - Select "write:packages" scope + - Add this token as a repository secret named `GITEAX_TOKEN` + +> Gitea Actions currently do not support package repository authorization like GitHub Actions, so a PAT is necessary for publishing. +> See https://github.com/go-gitea/gitea/issues/23642#issuecomment-2119876692. + +### 3. Container Registry + +Enable the container registry in your Gitea instance if not already enabled. The published images will be available at: +``` +{your-gitea-instance}/{owner}/components-elixir +``` + +## Usage + +### For Developers + +Before pushing code, always run: +```bash +mix precommit +``` + +This ensures your code will pass the CI quality checks. + +### For Releases + +To create a release: +1. Tag your commit: `git tag v1.0.0` +2. Push the tag: `git push origin v1.0.0` +3. The pipeline will automatically build and publish a release image + +### For Snapshots + +Snapshot builds are created automatically for every commit to the main branch. + +## Docker Image Usage + +Pull and run the latest snapshot: +```bash +docker pull {your-gitea-instance}/{owner}/components-elixir:latest +docker run -p 4000:4000 {your-gitea-instance}/{owner}/components-elixir:latest +``` + +Pull and run a specific release: +```bash +docker pull {your-gitea-instance}/{owner}/components-elixir:v1.0.0 +docker run -p 4000:4000 {your-gitea-instance}/{owner}/components-elixir:v1.0.0 +``` + +## Gitea Actions Limitations + +This pipeline is designed with Gitea Actions limitations in mind: +- No `concurrency`, `run-name`, `permissions`, or `timeout-minutes` support +- Limited expression support (only `always()` function) +- Simple `runs-on` syntax only +- No package repository authorization - uses Personal Access Token instead + +## Troubleshooting + +### Authentication Issues +- Ensure `GITEAX_TOKEN` secret is properly set with package write permissions +- Verify the token hasn't expired + +### Build Failures +- Check that `mix precommit` passes locally +- Ensure all tests pass with the test database configuration +- Verify Docker build works locally: `docker build -t test .` + +### Registry Issues +- Confirm container registry is enabled in your Gitea instance +- Check that the registry URL in the workflow matches your Gitea instance \ No newline at end of file diff --git a/.gitea/workflows/code-quality.yml b/.gitea/workflows/code-quality.yml new file mode 100644 index 0000000..aaec850 --- /dev/null +++ b/.gitea/workflows/code-quality.yml @@ -0,0 +1,75 @@ +name: Code Quality + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + code-quality: + runs-on: ubuntu-latest + name: Code Quality (Elixir ${{matrix.elixir}} OTP ${{matrix.otp}}) + strategy: + matrix: + otp: ['26.0'] + elixir: ['1.15'] + + services: + db: + image: postgres:15 + ports: ['5432:5432'] + env: + POSTGRES_PASSWORD: postgres + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Elixir + uses: erlef/setup-beam@v1 + with: + elixir-version: ${{matrix.elixir}} + otp-version: ${{matrix.otp}} + + - name: Restore dependencies cache + uses: actions/cache@v4 + with: + path: deps + key: ${{ runner.os }}-mix-${{ hashFiles('**/mix.lock') }} + restore-keys: ${{ runner.os }}-mix- + + - name: Restore compiled code cache + uses: actions/cache@v4 + with: + path: _build + key: ${{ runner.os }}-build-${{ matrix.otp }}-${{ matrix.elixir }}-${{ hashFiles('**/mix.lock') }} + restore-keys: | + ${{ runner.os }}-build-${{ matrix.otp }}-${{ matrix.elixir }}- + + - name: Install dependencies + run: mix deps.get + + - name: Check for unused dependencies + run: mix deps.unlock --check-unused + + - name: Compile with warnings as errors + run: mix compile --warnings-as-errors + + - name: Check code formatting + run: mix format --check-formatted + + - name: Run tests + run: mix test + env: + POSTGRES_PASSWORD: postgres + + - name: Run precommit (should pass if all above passed) + run: mix precommit + env: + POSTGRES_PASSWORD: postgres \ No newline at end of file diff --git a/.gitea/workflows/docker-build.yml b/.gitea/workflows/docker-build.yml new file mode 100644 index 0000000..6544f4b --- /dev/null +++ b/.gitea/workflows/docker-build.yml @@ -0,0 +1,69 @@ +name: Docker Build and Publish + +on: + push: + branches: ["main"] + tags: ["v*"] + +env: + REGISTRY: git.maxboeer.com + IMAGE_NAME: components-elixir + +jobs: + docker-build: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=ref,event=tag + type=raw,value=latest,enable={{is_default_branch}} + type=raw,value=snapshot-{{sha}},enable={{is_default_branch}} + + - name: Log in to Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITEAX_TOKEN }} + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + build-args: | + ELIXIR_VERSION=1.15 + OTP_VERSION=26 + DEBIAN_VERSION=bookworm-slim + + - name: Generate summary + run: | + echo "## Docker Build Summary" >> $GITHUB_STEP_SUMMARY + echo "- **Image**: \`${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}\`" >> $GITHUB_STEP_SUMMARY + echo "- **Tags**: " >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + if [[ "${{ github.ref_type }}" == "tag" ]]; then + echo "- **Build Type**: Release build for tag \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY + else + echo "- **Build Type**: Snapshot build for branch \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY + fi + echo "- **Commit**: \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY \ No newline at end of file diff --git a/config/test.exs b/config/test.exs index 1e64d1c..6a30c71 100644 --- a/config/test.exs +++ b/config/test.exs @@ -7,7 +7,7 @@ import Config # Run `mix help test` for more information. config :components_elixir, ComponentsElixir.Repo, username: "postgres", - password: "fCnPB8VQdPkhJAD29hq6sZEY", + password: System.get_env("POSTGRES_PASSWORD") || "fCnPB8VQdPkhJAD29hq6sZEY", hostname: "localhost", database: "components_elixir_test#{System.get_env("MIX_TEST_PARTITION")}", pool: Ecto.Adapters.SQL.Sandbox,