diff --git a/.github/workflows/quality-gate.yml b/.github/workflows/quality-gate.yml index 9212f77..257dcbf 100644 --- a/.github/workflows/quality-gate.yml +++ b/.github/workflows/quality-gate.yml @@ -1,9 +1,9 @@ name: Quality gate on: - push: - branches: - - main +# push: +# branches: +# - main pull_request: branches: - main @@ -21,6 +21,138 @@ jobs: fetch-depth: 0 persist-credentials: false + - name: Calculate Version + id: calculate-version + if: github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + + // Função para calcular nova versão baseada no branch + function calculateVersion(lastVersion, branchName) { + const parseVersion = (v) => { + const match = v.match(/^(\d+)\.(\d+)\.(\d+)(?:-rc(\d+))?$/); + if (!match) throw new Error(`Invalid version format: ${v}`); + return { + major: parseInt(match[1]), + minor: parseInt(match[2]), + patch: parseInt(match[3]), + rc: match[4] ? parseInt(match[4]) : null + }; + }; + + const current = parseVersion(lastVersion); + + if (branchName.startsWith('release/')) { + return `${current.major + 1}.0.0`; + } else if (branchName.startsWith('feature/')) { + return `${current.major}.${current.minor + 1}.0`; + } else if (branchName.startsWith('fix/')) { + return `${current.major}.${current.minor}.${current.patch + 1}`; + } else if (branchName.startsWith('rc/')) { + if (current.rc !== null) { + return `${current.major}.${current.minor}.${current.patch}-rc${current.rc + 1}`; + } else { + return `${current.major}.${current.minor}.${current.patch}-rc1`; + } + } + + return null; // Não sugerir para outros tipos de branch + } + + try { + const branchName = context.payload.pull_request.head.ref; + console.log(`Branch name: ${branchName}`); + + // Validar se o branch segue os padrões aceitos + const validPrefixes = ['release/', 'feature/', 'fix/', 'rc/']; + const isValidBranch = validPrefixes.some(prefix => branchName.startsWith(prefix)); + + if (!isValidBranch) { + const errorMessage = `## 🚨 Erro: Nome do Branch Inválido\n\n` + + `O branch \`${branchName}\` não segue os padrões de nomenclatura aceitos.\n\n` + + `### 📝 Padrões Aceitos:\n` + + `- \`release/*\`: Para releases de major version (ex: release/v2.0.0)\n` + + `- \`feature/*\`: Para novas funcionalidades (ex: feature/nova-funcionalidade)\n` + + `- \`fix/*\`: Para correções de bugs (ex: fix/correcao-bug)\n` + + `- \`rc/*\`: Para release candidates (ex: rc/v1.2.0-rc1)\n\n` + + `### 🔧 Como corrigir:\n` + + `1. Renomeie o branch para seguir um dos padrões acima\n` + + `2. Ou crie um novo branch com o nome correto\n`; + + const prNumber = context.issue.number; + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: errorMessage + }); + + core.setFailed(`Invalid branch name: ${branchName}. Must start with release/, feature/, fix/, or rc/`); + return; + } + + // Obter a última tag de release + console.log('Fetching latest release tag...'); + const { data: releases } = await github.rest.repos.listReleases({ + owner: context.repo.owner, + repo: context.repo.repo, + per_page: 1 + }); + + let lastReleaseVersion = '0.0.0'; + if (releases.length > 0) { + lastReleaseVersion = releases[0].tag_name.replace(/^v/, ''); + console.log(`Latest release version: ${lastReleaseVersion}`); + } else { + console.log('No releases found, using 0.0.0 as baseline'); + } + + // Calcular a nova versão baseada no branch + const newVersion = calculateVersion(lastReleaseVersion, branchName); + console.log(`Calculated version: ${newVersion}`); + + // Exportar a versão como output + core.setOutput('version', newVersion); + + // Adicionar comentário informativo no PR + const prNumber = context.issue.number; + const infoMessage = `## ✅ Versão Calculada Automaticamente\n\n` + + `**Branch:** \`${branchName}\`\n` + + `**Última release:** \`${lastReleaseVersion}\`\n` + + `**Nova versão:** \`${newVersion}\`\n\n` + + `### 📝 Regras Aplicadas:\n` + + `- \`release/*\`: Aumenta major, zera minor e patch (ex: 2.0.0)\n` + + `- \`feature/*\`: Mantém major, aumenta minor, zera patch (ex: 1.2.0)\n` + + `- \`fix/*\`: Mantém major e minor, aumenta patch (ex: 1.1.3)\n` + + `- \`rc/*\`: Mantém versão base, aumenta RC (ex: 1.1.2-rc2)\n`; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: infoMessage + }); + + } catch (error) { + console.error('Error during version calculation:', error); + + const prNumber = context.issue.number; + const errorMessage = `## 🚨 Erro no Cálculo de Versão\n\n` + + `Ocorreu um erro durante o cálculo da versão:\n\n\`\`\`\n${error.message}\n\`\`\`\n\n` + + `Por favor, verifique se o nome do branch está correto e tente novamente.`; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: errorMessage + }); + + core.setFailed(`Version calculation error: ${error.message}`); + } + - name: Generate App Token id: generate-app-token uses: actions/create-github-app-token@v1 @@ -65,10 +197,13 @@ jobs: - name: 🧪 Run Tests with Pytest run: | - pytest tests --junitxml=pytest.xml --cov=laborious --cov-report=xml --cov-report=term + pytest tests --junitxml=pytest.xml --cov=model-manager --cov-report=xml --cov-report=term - name: Run SonarQube Analysis uses: SonarSource/sonarqube-scan-action@v5 env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} + with: + args: > + -Dsonar.projectVersion=${{ steps.calculate-version.outputs.version || '0.0.0' }} diff --git a/sonar-project.properties b/sonar-project.properties index b332c70..0edb732 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,9 +1,7 @@ -sonar.projectKey=Aignosi_sientia-dataops-laborious_temporal_beaec423-6c42-4f26-8134-b676287b499d -sonar.projectName=sientia-dataops-laborious_temporal -sonar.sources=laborious +sonar.projectKey=Aignosi_sientia-dataops-model-manager_dc6e051c-995a-4b57-9cde-f511018184c7 +sonar.projectName=sientia-dataops-model-manager +sonar.sources=model-manager sonar.tests=tests -sonar.projectVersion=1.0.0 -sonar.coverage.exclusions=laborious/worker/worker.py sonar.qualitygate.wait=true sonar.qualitygate.timeout=300 sonar.python.coverage.reportPaths=coverage.xml