first commit
Some checks failed
Validate, publish and deploy / validate (push) Successful in 2m2s
Validate, publish and deploy / publish-and-deploy (push) Failing after 8s

This commit is contained in:
Cauê Faleiros
2026-09-15 16:42:34 -03:00
commit 98c951d374
170 changed files with 95988 additions and 0 deletions

109
.gitea/workflows/deploy.yml Normal file
View File

@@ -0,0 +1,109 @@
name: Validate, publish and deploy
on:
pull_request:
push:
branches: [main]
workflow_dispatch:
jobs:
validate:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- name: Validate source and deployment definitions
run: |
python3 -m py_compile local/*.py deploy/*.py
python3 -m unittest local.test_dependency_lock local.test_staging_readiness deploy.test_production_preflight local.test_pricing -v
sh -n local/lock_dependencies.sh
docker compose config --quiet
docker compose -f compose.staging.yaml config --quiet
set -a
. deploy/portainer.env.example
set +a
docker stack config --compose-file deploy/stack.yaml >/dev/null
publish-and-deploy:
needs: validate
if: gitea.event_name == 'push' && gitea.ref == 'refs/heads/main'
runs-on: ubuntu-latest
timeout-minutes: 75
env:
COMPOSE_PROJECT_NAME: dtf-release-${{ gitea.run_number }}
REGISTRY_HOST: ${{ vars.REGISTRY_HOST }}
REGISTRY_OWNER: ${{ vars.REGISTRY_OWNER }}
PYTHON_BASE_IMAGE: ${{ vars.PYTHON_BASE_IMAGE }}
NGINX_BASE_IMAGE: ${{ vars.NGINX_BASE_IMAGE }}
TRIVY_IMAGE: ${{ vars.TRIVY_IMAGE }}
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- name: Require production-capable application source
run: python3 deploy/production_preflight.py --source-only
- name: Validate immutable build inputs
run: |
for value in "$PYTHON_BASE_IMAGE" "$NGINX_BASE_IMAGE" "$TRIVY_IMAGE"; do
echo "$value" | grep -Eq '^[a-z0-9][a-z0-9._:/-]*@sha256:[0-9a-f]{64}$'
echo "$value" | grep -Ev '@sha256:0{64}$' >/dev/null
done
case "$REGISTRY_HOST/$REGISTRY_OWNER" in *[A-Z]*|*' '*|'/'*) exit 2;; esac
- name: Run complete isolated regression suite
run: |
docker compose up --build -d --wait
python3 -m local.security_test
python3 -m local.scanning_test
python3 -m local.smoke_test
python3 -m local.workflow_test
docker compose exec -T api python -m local.runtime_security_test
docker compose exec -T api python -m local.retention_test
node local/browser_test.mjs
python3 -m local.backup create-and-verify
- name: Build production images
run: |
api_sha="$REGISTRY_HOST/$REGISTRY_OWNER/dtf-api:${{ gitea.sha }}"
api_latest="$REGISTRY_HOST/$REGISTRY_OWNER/dtf-api:latest"
web_sha="$REGISTRY_HOST/$REGISTRY_OWNER/dtf-web:${{ gitea.sha }}"
web_latest="$REGISTRY_HOST/$REGISTRY_OWNER/dtf-web:latest"
docker build --pull --file deploy/Dockerfile.api \
--build-arg PYTHON_BASE_IMAGE="$PYTHON_BASE_IMAGE" \
--build-arg VCS_REF="${{ gitea.sha }}" \
--tag "$api_sha" --tag "$api_latest" .
docker build --pull --file deploy/Dockerfile.web \
--build-arg PYTHON_BASE_IMAGE="$PYTHON_BASE_IMAGE" \
--build-arg NGINX_BASE_IMAGE="$NGINX_BASE_IMAGE" \
--build-arg VCS_REF="${{ gitea.sha }}" \
--tag "$web_sha" --tag "$web_latest" .
- name: Block secret, configuration and image findings
run: |
api="$REGISTRY_HOST/$REGISTRY_OWNER/dtf-api:${{ gitea.sha }}"
web="$REGISTRY_HOST/$REGISTRY_OWNER/dtf-web:${{ gitea.sha }}"
docker run --rm --volume "$PWD:/src:ro" --workdir /src "$TRIVY_IMAGE" \
fs --scanners secret --exit-code 1 --severity HIGH,CRITICAL .
docker run --rm --volume "$PWD:/src:ro" --workdir /src "$TRIVY_IMAGE" \
config --exit-code 1 --severity HIGH,CRITICAL deploy
docker run --rm --volume /var/run/docker.sock:/var/run/docker.sock:ro "$TRIVY_IMAGE" \
image --exit-code 1 --scanners vuln --severity HIGH,CRITICAL "$api"
docker run --rm --volume /var/run/docker.sock:/var/run/docker.sock:ro "$TRIVY_IMAGE" \
image --exit-code 1 --scanners vuln --severity HIGH,CRITICAL "$web"
- name: Publish latest and rollback tags
env:
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: |
trap 'docker logout "$REGISTRY_HOST" >/dev/null 2>&1 || true' EXIT
echo "$REGISTRY_TOKEN" | docker login "$REGISTRY_HOST" --username "$REGISTRY_USERNAME" --password-stdin
docker push "$REGISTRY_HOST/$REGISTRY_OWNER/dtf-api:${{ gitea.sha }}"
docker push "$REGISTRY_HOST/$REGISTRY_OWNER/dtf-api:latest"
docker push "$REGISTRY_HOST/$REGISTRY_OWNER/dtf-web:${{ gitea.sha }}"
docker push "$REGISTRY_HOST/$REGISTRY_OWNER/dtf-web:latest"
- name: Trigger the Portainer stack webhook
env:
PORTAINER_WEBHOOK: ${{ secrets.PORTAINER_WEBHOOK }}
run: |
test -n "$PORTAINER_WEBHOOK"
curl --fail --silent --show-error --max-time 30 --request POST "$PORTAINER_WEBHOOK"
- name: Stop isolated test stack
if: always()
run: docker compose down --volumes --remove-orphans