Last active
October 9, 2022 21:49
-
-
Save copiousfreetime/4e41bd115b63bc928aa8e5f8daf26d1b to your computer and use it in GitHub Desktop.
Revisions
-
copiousfreetime revised this gist
Apr 28, 2022 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -44,10 +44,10 @@ upon `THING_KEY_REVIEW` or `THING_KEY_TEST` as appropriate. 1. Deal with the environment variables - possible approach above. 2. Create a `continuous_integration` job as a GitHub action and use the values that you did have in your `app.json` file for `environments.test.scripts.test-setup` and `environments.test.scripts.test` and make them individual steps in the workflow. 3. Turn on this workflow as appropriate for your GitHub events. In this workflow in the `continuous_integration` job is happening on every push to `main` and on every push to a branch that is part of a pull request. 4. Once this is in place, if you want to make the CI be required for branch merging, go to the Branch Protection rules of your repo and put this job in -
copiousfreetime created this gist
Apr 28, 2022 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,79 @@ # How to deal with missing Heroku CI/CD and Review Apps ## The reason for this - <https://status.heroku.com/incidents/2413> In particular the update from 2022-04-26 23:54:00 UTC > For the protection of our customers, we will not be reconnecting to GitHub > until we are certain that we can do so safely, **which may take some time > We recommend that customers use alternate methods rather than waiting for us > to restore this integration.** [emphasis mine]. ## Generate HEROKU_API_KEY You'll need to take a heroku use for your team/group/organization and make sure they have all the permissions needed. Then go to that [account page](https://dashboard.heroku.com/account), scrolldown to the bottom under the **API Key** section. Take that API Key and put it in GitHub secrets for your repository as `HEROKU_API_KEY`. This does mean that ALL of the items that happen in heroku as part of these workflows will appear to happen as the user that is associated with that api key. ## Setup GitHub Secrets/Environment variables In addition to the `HEROKU_API_KEY` above, you'll need to replicate any and all "secret" items that were in your Heroku config vars for your Test and Review environments to either GitHub secrets, or hardcode them into the workflows below. This example uses a combination of both. If you did have the same environment variable in both Heroku Test and Heroku Review, but with different values, you'll have to take that into account when you do the GitHub secrets. I'd probably recomented doing something like `THING_KEY_TEST` and then `THING_KEY_REVIEW` as GitHub secrets. And then in your workflows in the appropriate sections for CI or deploy use the `env:` section to setup the appropriate environment varable of `THING_KEY` baed upon `THING_KEY_REVIEW` or `THING_KEY_TEST` as appropriate. ## General Migration steps for CI 1. Deal with the environment variables - possible approach above. 2. Create a `continuous_integration` job as a GitHub action and use the values that you did have in your `app.json` file for `environments.test.scripts.test-setup` and `environments.test.scripts.test` and make them individual stesp in the workflow. 3. Turn on this workflow as appropriate for your GitHub events. In this workflow in the conintuous integration job is happening on every push to `main` and on every push to a branch that is part of a pull request. 4. Once this is in place, if you want to make the CI be required for branch merging, go to the Branch Protection rules of your repo and put this job in as a status check requirement. It should show up in the dropdown list if the job has run at least once in the past week. ## General Migration steps for "Review" apps 1. Deal with the environment variables - possible approach above. 2. Create a `review_deploy` job as a GitHub action that manges a heroku application in your pipeline in the `development` stage. 3. Update the `Set Member Permissions` step as appropriate for your situation. The old permissions that we done for the review apps where "ephemeral" and had specific rules around them in heroku along with the team member status in the pipeline. This does not apply for what we are dong now so we need to be explicity about the permissions of heroku users. 4. Wire up GitHub Deployment status around the review app so the PR links are good 5. Create a `review_destroy` job as a GitHub action that destorys the appropriate heroku app on pull request close. ## General Migration steps for Autodeployment to other stages of your pipeline 1. Deal with the environment variables - possible approacch above. 2. Create a `<stage>_deploy` job as a GitHub action that does does a heroku deploy based upon the appropriate branch from your repo. The example in this workflow deploys from the `main` branch of the repo to the `staging` stage of a heroku pipeline. And it also only does this if the `continuous_integration` job is successful. This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,274 @@ name: "CI/CD" on: push: branches: - 'main' pull_request: types: [opened, synchronize, reopened, closed] env: HEROKU_TEAM: "my-heroku-team" HEROKU_STAGING_APP: "my-staging-pipeline-app" STAGING_APP_URL: "https://url-to-staging-pipeline-app.invalid/" HEROKU_REVIEW_APP_ADDONS: "--addons=heroku-postgresql:hobby-dev" HEROKU_PIPELINE_NAME: "my-heroku-pipeline-name" # All the other environment variables your test environment needs # XYZ_TOKEN: ${{ secrets.XYZ_TOKEN }}} # SOMETHING_URL: ${{ secrets.SOMETHING_URL }} jobs: # Continus Integration job that runs all the tests - similar to what was # done with the Heroku CI Test. If you had an in-dyno database on your CI Test # runs, then this should also work for you here with the postgres service. continuous_integration: if: github.event.action != 'closed' env: DATABASE_URL: postgresql://postgres:[email protected]/dbname_test NODE_ENV: test NOCK_DISABLE_NETWORK: on runs-on: ubuntu-latest services: postgres: image: postgres env: POSTGRES_PASSWORD: postgres POSTGRES_USER: postgres ports: - 5432:5432 # Set health checks to wait until postgres has started options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 steps: - name: "Check out repository code" uses: actions/checkout@v3 - name: Setup Node uses: actions/setup-node@v3 with: node-version-file: .nvmrc cache: 'npm' - name: Update to latest npm run: npm install npm@latest -g - name: Install Node packages run: npm install - name: Setup the Test environment run: ./ci/test-setup # This was what you did have in app.json for test environment for `test-setup` script - name: Run tests run: ./ci/test # This was hwat you had in app.json for test environment `test` script # Auto deploy to the staging stage of the application pipelin when a push # happens on the main branch in the repo. This replicates auto deployment to a # heroku pipeline stage from a known branch. If you used a different branch, # change it here and in the `on` section at the top of the workflow. Feel free # to add other `_deploy` items if you had other branches going to other stages # # This also enforces that the test above run before the deploy happens staging_deploy: if: github.ref_name == 'main' name: Deploy to Heroku Staging needs: [continuous_integration] runs-on: ubuntu-latest steps: - name: "Check out repository code" uses: actions/checkout@v3 - name: Get git output names id: git shell: bash run: | if [[ "${{ github.ref }}" != "refs/tags/"* ]]; then if [[ ${{ github.event_name }} == 'pull_request' ]]; then echo "::set-output name=current_branch::$HEAD_REF" else echo "::set-output name=current_branch::$REF_BRANCH" fi else REF=$(printf "%q" "${{ github.ref }}") REF_BRANCH=${REF/refs\/tags\/${{ inputs.strip_tag_prefix }}/} echo "::set-output name=current_branch::$(eval printf "%s" "$REF_BRANCH")" fi # Wire up github deployments so that these can fire so if other # integrations depended on the github deployment notifications, they can # also still happen. - uses: chrnorm/deployment-action@releases/v1 name: Create GitHub deployment id: deployment with: initial_status: "in_progress" token: "${{ github.token }}" target_url: ${{ env.STAGING_APP_URL }} environment: staging ref: ${{ steps.git.outputs.current_branch }} - uses: akhileshns/[email protected] name: Heroku Deploy with: heroku_api_key: ${{ secrets.HEROKU_API_KEY }} heroku_app_name: ${{ env.HEROKU_STAGING_APP }} heroku_email: ${{ secrets.HEROKU_EMAIL }} - name: Update deployment status (success) if: ${{ success() }} uses: chrnorm/deployment-status@releases/v1 with: token: "${{ github.token }}" target_url: ${{ env.STAGING_APP_URL }} state: "success" deployment_id: ${{ steps.deployment.outputs.deployment_id }} ref: ${{ steps.git.outputs.current_branch }} - name: Update deployment status (failure) if: ${{ failure() }} uses: chrnorm/deployment-status@releases/v1 with: token: "${{ github.token }}" target_url: ${{ env.STAGING_APP_URL }} state: "failure" deployment_id: ${{ steps.deployment.outputs.deployment_id }} ref: ${{ steps.git.outputs.current_branch }} # Create a review app on pull request open or reopen, and push to the review # app on PR syncronize a.k.a 'push' review_deploy: name: "Deploy to Heroku Review" if: github.event_name == 'pull_request' && github.event.action != 'closed' runs-on: ubuntu-latest env: HEROKU_APP_NAME: my-app-slug-review-pr-${{ github.event.number }} steps: - name: "Check out repository code" uses: actions/checkout@v3 with: fetch-depth: 0 ref: ${{ github.head_ref }} - name: Get git output names id: git shell: bash run: | if [[ "${{ github.ref }}" != "refs/tags/"* ]]; then if [[ ${{ github.event_name }} == 'pull_request' ]]; then echo "::set-output name=current_branch::$HEAD_REF" else echo "::set-output name=current_branch::$REF_BRANCH" fi else REF=$(printf "%q" "${{ github.ref }}") REF_BRANCH=${REF/refs\/tags\/${{ inputs.strip_tag_prefix }}/} echo "::set-output name=current_branch::$(eval printf "%s" "$REF_BRANCH")" fi # Wire up the github deployment so the links are valid for the PR under # `view deployment` - name: Create GitHub deployment uses: chrnorm/deployment-action@releases/v1 id: deployment with: initial_status: "in_progress" token: "${{ github.token }}" target_url: https://${{ env.HEROKU_APP_NAME}}.herokuapp.com/ environment: ${{ env.HEROKU_APP_NAME }} ref: ${{ github.head_ref }} - name: Login to Heroku uses: akhileshns/[email protected] with: heroku_api_key: ${{ secrets.HEROKU_API_KEY }} heroku_email: ${{ secrets.HEROKU_EMAIL }} heroku_app_name: ${{ env.HEROKU_APP_NAME }} justlogin: true - name: Create Heroku app if: github.event.action == 'opened' || github.event.action == 'reopened' run: heroku apps:create ${{ env.HEROKU_APP_NAME }} --team=${{ env.HEROKU_TEAM }} ${{ env.HEROKU_REVIEW_APP_ADDONS }} - name: Add Heroku app to pipeline if: github.event.action == 'opened' || github.event.action == 'reopened' run: heroku pipelines:add ${{ env.HEROKU_PIPELINE_NAME }} --app=${{ env.HEROKU_APP_NAME }} --stage=development # This is where you set the environment variables that were part of the # original Heroku Config Vars for the Review App. Update this as # appropriate - name: Set the environment variables if: github.event.action == 'opened' || github.event.action == 'reopened' run: | env | grep AUTH0 > .env env | grep API_AUDIENCE >> .env env | grep HEALTHCLOUD >> .env env | grep SALESFORCE >> .env cat .env | tr '\n' ' ' | xargs heroku config:set --app=${{ env.HEROKU_APP_NAME }} rm -f .env - name: Add Heroku remote if: github.event.action != 'closed' run: heroku git:remote --app=${{ env.HEROKU_APP_NAME }} # Depending on how your heroku organization is setup, the step may not # be necessary. Previously in heroku review apps, the members of the # pipeline team would be automatically given ephemeral permissions on the # review app. That doesn't happen so this needs to be replicated. # # This will cause a lot of email notifications. - name: Set Member Permissions if: github.event.action != 'closed' shell: bash --noprofile --norc {0} run: | users=$(heroku members --team ${{ env.HEROKU_TEAM }} | grep "something appropriate" | awk '{ print $1 }') for user in ${users} do heroku access:add ${user} --app=${{ env.HEROKU_APP_NAME }} --permissions deploy,operate,manage heroku access:update ${user} --app=${{ env.HEROKU_APP_NAME }} --permissions deploy,operate,manage done exit 0 - name: Push to Heroku if: github.event.action != 'closed' run: git push heroku ${{ github.head_ref }}:main --force # Update the github deployment with success and link to the environment - name: Update deployment status if: github.event.action != 'closed' uses: chrnorm/deployment-status@releases/v1 with: token: "${{ github.token }}" target_url: https://${{ env.HEROKU_APP_NAME}}.herokuapp.com/ environment_url: https://${{ env.HEROKU_APP_NAME}}.herokuapp.com/ state: "success" deployment_id: ${{ steps.deployment.outputs.deployment_id }} # Once the PR is closed, destroy the app in heroku. # review_destroy: if: github.event_name == 'pull_request' && github.event.action == 'closed' name: "Cleanup and Remove Heroku Review" runs-on: ubuntu-latest env: HEROKU_APP_NAME: my-app-slug-review-pr-${{ github.event.number }} steps: - name: Login to Heroku uses: akhileshns/[email protected] with: heroku_api_key: ${{ secrets.HEROKU_API_KEY }} heroku_email: ${{ secrets.HEROKU_EMAIL }} heroku_app_name: ${{ env.HEROKU_APP_NAME }} justlogin: true - name: Destroy Heroku app run: heroku apps:destroy --app=${{ env.HEROKU_APP_NAME }} --confirm=${{ env.HEROKU_APP_NAME }}