# Dejo CI Conventional Commits e Semantic Release > Guia de configuração, desenvolvimento e fluxo de CI/CD com Conventional Commits e Semantic Release no Gitea. --- ## 📋 Índice - [Pré-requisitos](#-pré-requisitos) - [Clonando o Repositório](#-clonando-o-repositório) - [⚙️ Instalação e Hooks](#-instalação-e-hooks) - [📦 Conventional Commits](#-conventional-commits) - [🚀 Fluxo de CI/CD](#-fluxo-de-cicd) - [📝 Novos Releases](#-novos-releases) - [🛠️ Troubleshooting](#-troubleshooting) --- ## 🔧 Pré-requisitos - Git v2.25+ - Node.js v20.x LTS - npm v8+ - Acesso ao repositório no Gitea com permissão para _secrets_ --- ## 🔗 Clonando o Repositório ```bash git clone https://git.dejodigital.com.br/dejo-core/dejo-node.git cd dejo-node ``` --- ## ⚙️ Instalação e Hooks > ⚠️ O**Atenção:** é obrigatório execute `npm ci --no-audit` antes de qualquer commit. Isso instala as dependências e configura os hooks; sem isso, o hook `commit-msg` não será instalado e seus commits serão bloqueados. Instale dependências e configure hooks: ```bash npm ci --no-audit ``` **Testando o hook:** ```bash # Deve falhar git commit --allow-empty -m "mensagem inválida" # Deve passar git commit --allow-empty -m "feat: testando hook de commit-msg" ``` --- ## 📦 Conventional Commits Por padrão o semantic-release, usando o preset conventionalcommits, só considera como “mudanças que geram release”: - `feat`: → bump minor - `fix`: → bump patch - `revert`: (gera bump major) **Qualquer commit com ! (quebra de compatibilidade) → bump major** Na especificação de Conventional Commits, o ponto de exclamação ! serve para sinalizar um breaking change (quebra de compatibilidade). Isso significa que qualquer commit cujo cabeçalho contenha ! — por exemplo: ```bash git commit -m "feat!: remove endpoint /v1/users BREAKING CHANGE: a remoção do endpoint /v1/users é incompatível com versões anteriores." ``` - O ! no cabeçalho já sinaliza o breaking change. - O rodapé BREAKING CHANGE: explica o porquê — neste caso, a incompatibilidade com versões antigas. - Quando CI (por exemplo, semantic-release) rodar, ele vai automaticamente detectar esse !/BREAKING CHANGE e gerar o bump major (por exemplo, de 1.3.0 para 2.0.0). Todos os outros tipos (docs:, style:, refactor:, test:, chore:, build:, ci:, perf:, revert: sem !) não disparam release algum — são classificados como no-release. Formato obrigatório: ```text (): ``` **Tipos válidos:** - `feat`: Nova funcionalidade - `fix`: Correção de bug - `docs`: Documentação - `style`: Formatação - `refactor`: Refatoração - `test`: Testes - `chore`: Tarefas de build/infra - `ci`: CI/CD - `perf`: Performance - `revert`: Reversão **Exemplo:** ```bash git commit -m "fix(api): corrige timeout na rota /users" ``` --- ## 🚀 Fluxo de CI/CD ***Atualmente o Gitea-Actions não suporta o evento workflow_run, então o segundo workflow não é acionado ao finalizar o CI. Por isso, consolidei os pipelines de CI e CD em um único workflow.*** O workflow está em **`.gitea/workflows/ci-and-cd.yml`**: ```yaml # .gitea/workflows/ci-and-cd.yml name: CI & CD on: push: branches: - master jobs: lint_commits: name: Lint Commits runs-on: [self-hosted] steps: - name: Checkout Repository uses: actions/checkout@v3 with: fetch-depth: 0 - name: Install Dependencies env: NODE_ENV: development NPM_CONFIG_PRODUCTION: 'false' run: npm ci --no-audit - name: Lint Commit Messages # Se qualquer mensagem não corresponder ao Conventional Commits, este step falha run: npx commitlint --from=origin/master --to=HEAD release: name: Release needs: lint_commits # só roda se lint_commits passar runs-on: [self-hosted] outputs: sha_short: ${{ steps.commit_short.outputs.sha_short }} is_tagged: ${{ steps.check_tag.outputs.is_tagged }} steps: - name: Checkout Repository uses: actions/checkout@v3 with: fetch-depth: 0 fetch-tags: true - name: Commit Short Hash id: commit_short run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' - name: Install Dependencies run: npm ci --no-audit - name: Run Semantic Release env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} GITEA_URL: https://git.dejodigital.com.br run: npx semantic-release - name: Check if Release Tag Exists id: check_tag run: | if git tag --points-at HEAD | grep -q '^v'; then echo "is_tagged=true" >> $GITHUB_OUTPUT else echo "is_tagged=false" >> $GITHUB_OUTPUT fi build_and_push: name: Docker | Build and Push needs: release if: ${{ needs.release.outputs.is_tagged == 'true' }} # só roda se semantic-release criou tag runs-on: [self-hosted] env: DEJO_NODE_AWS_REGION: us-east-1 AWS_ECR_REPOSITORY: dev-dejo/dejo-node DISABLE_DISCORD_NOTIFY: true DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} sha_short: ${{ needs.release.outputs.sha_short }} steps: - name: Checkout Repository uses: actions/checkout@v3 with: fetch-depth: 0 - name: Discord | Notify Start if: ${{ env.DISABLE_DISCORD_NOTIFY != 'true' }} run: | TAG=${GITHUB_REF#refs/tags/} curl -X POST -H "Content-Type: application/json" \ -d "{\"content\": \":arrow_forward: Deploy da versão **${TAG}** iniciado...\"}" \ "${DISCORD_WEBHOOK}" - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Copy Env run: cp infrastructure/.env.example infrastructure/.env - name: Cache Docker layers uses: actions/cache@v4 with: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-${{ github.sha }} restore-keys: ${{ runner.os }}-buildx - name: Docker Login to AWS ECR uses: docker/login-action@v2 with: registry: ${{ secrets.DEV_DEJO_AWS_ECR_REGISTRY }} username: ${{ secrets.DEJO_NODE_AWS_ACCESS_KEY }} password: ${{ secrets.DEJO_NODE_AWS_SECRET_KEY }} - name: Build and Push Backend uses: docker/build-push-action@v5 with: context: infrastructure file: infrastructure/Dockerfile push: true tags: | ${{ secrets.DEV_DEJO_AWS_ECR_REGISTRY }}/${{ env.AWS_ECR_REPOSITORY }}:latest ${{ secrets.DEV_DEJO_AWS_ECR_REGISTRY }}/${{ env.AWS_ECR_REPOSITORY }}:${{ env.sha_short }} cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,mode=max,dest=/tmp/.buildx-cache-new - name: Moving Cache run: | rm -rf /tmp/.buildx-cache mv /tmp/.buildx-cache-new /tmp/.buildx-cache kustomize_apply: name: Kubernetes | Kustomize Apply needs: build_and_push runs-on: [self-hosted] env: DEJO_NODE_AWS_REGION: us-east-1 KUBE_NAMESPACE: dejo-node steps: - name: Checkout Repository uses: actions/checkout@v3 with: fetch-depth: 0 - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ secrets.DEJO_NODE_AWS_ACCESS_KEY }} aws-secret-access-key: ${{ secrets.DEJO_NODE_AWS_SECRET_KEY }} aws-region: ${{ env.DEJO_NODE_AWS_REGION }} - name: Apply Kustomize run: | echo "${{ secrets.DEJO_NODE_KUBE_CONFIG_DATA_DEV }}" | base64 -d > kubeconfig export KUBECONFIG=$PWD/kubeconfig kubectl apply -k infrastructure/kubernetes/dev -n "${KUBE_NAMESPACE}" deploy_backend: name: Kubernetes | Deploy App needs: kustomize_apply runs-on: [self-hosted] env: DEJO_NODE_AWS_REGION: us-east-1 AWS_ECR_REPOSITORY: dev-dejo/dejo-node KUBE_NAMESPACE: dejo-node KUBE_DEPLOY_NAME: api-app DISABLE_DISCORD_NOTIFY: true DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} sha_short: ${{ needs.release.outputs.sha_short }} steps: - name: Checkout Repository uses: actions/checkout@v3 with: fetch-depth: 0 - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ secrets.DEJO_NODE_AWS_ACCESS_KEY }} aws-secret-access-key: ${{ secrets.DEJO_NODE_AWS_SECRET_KEY }} aws-region: ${{ env.DEJO_NODE_AWS_REGION }} - name: Deploy API run: | echo "${{ secrets.DEJO_NODE_KUBE_CONFIG_DATA_DEV }}" | base64 -d > kubeconfig export KUBECONFIG=$PWD/kubeconfig kubectl set image deployment/${{ env.KUBE_DEPLOY_NAME }} \ ${{ env.KUBE_DEPLOY_NAME }}="${{ secrets.DEV_DEJO_AWS_ECR_REGISTRY }}/${{ env.AWS_ECR_REPOSITORY }}:${{ env.sha_short }}" \ --record -n "${KUBE_NAMESPACE}" - name: Verify Rollout run: | echo "${{ secrets.DEJO_NODE_KUBE_CONFIG_DATA_DEV }}" | base64 -d > kubeconfig export KUBECONFIG=$PWD/kubeconfig kubectl rollout status deployment/${{ env.KUBE_DEPLOY_NAME }} -n "${KUBE_NAMESPACE}" - name: Discord | Notify Error if: ${{ failure() && env.DISABLE_DISCORD_NOTIFY != 'true' }} run: | curl -X POST -H "Content-Type: application/json" \ -d '{"content": ":x: Erro durante o deploy! Veja logs."}' \ "${{ env.DISCORD_WEBHOOK }}" exit 1 - name: Discord | Notify Success if: ${{ success() && env.DISABLE_DISCORD_NOTIFY != 'true' }} run: | curl -X POST -H "Content-Type: application/json" \ -d '{"content": ":white_check_mark: Deploy concluído com sucesso! :rocket:"}' \ "${{ env.DISCORD_WEBHOOK }}" ``` --- ## 🔑 Secrets necessários - **GITEA_TOKEN**: token com permissão de `repo:write` - **GITEA_URL**: URL da instância (ex.: `https://git.dejodigital.com.br`) --- ## 📝 Novos Releases Para criar um novo release, basta: ```bash git add . git commit -m "feat: adiciona recurso X" git push origin master ``` O CI vai: 1. Validar commits 2. Gerar versão semântica 3. Atualizar `CHANGELOG.md` 4. Criar tag `vX.Y.Z` 5. Publicar release no Gitea --- ## 🛠️ Troubleshooting - **commitlint não encontrado:** verifique `devDependencies` no `package.json` e se o `commitlint.config.js` está na raiz. - **Erro `addAbortListener`:** use Node.js v20 no workflow. - **Mensagens de audit:** use `--no-audit` ou configure `.npmrc` com `audit=false`. ---