diff --git a/.gitea/workflows/ci-build.yml b/.gitea/workflows/ci-build.yml new file mode 100644 index 0000000..99456a5 --- /dev/null +++ b/.gitea/workflows/ci-build.yml @@ -0,0 +1,150 @@ +name: CI - Build + +on: + workflow_call: + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + env: + DEFAULT_BRANCH: main + REGISTRY_URL: ${{ secrets.REGISTRY_URL }} + REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} + REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} + REGISTRY_CONTAINER_NAME: calminer + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Collect workflow metadata + id: meta + shell: bash + env: + DEFAULT_BRANCH: ${{ env.DEFAULT_BRANCH }} + run: | + ref_name="${GITHUB_REF_NAME:-${GITHUB_REF##*/}}" + event_name="${GITHUB_EVENT_NAME:-}" + sha="${GITHUB_SHA:-}" + + if [ "$ref_name" = "${DEFAULT_BRANCH:-main}" ]; then + echo "on_default=true" >> "$GITHUB_OUTPUT" + else + echo "on_default=false" >> "$GITHUB_OUTPUT" + fi + + echo "ref_name=$ref_name" >> "$GITHUB_OUTPUT" + echo "event_name=$event_name" >> "$GITHUB_OUTPUT" + echo "sha=$sha" >> "$GITHUB_OUTPUT" + + - name: Set up QEMU and Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to gitea registry + if: ${{ steps.meta.outputs.on_default == 'true' }} + uses: docker/login-action@v3 + continue-on-error: true + with: + registry: ${{ env.REGISTRY_URL }} + username: ${{ env.REGISTRY_USERNAME }} + password: ${{ env.REGISTRY_PASSWORD }} + + - name: Build image + id: build-image + env: + REGISTRY_URL: ${{ env.REGISTRY_URL }} + REGISTRY_CONTAINER_NAME: ${{ env.REGISTRY_CONTAINER_NAME }} + SHA_TAG: ${{ steps.meta.outputs.sha }} + PUSH_IMAGE: ${{ steps.meta.outputs.on_default == 'true' && steps.meta.outputs.event_name != 'pull_request' && env.REGISTRY_URL != '' && env.REGISTRY_USERNAME != '' && env.REGISTRY_PASSWORD != '' }} + run: | + set -eo pipefail + LOG_FILE=build.log + if [ "${PUSH_IMAGE}" = "true" ]; then + docker buildx build \ + --push \ + --tag "${REGISTRY_URL}/allucanget/${REGISTRY_CONTAINER_NAME}:latest" \ + --tag "${REGISTRY_URL}/allucanget/${REGISTRY_CONTAINER_NAME}:${SHA_TAG}" \ + --file Dockerfile \ + . 2>&1 | tee "${LOG_FILE}" + else + docker buildx build \ + --load \ + --tag "${REGISTRY_CONTAINER_NAME}:ci" \ + --file Dockerfile \ + . 2>&1 | tee "${LOG_FILE}" + fi + + - name: Upload docker build logs + if: failure() + uses: actions/upload-artifact@v4 + with: + name: docker-build-logs + path: build.log + + deploy: + needs: build + if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' + runs-on: ubuntu-latest + env: + REGISTRY_URL: ${{ secrets.REGISTRY_URL }} + REGISTRY_CONTAINER_NAME: calminer + KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }} + STAGING_KUBE_CONFIG: ${{ secrets.STAGING_KUBE_CONFIG }} + PROD_KUBE_CONFIG: ${{ secrets.PROD_KUBE_CONFIG }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up kubectl for staging + if: github.event.head_commit && contains(github.event.head_commit.message, '[deploy staging]') + uses: azure/k8s-set-context@v3 + with: + method: kubeconfig + kubeconfig: ${{ env.STAGING_KUBE_CONFIG }} + + - name: Set up kubectl for production + if: github.event.head_commit && contains(github.event.head_commit.message, '[deploy production]') + uses: azure/k8s-set-context@v3 + with: + method: kubeconfig + kubeconfig: ${{ env.PROD_KUBE_CONFIG }} + + - name: Deploy to staging + if: github.event.head_commit && contains(github.event.head_commit.message, '[deploy staging]') + run: | + kubectl set image deployment/calminer-app calminer=${REGISTRY_URL}/allucanget/${REGISTRY_CONTAINER_NAME}:latest + kubectl apply -f k8s/configmap.yaml + kubectl apply -f k8s/secret.yaml + kubectl rollout status deployment/calminer-app + + - name: Collect staging deployment logs + if: github.event.head_commit && contains(github.event.head_commit.message, '[deploy staging]') + run: | + mkdir -p logs/deployment/staging + kubectl get pods -o wide > logs/deployment/staging/pods.txt + kubectl get deployment calminer-app -o yaml > logs/deployment/staging/deployment.yaml + kubectl logs deployment/calminer-app --all-containers=true --tail=500 > logs/deployment/staging/calminer-app.log + + - name: Deploy to production + if: github.event.head_commit && contains(github.event.head_commit.message, '[deploy production]') + run: | + kubectl set image deployment/calminer-app calminer=${REGISTRY_URL}/allucanget/${REGISTRY_CONTAINER_NAME}:latest + kubectl apply -f k8s/configmap.yaml + kubectl apply -f k8s/secret.yaml + kubectl rollout status deployment/calminer-app + + - name: Collect production deployment logs + if: github.event.head_commit && contains(github.event.head_commit.message, '[deploy production]') + run: | + mkdir -p logs/deployment/production + kubectl get pods -o wide > logs/deployment/production/pods.txt + kubectl get deployment calminer-app -o yaml > logs/deployment/production/deployment.yaml + kubectl logs deployment/calminer-app --all-containers=true --tail=500 > logs/deployment/production/calminer-app.log + + - name: Upload deployment logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: deployment-logs + path: logs/deployment + if-no-files-found: ignore diff --git a/.gitea/workflows/ci-lint.yml b/.gitea/workflows/ci-lint.yml new file mode 100644 index 0000000..b905a36 --- /dev/null +++ b/.gitea/workflows/ci-lint.yml @@ -0,0 +1,44 @@ +name: CI - Lint + +on: + workflow_call: + workflow_dispatch: + +jobs: + lint: + runs-on: ubuntu-latest + env: + APT_CACHER_NG: http://192.168.88.14:3142 + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.12" + + - name: Configure apt proxy + run: | + if [ -n "${APT_CACHER_NG}" ]; then + echo "Acquire::http::Proxy \"${APT_CACHER_NG}\";" | tee /etc/apt/apt.conf.d/01apt-cacher-ng + fi + + - name: Install system packages + run: | + apt-get update + apt-get install -y build-essential libpq-dev + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install -r requirements-test.txt + + - name: Run Ruff + run: ruff check . + + - name: Run Black + run: black --check . + + - name: Run Bandit + run: bandit -c pyproject.toml -r tests diff --git a/.gitea/workflows/ci-test.yml b/.gitea/workflows/ci-test.yml new file mode 100644 index 0000000..0cf1572 --- /dev/null +++ b/.gitea/workflows/ci-test.yml @@ -0,0 +1,73 @@ +name: CI - Test + +on: + workflow_call: + workflow_dispatch: + +jobs: + test: + runs-on: ubuntu-latest + env: + APT_CACHER_NG: http://192.168.88.14:3142 + DB_DRIVER: postgresql+psycopg2 + DB_HOST: 192.168.88.35 + DB_NAME: calminer_test + DB_USER: calminer + DB_PASSWORD: calminer_password + services: + postgres: + image: postgres:17 + env: + POSTGRES_USER: ${{ env.DB_USER }} + POSTGRES_PASSWORD: ${{ env.DB_PASSWORD }} + POSTGRES_DB: ${{ env.DB_NAME }} + 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 Python + uses: actions/setup-python@v4 + with: + python-version: "3.12" + + - name: Configure apt proxy + run: | + if [ -n "${APT_CACHER_NG}" ]; then + echo "Acquire::http::Proxy \"${APT_CACHER_NG}\";" | tee /etc/apt/apt.conf.d/01apt-cacher-ng + fi + + - name: Install system packages + run: | + apt-get update + apt-get install -y build-essential libpq-dev + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install -r requirements-test.txt + + - name: Run tests + env: + DATABASE_DRIVER: ${{ env.DB_DRIVER }} + DATABASE_HOST: postgres + DATABASE_PORT: 5432 + DATABASE_USER: ${{ env.DB_USER }} + DATABASE_PASSWORD: ${{ env.DB_PASSWORD }} + DATABASE_NAME: ${{ env.DB_NAME }} + run: | + pytest --cov=. --cov-report=term-missing --cov-report=xml --cov-fail-under=80 --junitxml=pytest-report.xml + + - name: Upload test artifacts + if: always() + uses: actions/upload-artifact@v3 + with: + name: test-artifacts + path: | + coverage.xml + pytest-report.xml diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..2896f94 --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,30 @@ +name: CI + +on: + push: + branches: + - main + - develop + - v2 + pull_request: + branches: + - main + - develop + workflow_dispatch: + +jobs: + lint: + uses: ./.gitea/workflows/ci-lint.yml + secrets: inherit + + test: + needs: lint + uses: ./.gitea/workflows/ci-test.yml + secrets: inherit + + build: + needs: + - lint + - test + uses: ./.gitea/workflows/ci-build.yml + secrets: inherit