# Contributing to Calminer We welcome contributions to Calminer! If you would like to contribute, please follow these guidelines: ## Fork the Repository Create a personal copy of the repository on your GitHub account. ## Create a Branch Before making changes, create a new branch for your feature or bug fix. ## Make Your Changes Implement your changes in the new branch. ## Write Tests Ensure that your changes are covered by tests. ## Run Test Suite With Coverage Execute the default pytest run to enforce the 80% project-wide coverage threshold and review missing lines in the terminal report. ```bash pytest ``` ## Run Export Test Suite Before opening a pull request, run the export-focused pytest module to verify CSV/XLSX streaming endpoints. ```bash pytest tests/test_export_routes.py ``` This ensures the API headers, download content, and modal routes remain functional. ## Submit a Pull Request Once you are satisfied with your changes, submit a pull request to the main repository. ## Continuous Integration Calminer uses Gitea Actions for automated testing, linting, and deployment. The pipeline is orchestrated by `.gitea/workflows/ci.yml`, which delegates to reusable stage workflows that run entirely on the self-hosted Gitea runner: - `.gitea/workflows/ci-lint.yml` checks out the repository, installs dependencies, and runs Ruff, Black, and Bandit. - `.gitea/workflows/ci-test.yml` provisions PostgreSQL 17, installs dependencies, executes pytest with an 80% coverage threshold, and uploads `coverage.xml` plus `pytest-report.xml` artifacts. - `.gitea/workflows/ci-build.yml` builds the Docker image, pushing tags only for `main` branch pushes (never for pull requests) when registry credentials are configured. It retains the optional deployment job gated by commit messages (`[deploy staging]`, `[deploy production]`). The workflow validates that the configured registry host matches the current Gitea instance to avoid publishing to the wrong registry. - `.gitea/workflows/deploy-coolify.yml` runs on `push` events to `main` (and via manual dispatch) once the repository is checked out. It bundles `docker-compose.prod.yml`, requires Coolify secrets (`COOLIFY_BASE_URL`, `COOLIFY_API_TOKEN`, `COOLIFY_APPLICATION_ID`, optional `COOLIFY_DEPLOY_ENV`), and calls the Coolify `/api/v1/deploy` endpoint with the application UUID. ### Workflow Behavior - `CI - Lint` triggers on push/PR to `main`, `develop`, or `v2` and must succeed before downstream workflows start. - `CI - Test` and `CI - Build` run as dependent jobs within the orchestrating workflow, so artifacts and images reflect the linted commit. - Coverage below 80% fails the test workflow and stops the build sequence. - Artifacts remain available for PR inspection via the test workflow. - Docker pushes occur only for main-branch pushes (PRs will never publish images). Deployments run exclusively on `main` pushes and require explicit `[deploy staging]` / `[deploy production]` markers. - Coolify automation also runs only for `main` pushes and relies on the configured application UUID to target the correct deployment. ### Gitea Runner and Registry Configuration The runner and registry are self-hosted within Gitea. Configure the following secrets in the repository settings before enabling the workflows: - `REGISTRY_URL`: Base URL of the Gitea container registry (for example `https://git.example.com`). - `REGISTRY_USERNAME` / `REGISTRY_PASSWORD`: Credentials with permission to push images to the project namespace. - `COOLIFY_BASE_URL`: Base URL to the Coolify instance (no trailing slash). - `COOLIFY_API_TOKEN`: Personal API token from Coolify with deploy permission. - `COOLIFY_APPLICATION_ID`: Coolify application UUID (see **Applications → Settings → UUID** in the Coolify UI). - `COOLIFY_DEPLOY_ENV` (optional): Multiline environment file content; omit if `deploy/.env` is stored in the repo. - `KUBE_CONFIG`, `STAGING_KUBE_CONFIG`, `PROD_KUBE_CONFIG` (optional): Base64 encoded kubeconfig for the optional k8s deployment job. - `K8S_DEPLOY_ENABLED` (optional): Set to `true` to allow the CI deploy job to run Kubernetes steps; leave unset/any other value to skip k8s updates (Coolify deploy still runs). Tips: - Ensure DNS records resolve the registry host for the runner network. Runner logs such as `logs/ci-lint-399.log` will show failures if the host cannot be resolved. - The workflows prefer `GITEA_*` environment variables when available (for example `GITEA_REF`, `GITEA_SHA`) and fall back to GitHub-compatible names, guaranteeing operation on a native Gitea runner. - If you change the registry endpoint, update `REGISTRY_URL` and verify the workflow warning emitted by the “Validate registry configuration” step to avoid pushing images to the wrong registry. ### Local Testing To replicate CI locally: ```bash # Install test deps pip install -r requirements-test.txt # Run linting ruff check . black --check . # Run tests with coverage pytest --cov=. --cov-report=term-missing --cov-fail-under=80 # Build image docker build -t calminer . ``` Thank you for your interest in contributing to Calminer!