diff --git a/.github/workflows/_cypress.yml b/.github/workflows/_cypress.yml new file mode 100644 index 0000000..1b0e7da --- /dev/null +++ b/.github/workflows/_cypress.yml @@ -0,0 +1,49 @@ +name: End-to-end Tests + +on: + workflow_call: + inputs: + pattern: + type: string + required: true + name: + type: string + required: true + +jobs: + e2e: + name: "End-to-end - ${{ inputs.name }} (${{ matrix.browser }})" + runs-on: ubuntu-20.04 + container: + image: gmmcal/gmmcal:cypress + env: + CYPRESS_BASE_URL: http://web:3000 + CYPRESS_SPEC_PATTERN: ${{ inputs.pattern }} + + strategy: + matrix: + browser: [chrome, firefox] + + services: + postgres: + image: postgres:16 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: gmmcalcombr_test + ports: + - 5432:5432 + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + + web: + image: gmmcal/gmmcal:test + env: + DATABASE_URL: postgres://postgres:postgres@postgres:5432/gmmcalcombr_test + ON_CYPRESS: true + ports: + - 3000:3000 + + steps: + - name: Run tests on ${{ matrix.browser }} + run: cypress run --browser ${{ matrix.browser }} + working-directory: /rails diff --git a/.github/workflows/_deploy.yml b/.github/workflows/_deploy.yml new file mode 100644 index 0000000..1122526 --- /dev/null +++ b/.github/workflows/_deploy.yml @@ -0,0 +1,34 @@ +name: Deploy application + +on: + workflow_call: + inputs: + name: + type: string + required: true + environment: + type: string + required: true + url: + type: string + required: true + params: + type: string + required: false + default: "" + +jobs: + deploy: + name: ${{ inputs.name }} + runs-on: ubuntu-20.04 + environment: + name: ${{ inputs.environment }} + url: ${{ inputs.url }} + + steps: + - name: Deploy + env: + DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }} + DEPLOY_SERVICE: ${{ secrets.DEPLOY_SERVICE }} + run: | + curl "https://api.render.com/deploy/srv-$DEPLOY_SERVICE?key=$DEPLOY_KEY&${{ inputs.params }}" diff --git a/.github/workflows/_docker.yml b/.github/workflows/_docker.yml new file mode 100644 index 0000000..bf0b35b --- /dev/null +++ b/.github/workflows/_docker.yml @@ -0,0 +1,53 @@ +name: Build + +on: + workflow_call: + inputs: + name: + type: string + required: true + tag-name: + type: string + required: false + default: "gmmcal/gmmcal:test" + target: + type: string + required: false + default: test + reference: + type: string + required: false + publish: + type: boolean + required: false + default: true + +jobs: + build: + name: ${{ inputs.name }} + runs-on: ubuntu-20.04 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ inputs.reference }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build image + uses: docker/build-push-action@v5 + with: + push: ${{ inputs.publish }} + context: . + target: ${{ inputs.target }} + tags: ${{ inputs.tag-name }} + cache-from: type=registry,ref=gmmcal/gmmcal:buildcache${{ inputs.target }} + cache-to: type=registry,ref=gmmcal/gmmcal:buildcache${{ inputs.target }},mode=max diff --git a/.github/workflows/_lint.yml b/.github/workflows/_lint.yml new file mode 100644 index 0000000..bec5355 --- /dev/null +++ b/.github/workflows/_lint.yml @@ -0,0 +1,28 @@ +name: Lint + +on: + workflow_call: + inputs: + name: + type: string + required: true + command: + type: string + required: true + image: + type: string + required: false + default: gmmcal/gmmcal:test + +jobs: + lint: + name: ${{ inputs.name }} + runs-on: ubuntu-20.04 + container: + image: ${{ inputs.image }} + options: "--user=root:root" + + steps: + - name: Execute ${{ inputs.command }} + run: ${{ inputs.command }} + working-directory: /rails diff --git a/.github/workflows/_preview.yml b/.github/workflows/_preview.yml new file mode 100644 index 0000000..d8f4f06 --- /dev/null +++ b/.github/workflows/_preview.yml @@ -0,0 +1,22 @@ +name: Deploy preview image + +on: + workflow_call: + inputs: + tag-name: + type: string + required: true + +jobs: + deploy: + name: Deploy + runs-on: ubuntu-latest + environment: + name: preview + url: ${{ steps.result.outputs.url }} + steps: + - name: Create Render service preview + id: result + run: | + curl -X POST https://api.render.com/v1/services/srv-${{ secrets.DEPLOY_SERVICE }}/preview -H 'Authorization: Bearer ${{ secrets.RENDER_API_KEY }}' -H 'Accept: application/json' -d '{"imagePath": "docker.io/${{ inputs.tag-name }}", "name": "gustavocunha-preview-pr-${{ github.event.number }}-${{ github.run_number }}"}' > result.json + echo "url=$(jq -r '.service.serviceDetails.url' result.json)" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/_release.yml b/.github/workflows/_release.yml new file mode 100644 index 0000000..77a397d --- /dev/null +++ b/.github/workflows/_release.yml @@ -0,0 +1,24 @@ +name: Release + +on: + workflow_call: + inputs: + tag: + type: string + required: true + +jobs: + release: + name: Create release page + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Create release + uses: ncipollo/release-action@v1 + with: + generateReleaseNotes: true + tag: ${{ inputs.tag }} diff --git a/.github/workflows/_tag.yml b/.github/workflows/_tag.yml new file mode 100644 index 0000000..dcaaa17 --- /dev/null +++ b/.github/workflows/_tag.yml @@ -0,0 +1,27 @@ +name: Tag application + +on: + workflow_call: + outputs: + version: + description: Prefix of image name + value: ${{ jobs.tag.outputs.version }} + +jobs: + tag: + name: Determine tag number + runs-on: ubuntu-latest + outputs: + version: ${{ steps.semver.outputs.next }} + + steps: + - name: Get Next Version + id: semver + uses: ietf-tools/semver-action@v1 + with: + token: ${{ github.token }} + noVersionBumpBehavior: patch + branch: main + majorList: "BREAK" + minorList: "NEW" + patchList: "FIX,OPT" diff --git a/.github/workflows/_tests.yml b/.github/workflows/_tests.yml new file mode 100644 index 0000000..c52c811 --- /dev/null +++ b/.github/workflows/_tests.yml @@ -0,0 +1,38 @@ +name: Backend Tests + +on: + workflow_call: + inputs: + command: + type: string + required: true + +jobs: + tests: + name: Backend + runs-on: ubuntu-20.04 + container: + image: gmmcal/gmmcal:test + env: + DATABASE_URL: postgres://postgres:postgres@postgres:5432/gmmcalcombr_test + DATABASE_CLEANER_ALLOW_REMOTE_DATABASE_URL: true + + services: + postgres: + image: postgres:16 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: gmmcalcombr_test + ports: + - 5432:5432 + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + + steps: + - name: Migrate database + run: bundle exec rails db:migrate + working-directory: /rails + + - name: Execute tests + run: ${{ inputs.command }} + working-directory: /rails diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..39c38fb --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,53 @@ +name: Tag Release + +on: + push: + branches: + - main + +jobs: + tag: + runs-on: ubuntu-20.04 + permissions: + contents: write + + steps: + - name: Get Next Version + id: semver + uses: ietf-tools/semver-action@v1 + with: + token: ${{ github.token }} + branch: main + majorList: "BREAK" + minorList: "NEW" + patchList: "FIX,OPT" + + - name: 🏷️ Create tag ${{ steps.semver.outputs.next }} + uses: actions/github-script@v7 + with: + script: | + github.rest.git.createRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: 'refs/tags/${{ steps.semver.outputs.next }}', + sha: context.sha + }) + + - name: 🏷️ Create/update tag ${{ steps.semver.outputs.nextMajor }} + uses: actions/github-script@v7 + with: + script: | + github.rest.git.createRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: 'tags/${{ steps.semver.outputs.nextMajor }}', + sha: context.payload.after + }).catch(err => { + if (err.status !== 422) throw err; + github.rest.git.updateRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: 'tags/${{ steps.semver.outputs.nextMajor }}', + sha: context.payload.after + }); + })