From 634629ea3cf4b2813dfa4f665331747117fe954d Mon Sep 17 00:00:00 2001 From: Guido de Jong <35309288+guidojw@users.noreply.github.com> Date: Fri, 11 Mar 2022 23:41:09 +0100 Subject: [PATCH] feat: GitHub Actions (#277) * feat: add workflow configurations * fix(ci): correctly set network * fix(ci): remove pseudo-tty flags from docker run * fix(ci): specify POSTGRES_HOST * chore(ci): remove unnecessary env variable setting * feat: add workflow configurations * fix(ci): correctly set network * fix(ci): remove pseudo-tty flags from docker run * fix(ci): specify POSTGRES_HOST * chore(ci): remove unnecessary env variable setting * fix(ci): try setting timezone * fix(ci): set PGTZ env variable too * fix(ci): remove timezone stuff and improve user_cleanup_job_spec * fix(jobs): change end_date to correct number * feat: problem matchers * chore: change documentation * refactor(ci): try building without RAILS_MASTER_KEY * fix(ci): default camo_key to empty string * fix(ci): readd RAILS_MASTER_KEY stuff * test(ci): test problem matchers * fix(problemmatchers): rspec regex * fix(problemmatchers): escape dot correctly * fix(problemmatchers): remove escaped backslash * chore: remove unused build-args setting and add -t to docker run * fix(ci): add db container to lint step too * chore(ci): remove -t from docker run * refactor: update all action tags to exclude prefix * fix: image repository * chore: remove unnecessary step id * fix: set Sentry release * fix: lint error in Sentry initializer * fix: use whitespace character in regex * fix: also change sidekiq image url Co-authored-by: Wilco --- .buildkite/pipeline.yml | 66 ------ .buildkite/release.sh | 9 - .buildkite/sentry.sh | 9 - .buildkite/slack.sh | 8 - .github/problem-matchers/rspec.json | 16 ++ .github/problem-matchers/rubocop.json | 32 +++ .github/workflows/cleanup-registry.yml | 24 +++ .github/workflows/continuous-delivery.yml | 216 +++++++++++++++++++ .github/workflows/continuous-integration.yml | 104 +++++++++ .github/workflows/publish-image.yml | 115 ++++++++++ DEPLOY.md | 7 +- Dockerfile | 2 + README.md | 7 +- config/deploy.rb | 2 +- config/initializers/sentry.rb | 1 + docker-compose.buildkite.yml | 25 --- docker-compose.yml | 4 +- 17 files changed, 523 insertions(+), 124 deletions(-) delete mode 100644 .buildkite/pipeline.yml delete mode 100644 .buildkite/release.sh delete mode 100644 .buildkite/sentry.sh delete mode 100644 .buildkite/slack.sh create mode 100644 .github/problem-matchers/rspec.json create mode 100644 .github/problem-matchers/rubocop.json create mode 100644 .github/workflows/cleanup-registry.yml create mode 100644 .github/workflows/continuous-delivery.yml create mode 100644 .github/workflows/continuous-integration.yml create mode 100644 .github/workflows/publish-image.yml delete mode 100644 docker-compose.buildkite.yml diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml deleted file mode 100644 index ae671fec..00000000 --- a/.buildkite/pipeline.yml +++ /dev/null @@ -1,66 +0,0 @@ -steps: - - label: ":docker: Build test image" - plugins: - - docker-compose#v2.6.0: - build: app - config: docker-compose.buildkite.yml - - - wait - - - label: ":rspec: Rspec" - command: "bin/wait_for -t 30 db:5432 -- bin/ci.sh spec" - plugins: - - docker-compose#v2.6.0: - run: app - config: docker-compose.buildkite.yml - - - label: ":rubocop: Lint" - command: "bin/ci.sh lint" - plugins: - - docker-compose#v2.6.0: - run: app - config: docker-compose.buildkite.yml - - - wait - - - label: ":docker: Build+Push `:staging` image" - branches: "staging" - plugins: - - docker-login#v2.0.1: - server: docker.csvalpha.nl - username: buildkite - password-env: DOCKER_PASSWORD - - docker-compose#v2.6.0: - push: app-production:docker.csvalpha.nl/amber-api:staging - image-name: docker.csvalpha.nl/amber-api:staging - config: docker-compose.buildkite.yml - - - label: ":docker: Build+Push `:production` image" - branches: "master" - plugins: - - docker-login#v2.0.1: - server: docker.csvalpha.nl - username: buildkite - password-env: DOCKER_PASSWORD - - docker-compose#v2.6.0: - push: app-production:docker.csvalpha.nl/amber-api:latest - image-name: docker.csvalpha.nl/amber-api:latest - config: docker-compose.buildkite.yml - - - block: "Deploy this stage" - branches: "master staging" - - - label: 'Restarting service' - command: 'bash .buildkite/release.sh' - branches: "master staging" - - - wait - - - label: 'Inform Sentry' - command: 'bash .buildkite/sentry.sh' - branches: "master staging" - - - label: 'Inform Slack' - command: 'bash .buildkite/slack.sh' - branches: "master staging" - diff --git a/.buildkite/release.sh b/.buildkite/release.sh deleted file mode 100644 index 30b7426a..00000000 --- a/.buildkite/release.sh +++ /dev/null @@ -1,9 +0,0 @@ -STAGE=$BUILDKITE_BRANCH -if [ "$STAGE" = "master" ]; then STAGE='production'; fi -if [ "$STAGE" = "production" ] || [ "$STAGE" = "staging" ]; then echo 'Deploying for stage' $STAGE; else echo 'Stage' $STAGE 'unknown.. skipping deploy'; exit 0; fi - -cd /opt/docker/amber-api/$STAGE -docker-compose pull web -docker-compose build web sidekiq -docker-compose run --rm web rails db:migrate -docker-compose up -d web sidekiq diff --git a/.buildkite/sentry.sh b/.buildkite/sentry.sh deleted file mode 100644 index 18604692..00000000 --- a/.buildkite/sentry.sh +++ /dev/null @@ -1,9 +0,0 @@ -STAGE=$BUILDKITE_BRANCH -if [ "$STAGE" = "master" ]; then STAGE='production'; fi -if [ "$STAGE" = "production" ] || [ "$STAGE" = "staging" ]; then echo 'Deploying for stage' $STAGE; else echo 'Stage' $STAGE 'unknown.. skipping deploy'; exit 0; fi - -curl -sSf -H 'Content-Type: application/json' \ - -H 'Authorization: Bearer '$SENTRY_API_TOKEN \ - --request POST \ - --data '{"version": "'"$(date)"'", "ref": "'"$BUILDKITE_COMMIT"'", "environment": "'"$STAGE"'"}' \ - https://sentry.io/api/0/projects/csvalpha/amber-api/releases/ diff --git a/.buildkite/slack.sh b/.buildkite/slack.sh deleted file mode 100644 index 8e680d92..00000000 --- a/.buildkite/slack.sh +++ /dev/null @@ -1,8 +0,0 @@ -STAGE=$BUILDKITE_BRANCH -if [ "$STAGE" = "master" ]; then STAGE='production'; fi -if [ "$STAGE" = "production" ] || [ "$STAGE" = "staging" ]; then echo 'Deploying for stage' $STAGE; else echo 'Stage' $STAGE 'unknown.. skipping deploy'; exit 0; fi - -curl -sSf --request POST \ - -H 'Content-type: application/json' \ - --data '{"username": "Buildkite deploy", "text": "Deploy for amber-api '$STAGE' is finished"}' \ - $SLACK_URL diff --git a/.github/problem-matchers/rspec.json b/.github/problem-matchers/rspec.json new file mode 100644 index 00000000..38931566 --- /dev/null +++ b/.github/problem-matchers/rspec.json @@ -0,0 +1,16 @@ +{ + "problemMatcher": [ + { + "owner": "rspec", + "severity": "error", + "pattern": [ + { + "regexp": "^rspec\\s\\.\/(.*):(.*)\\s#\\s(.*)$", + "file": 1, + "line": 2, + "message": 3 + } + ] + } + ] +} diff --git a/.github/problem-matchers/rubocop.json b/.github/problem-matchers/rubocop.json new file mode 100644 index 00000000..db2bfa82 --- /dev/null +++ b/.github/problem-matchers/rubocop.json @@ -0,0 +1,32 @@ +{ + "problemMatcher": [ + { + "owner": "rubocop-error", + "severity": "error", + "pattern": [ + { + "regexp": "^(.+):(\\d+):(\\d+):\\sC:\\s((.+):\\s.+)$", + "file": 1, + "line": 2, + "column": 3, + "message": 4, + "code": 5 + } + ] + }, + { + "owner": "rubocop-warning", + "severity": "warning", + "pattern": [ + { + "regexp": "^(.+):(\\d+):(\\d+):\\sW:\\s((.+):\\s.+)$", + "file": 1, + "line": 2, + "column": 3, + "message": 4, + "code": 5 + } + ] + } + ] +} diff --git a/.github/workflows/cleanup-registry.yml b/.github/workflows/cleanup-registry.yml new file mode 100644 index 00000000..2764b72b --- /dev/null +++ b/.github/workflows/cleanup-registry.yml @@ -0,0 +1,24 @@ +name: Cleanup Registry + +on: + schedule: + - cron: '0 0 * * 1' # https://crontab.guru/#0_0_*_*_1 + workflow_dispatch: + +env: + IMAGE_NAMES: amber-api + +jobs: + cleanup: + name: Cleanup + runs-on: ubuntu-latest + steps: + - name: Delete old versions + uses: snok/container-retention-policy@81ba73785bb8207a451a0de928aa6a3c57d6fd77 # tag=v1.4.0 + with: + image-names: ${{ env.IMAGE_NAMES }} + cut-off: 2 days ago UTC + account-type: org + org-name: ${{ github.repository_owner }} + skip-tags: latest,staging + token: ${{ secrets.PAT }} diff --git a/.github/workflows/continuous-delivery.yml b/.github/workflows/continuous-delivery.yml new file mode 100644 index 00000000..4ae84b7f --- /dev/null +++ b/.github/workflows/continuous-delivery.yml @@ -0,0 +1,216 @@ +name: Continuous Delivery + +on: + workflow_dispatch: + inputs: + merge: + description: Merge staging into master first? (y/N) + required: false + default: 'n' + +concurrency: + group: cd-${{ github.ref_name }} + +env: + PROJECT_NAME: amber-api + SENTRY_ORG: csvalpha + APP_ID: 152333 + +jobs: + branch_check: + name: Branch Check + runs-on: ubuntu-latest + steps: + - name: Validate branch + run: | + if [ $GITHUB_REF_NAME != 'staging' ] && [ $GITHUB_REF_NAME != 'master' ]; then + echo 'This workflow can only be run on branches staging and master.' + exit 1 + fi + + metadata: + name: Metadata + runs-on: ubuntu-latest + needs: branch_check + outputs: + has_diff: ${{ steps.get_metadata.outputs.has_diff }} + stage: ${{ steps.get_metadata.outputs.stage }} + steps: + - name: Checkout code + uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # tag=v2.4.0 + + - name: Get metadata + id: get_metadata + env: + INPUT_MERGE: ${{ github.event.inputs.merge }} + run: | + if [ $GITHUB_REF_NAME = 'master' ]; then + if [ "${INPUT_MERGE,,}" = 'y' ]; then + git fetch origin staging + if ! git diff origin/master origin/staging --exit-code; then + echo '::set-output name=has_diff::true' + else + echo '::set-output name=has_diff::false' + fi + fi + + echo '::set-output name=stage::production' + else + echo '::set-output name=stage::staging' + fi + + merge: + name: Merge + runs-on: ubuntu-latest + needs: metadata + if: github.event.inputs.merge == 'y' + outputs: + sha: ${{ steps.get_sha.outputs.sha }} + steps: + - name: Validate inputs + env: + HAS_DIFF: ${{ fromJSON(needs.metadata.outputs.has_diff || false) }} + run: | + if [ $GITHUB_REF_NAME != 'master' ]; then + echo 'Can only merge when the workflow target branch is master.' + exit 1 + fi + + if ! $HAS_DIFF; then + echo 'There is no diff so a merge is not necessary, skipping next steps.' + fi + + - name: Checkout code + if: fromJSON(needs.metadata.outputs.has_diff) + uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # tag=v2.4.0 + + - name: Run merge + if: fromJSON(needs.metadata.outputs.has_diff) + uses: devmasx/merge-branch@854d3ac71ed1e9deb668e0074781b81fdd6e771f # tag=v1.4.0 + with: + type: now + from_branch: staging + target_branch: master + github_token: ${{ github.token }} + + - name: Get merge commit SHA + id: get_sha + if: fromJSON(needs.metadata.outputs.has_diff) + run: | + git fetch origin master + echo '::set-output name=sha::'$(git rev-parse origin/master) + + continuous_integration: + name: Continuous Integration + needs: [metadata, merge] + if: fromJSON(needs.metadata.outputs.has_diff) + uses: csvalpha/amber-api/.github/workflows/continuous-integration.yml@staging + with: + sha: ${{ needs.merge.outputs.sha }} + secrets: + rails_master_key: ${{ secrets.RAILS_MASTER_KEY }} + + publish_image: + name: Publish Image + needs: [metadata, merge] + if: fromJSON(needs.metadata.outputs.has_diff) + uses: csvalpha/amber-api/.github/workflows/publish-image.yml@staging + with: + sha: ${{ needs.merge.outputs.sha }} + secrets: + sentry_auth_token: ${{ secrets.SENTRY_AUTH_TOKEN }} + + deploy: + name: Deploy + runs-on: ubuntu-latest + needs: [metadata, merge, continuous_integration, publish_image] + if: | + (github.ref_name == 'staging' || github.ref_name == 'master') && ((github.ref_name == 'master' && + github.event.inputs.merge == 'y' && fromJSON(needs.metadata.outputs.has_diff) && success()) || + ((github.event.inputs.merge != 'y' || !fromJSON(needs.metadata.outputs.has_diff)) && !cancelled())) + steps: + - name: Get environment URL + id: get_url + run: | + if [ $GITHUB_REF_NAME = 'master' ]; then + echo '::set-output name=environment_url::https://csvalpha.nl/api' + else + echo '::set-output name=environment_url::https://staging.csvalpha.nl/api' + fi + + - name: Checkout code + uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # tag=v2.4.0 + with: + ref: ${{ needs.merge.outputs.sha }} + + - name: Start deployment + uses: bobheadxi/deployments@f235d02c2daaaa84c710d013c7d39f7f0f8bf298 # tag=v0.6.2 + id: start_deployment + with: + step: start + token: ${{ secrets.GITHUB_TOKEN }} + env: ${{ needs.metadata.outputs.stage }} + + - name: Deploy + uses: appleboy/ssh-action@1d1b21ca96111b1eb4c03c21c14ebb971d2200f6 # tag=v0.1.4 + env: + STAGE: ${{ needs.metadata.outputs.stage }} + with: + host: csvalpha.nl + username: github-actions + key: ${{ secrets.SSH_PRIVATE_KEY }} + envs: PROJECT_NAME,STAGE + script: | + cd /opt/docker/$PROJECT_NAME/$STAGE + docker-compose pull + docker-compose run --rm web rails db:migrate + docker-compose up -d + + - name: Finalize Sentry release + uses: getsentry/action-release@744e4b262278339b79fb39c8922efcae71e98e39 # tag=v1.1.6 + env: + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_PROJECT: ${{ env.PROJECT_NAME }} + with: + environment: ${{ needs.metadata.outputs.stage }} + version: ${{ needs.merge.outputs.sha }} + set_commits: skip + + - name: Finish deployment + uses: bobheadxi/deployments@f235d02c2daaaa84c710d013c7d39f7f0f8bf298 # tag=v0.6.2 + if: steps.start_deployment.conclusion == 'success' && always() + with: + step: finish + token: ${{ secrets.GITHUB_TOKEN }} + status: ${{ job.status }} + deployment_id: ${{ steps.start_deployment.outputs.deployment_id }} + env_url: ${{ steps.get_url.outputs.environment_url }} + + update_check_run: + name: Update Check Run + runs-on: ubuntu-latest + needs: [branch_check, metadata, merge, continuous_integration, publish_image, deploy] + if: (github.ref_name == 'staging' || github.ref_name == 'master') && always() + steps: + - name: Get conclusion + id: get_conclusion + env: + RESULTS: ${{ join(needs.*.result, ' ') }} + run: | + echo '::set-output name=conclusion::success' + for RESULT in $RESULTS; do + if [ $RESULT = 'cancelled' ] || [ $RESULT = 'failure' ]; then + echo '::set-output name=conclusion::'$RESULT + break + fi + done + + - name: Update Continuous Delivery check run + uses: guidojw/actions/update-check-run@2b1dea8cbd9e44491c269e771b75636026caf8ca # tag=v1.1.0 + with: + app_id: ${{ env.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + sha: ${{ needs.merge.outputs.sha }} + name: Continuous Delivery + conclusion: ${{ steps.get_conclusion.outputs.conclusion }} + details_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml new file mode 100644 index 00000000..c292ae82 --- /dev/null +++ b/.github/workflows/continuous-integration.yml @@ -0,0 +1,104 @@ +name: Continuous Integration + +on: + push: + branches: [staging, master] + pull_request: + workflow_call: + inputs: + sha: + required: false + type: string + secrets: + rails_master_key: + required: true + +jobs: + build: + name: Build + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # tag=v2.4.0 + with: + ref: ${{ inputs.sha }} + + - name: Build test image + uses: guidojw/actions/build-docker-image@2b1dea8cbd9e44491c269e771b75636026caf8ca # tag=v1.1.0 + with: + file: Dockerfile + build-args: | + BUNDLE_INSTALL_EXCLUDE=development + name: app + + lint: + name: Lint + runs-on: ubuntu-latest + needs: build + services: + db: + image: postgres:11.2 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 5432:5432 + steps: + - name: Checkout code + uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # tag=v2.4.0 + with: + ref: ${{ inputs.sha }} + + - name: Add problem matchers + run: | + echo '::add-matcher::.github/problem-matchers/rubocop.json' + + - name: Load test image + uses: guidojw/actions/load-docker-image@2b1dea8cbd9e44491c269e771b75636026caf8ca # tag=v1.1.0 + with: + name: app + + - name: Lint + env: + RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }} + run: | + docker run -e POSTGRES_USER=postgres -e POSTGRES_HOST=localhost -e RAILS_MASTER_KEY --network=host app \ + bin/ci.sh lint + + test: + name: Test + runs-on: ubuntu-latest + needs: build + services: + db: + image: postgres:11.2 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 5432:5432 + steps: + - name: Checkout code + uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # tag=v2.4.0 + with: + ref: ${{ inputs.sha }} + + - name: Add problem matchers + run: | + echo '::add-matcher::.github/problem-matchers/rspec.json' + + - name: Load test image + uses: guidojw/actions/load-docker-image@2b1dea8cbd9e44491c269e771b75636026caf8ca # tag=v1.1.0 + with: + name: app + + - name: Test + env: + RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }} + run: | + docker run -e POSTGRES_USER=postgres -e POSTGRES_HOST=localhost -e RAILS_MASTER_KEY --network=host app \ + bin/ci.sh spec diff --git a/.github/workflows/publish-image.yml b/.github/workflows/publish-image.yml new file mode 100644 index 00000000..5c5d7685 --- /dev/null +++ b/.github/workflows/publish-image.yml @@ -0,0 +1,115 @@ +name: Publish Image + +on: + push: + branches: [staging, master] + workflow_call: + inputs: + sha: + required: false + type: string + secrets: + sentry_auth_token: + required: true + workflow_dispatch: + +env: + PROJECT_NAME: amber-api + REGISTRY_URL: ghcr.io + SENTRY_ORG: csvalpha + APP_ID: 152333 + +jobs: + metadata: + name: Metadata + runs-on: ubuntu-latest + outputs: + tag: ${{ steps.get_metadata.outputs.tag }} + build_args: ${{ steps.get_metadata.outputs.build_args }} + steps: + - name: Get metadata + id: get_metadata + env: + INPUT_SHA: ${{ inputs.sha }} + run: | + if [ $GITHUB_REF_NAME = 'master' ]; then + echo '::set-output name=tag::latest' + else + echo '::set-output name=tag::'$GITHUB_REF_NAME + fi + + if [ $GITHUB_REF_NAME = 'staging' ] || [ $GITHUB_REF_NAME = 'master' ]; then + BUILD_ARGS='BUILD_HASH='${INPUT_SHA:-$GITHUB_SHA} + echo '::set-output name=build_args::'$BUILD_ARGS + fi + + publish: + name: Publish + runs-on: ubuntu-latest + needs: metadata + steps: + - name: Checkout code + uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # tag=v2.4.0 + with: + ref: ${{ inputs.sha }} + fetch-depth: 0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@94ab11c41e45d028884a99163086648e898eed25 # tag=v1.6.0 + + - name: Login to GitHub Container Registry + uses: docker/login-action@42d299face0c5c43a0487c477f595ac9cf22f1a7 # tag=v1.13.0 + with: + registry: ${{ env.REGISTRY_URL }} + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push image + uses: docker/build-push-action@7f9d37fa544684fb73bfe4835ed7214c255ce02b # tag=v2.9.0 + with: + push: true + context: . + build-args: ${{ needs.metadata.outputs.build_args }} + cache-from: type=gha,scope=main + cache-to: type=gha,scope=main + tags: | + ${{ env.REGISTRY_URL }}/${{ github.repository_owner }}/${{ env.PROJECT_NAME }}:${{ + needs.metadata.outputs.tag }} + + - name: Create Sentry release + if: ${{ !(github.event_name == 'workflow_dispatch' && github.workflow == 'Publish Image') }} + uses: getsentry/action-release@744e4b262278339b79fb39c8922efcae71e98e39 # tag=v1.1.6 + env: + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_PROJECT: ${{ env.PROJECT_NAME }} + with: + finalize: false + version: ${{ inputs.sha }} + + update_check_run: + name: Update Check Run + runs-on: ubuntu-latest + needs: [metadata, publish] + if: github.event_name == 'workflow_dispatch' && github.workflow == 'Publish Image' && always() + steps: + - name: Get conclusion + id: get_conclusion + env: + RESULTS: ${{ join(needs.*.result, ' ') }} + run: | + echo '::set-output name=conclusion::success' + for RESULT in $RESULTS; do + if [ $RESULT = 'cancelled' ] || [ $RESULT = 'failure' ]; then + echo '::set-output name=conclusion::'$RESULT + break + fi + done + + - name: Update Publish Image check run + uses: guidojw/actions/update-check-run@2b1dea8cbd9e44491c269e771b75636026caf8ca # tag=v1.1.0 + with: + app_id: ${{ env.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + name: Publish Image + conclusion: ${{ steps.get_conclusion.outputs.conclusion }} + details_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} diff --git a/DEPLOY.md b/DEPLOY.md index 72c910ff..690af81a 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -1,5 +1,10 @@ ## Deploying -Deploying is done via buildkite. To deploy, push branch `master` or `staging` to Github and click in Buildkite on the 'Deploy this step' button to finish deploying. +Deployments are done using GitHub Actions. To deploy a branch, follow the following steps: + +* Go to the Continuous Delivery [workflow page](https://github.com/csvalpha/amber-api/actions/workflows/continuous-delivery.yml). +* Open the "Run workflow" modal. +* Choose a branch and if you want to merge the changes on the staging branch into the master branch (only possible when the branch chosen in previous step is master). +* Click the green button "Run workflow". We use a continuous development cycle. That means: branch `master` is always in production. When a feature is merged through a PR to `staging`, merge its changes to `master` and deploy as soon as possible. diff --git a/Dockerfile b/Dockerfile index d62c9094..4b7cb28b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,7 @@ FROM ruby:3.0.3-alpine +ARG BUILD_HASH='unknown' +ENV BUILD_HASH=$BUILD_HASH ARG BUNDLE_INSTALL_EXCLUDE='development test' EXPOSE 3000 diff --git a/README.md b/README.md index 60ea69c5..c9aa69e7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ Alpha AMBER API ================ -[![Build status](https://badge.buildkite.com/7bb7573780e61f69cb8d834590a0c2125ed5a5ee588fb5380e.svg)](https://buildkite.com/csv-alpha/amber-api) +[![Continuous Integration](https://github.com/csvalpha/amber-api/actions/workflows/continuous-integration.yml/badge.svg)](https://github.com/csvalpha/amber-api/actions/workflows/continuous-integration.yml) +[![Continuous Delivery](https://github.com/csvalpha/amber-api/actions/workflows/continuous-delivery.yml/badge.svg)](https://github.com/csvalpha/amber-api/actions/workflows/continuous-delivery.yml) [![Depfu](https://badges.depfu.com/badges/663adb8e75ff19a32ca0d866d5fe2e85/count.svg)](https://depfu.com/github/csvalpha/amber-api?project_id=7749) ## Prerequisites @@ -94,8 +95,8 @@ To run RuboCop, execute: bundle exec rubocop -## Buildkite (automated testing) -Buildkite is a test service which automatically tests the application after a commit has been pushed. Buildkite will run RuboCop and RSpec (see `.buildkite/pipeline.yml`) and will fail if one of these fails. +## GitHub Actions (automated testing) +GitHub Actions is a CI/CD service which automatically tests the application after a commit has been pushed. GitHub Actions will run RuboCop and RSpec (see `.github/workflows/continuous-integration.yml`) and will fail if one of these fails. ## Deploying See [DEPLOY.md](https://github.com/csvalpha/amber-api/blob/master/DEPLOY.md) for that. diff --git a/config/deploy.rb b/config/deploy.rb index e28ea243..ae15c4b6 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -1,4 +1,4 @@ -# Deploy is done via buildkite, see .buildkite directory +# Deploy is done via GitHub Actions, see .github directory # This file is for mina to be able to connect to the rails console on the server require 'mina/rails' diff --git a/config/initializers/sentry.rb b/config/initializers/sentry.rb index d51f9d0d..3d962ea4 100644 --- a/config/initializers/sentry.rb +++ b/config/initializers/sentry.rb @@ -1,6 +1,7 @@ Raven.configure do |config| config.dsn = Rails.application.config.x.sentry_dsn config.environments = %w[production staging] + config.release = ENV['BUILD_HASH'] config.sanitize_fields = Rails.application.config.filter_parameters.map(&:to_s) config.async = lambda { |event| diff --git a/docker-compose.buildkite.yml b/docker-compose.buildkite.yml deleted file mode 100644 index f957b8b4..00000000 --- a/docker-compose.buildkite.yml +++ /dev/null @@ -1,25 +0,0 @@ -version: '3' - -services: - db: - image: postgres:11.2 - app: - build: - context: . - dockerfile: Dockerfile - args: - - BUNDLE_INSTALL_EXCLUDE='development' - depends_on: - - db - environment: - - RAILS_ENV=test - - POSTGRES_USER=postgres - - POSTGRES_HOST=db - - RAILS_MASTER_KEY - - app-production: - build: - context: . - dockerfile: Dockerfile - args: - - RAILS_MASTER_KEY diff --git a/docker-compose.yml b/docker-compose.yml index eb7533d9..fdae258a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,7 +14,7 @@ services: - redis_data:/var/lib/redis/data sidekiq: env_file: .env - image: docker.csvalpha.nl/amber-api:latest + image: ghcr.io/csvalpha/amber-api:latest command: sidekiq -C config/sidekiq.yml depends_on: - db @@ -25,7 +25,7 @@ services: - POSTGRES_HOST=db web: env_file: .env - image: docker.csvalpha.nl/amber-api:latest + image: ghcr.io/csvalpha/amber-api:latest depends_on: - db - redis