diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..345f7ad --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,49 @@ +name: CI + +on: + push: + branches: + - main + pull_request: + branches: + - main + workflow_dispatch: + +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + quality: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + + - name: Setup Node.js + uses: actions/setup-node@v5 + with: + node-version: 22 + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Generate Next.js types + run: pnpm exec next typegen + + - name: Typecheck + run: pnpm exec tsc --noEmit + + - name: Lint + run: pnpm run lint + + - name: Build application + run: pnpm run build diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml deleted file mode 100644 index ea5949a..0000000 --- a/.github/workflows/docker-publish.yml +++ /dev/null @@ -1,87 +0,0 @@ -name: Build and Push to Docker Hub - -on: - push: - branches: - - main - tags: - - 'v*.*.*' - pull_request: - branches: - - main - workflow_dispatch: - -env: - DOCKER_IMAGE_NAME: openmonetis - -jobs: - quality: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v5 - - - name: Setup pnpm - uses: pnpm/action-setup@v4 - - - name: Setup Node.js - uses: actions/setup-node@v5 - with: - node-version: 22 - cache: 'pnpm' - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Lint - run: pnpm run lint - - build-and-push: - runs-on: ubuntu-latest - needs: quality - permissions: - contents: read - packages: write - - steps: - - name: Checkout repository - uses: actions/checkout@v5 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to Docker Hub - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Extract metadata (tags, labels) - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ secrets.DOCKER_USERNAME }}/${{ env.DOCKER_IMAGE_NAME }} - tags: | - type=ref,event=branch - type=ref,event=pr - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=raw,value=latest,enable={{is_default_branch}} - type=sha,prefix={{branch}}- - - - name: Build and push Docker image - uses: docker/build-push-action@v5 - with: - context: . - file: ./Dockerfile - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max - platforms: linux/amd64,linux/arm64 - - - name: Image digest - run: echo ${{ steps.meta.outputs.digest }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8b289ba..f0151cd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,58 +2,151 @@ name: Release on: push: - branches: - - main + tags: + - "v*.*.*" + +concurrency: + group: release-${{ github.ref }} + cancel-in-progress: false + +env: + DOCKER_IMAGE_NAME: openmonetis + +permissions: + contents: read jobs: - release: + quality: runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Validate release version + shell: bash + run: | + TAG_VERSION="${GITHUB_REF_NAME#v}" + PACKAGE_VERSION="$(jq -r '.version' package.json)" + + if [[ ! "$TAG_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "A tag $GITHUB_REF_NAME não segue o formato vX.Y.Z." + exit 1 + fi + + if [[ "$TAG_VERSION" != "$PACKAGE_VERSION" ]]; then + echo "A tag $GITHUB_REF_NAME não corresponde à versão $PACKAGE_VERSION do package.json." + exit 1 + fi + + if ! grep -Fq "## [$TAG_VERSION]" CHANGELOG.md; then + echo "A versão $TAG_VERSION não foi encontrada no CHANGELOG.md." + exit 1 + fi + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + + - name: Setup Node.js + uses: actions/setup-node@v5 + with: + node-version: 22 + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Generate Next.js types + run: pnpm exec next typegen + + - name: Typecheck + run: pnpm exec tsc --noEmit + + - name: Lint + run: pnpm run lint + + docker: + runs-on: ubuntu-latest + needs: quality + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ secrets.DOCKER_USERNAME }}/${{ env.DOCKER_IMAGE_NAME }} + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=raw,value=latest + + - name: Build and push Docker image + id: build + uses: docker/build-push-action@v5 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + platforms: linux/amd64,linux/arm64 + + - name: Image digest + run: echo "${{ steps.build.outputs.digest }}" + + github-release: + runs-on: ubuntu-latest + needs: docker permissions: contents: write steps: - name: Checkout repository uses: actions/checkout@v5 - with: - fetch-depth: 0 - - - name: Read version from package.json - id: version - run: | - VERSION=$(jq -r '.version' package.json) - echo "value=$VERSION" >> $GITHUB_OUTPUT - echo "tag=v$VERSION" >> $GITHUB_OUTPUT - - - name: Check if tag already exists - id: tag_check - run: | - if git ls-remote --tags origin "refs/tags/v${{ steps.version.outputs.value }}" | grep -q .; then - echo "exists=true" >> $GITHUB_OUTPUT - else - echo "exists=false" >> $GITHUB_OUTPUT - fi - name: Extract changelog for this version - if: steps.tag_check.outputs.exists == 'false' id: changelog + shell: bash run: | - VERSION="${{ steps.version.outputs.value }}" - # Extrai o bloco entre ## [X.Y.Z] e o próximo ## [ - NOTES=$(awk "/^## \[$VERSION\]/{found=1; next} found && /^## \[/{exit} found{print}" CHANGELOG.md) - # Remove linhas em branco do início e fim - NOTES=$(echo "$NOTES" | sed '/./,$!d' | sed -e :a -e '/^\n*$/{$d;N;ba}') + VERSION="${GITHUB_REF_NAME#v}" + NOTES=$(awk -v version="$VERSION" ' + index($0, "## [" version "]") == 1 { found=1; next } + found && /^## \[/ { exit } + found && !started && /^[[:space:]]*$/ { next } + found { started=1; print } + ' CHANGELOG.md) + + if [[ -z "$NOTES" ]]; then + echo "Não foi possível extrair as notas da versão $VERSION." + exit 1 + fi + { echo "notes<> $GITHUB_OUTPUT + } >> "$GITHUB_OUTPUT" - - name: Create tag and GitHub Release - if: steps.tag_check.outputs.exists == 'false' + - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: - tag_name: ${{ steps.version.outputs.tag }} - name: ${{ steps.version.outputs.tag }} + tag_name: ${{ github.ref_name }} + name: ${{ github.ref_name }} body: ${{ steps.changelog.outputs.notes }} draft: false prerelease: false