Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cypress release trigger #99

Merged
merged 39 commits into from
Sep 26, 2022
Merged

Cypress release trigger #99

merged 39 commits into from
Sep 26, 2022

Conversation

oudeismetis
Copy link
Member

@oudeismetis oudeismetis commented Jul 25, 2022

Better way to run Cypress for Review Apps

Addresses #88

  • Github Action turns on Heroku maintenance mode temporarily so Cypress defaults to failing
  • Heroku deployments call a release script
  • Release script calls Github API to trigger a rerun of the failing Cypress run
  • 2nd run of Cypress passes and is now guaranteed to be testing the most current version of deployed code
  • Document secret generation for devs

TODO:

  • Implement feature and/or fix bug
  • Add and/or fix tests
  • Review App looks good
  • Code Review
  • During merge...remove NPM_PRIVATE_TOKEN from Github and Heroku settings
  • During merge...generate new GITHUB_TOKEN and add it to the pipeline and staging settings in Heroku
  • During merge...generate new HEROKU_API_KEY and replace the old one in Github settings

@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 July 25, 2022 18:16 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 July 25, 2022 18:30 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 July 25, 2022 18:44 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 July 25, 2022 18:48 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 July 25, 2022 19:01 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 August 1, 2022 19:18 Inactive
@oudeismetis oudeismetis had a problem deploying to tn-spa-bootstrapper-pr-99 August 1, 2022 19:25 Failure
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 August 1, 2022 19:30 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 August 1, 2022 19:37 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 August 1, 2022 19:45 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 August 22, 2022 17:08 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 August 22, 2022 17:23 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 August 22, 2022 17:31 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 August 22, 2022 17:43 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 August 24, 2022 15:29 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 August 24, 2022 15:38 Inactive
@oudeismetis oudeismetis had a problem deploying to tn-spa-bootstrapper-pr-99 August 24, 2022 15:51 Failure
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 August 26, 2022 18:39 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 August 31, 2022 18:07 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 August 31, 2022 18:14 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 August 31, 2022 18:16 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 August 31, 2022 18:17 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 August 31, 2022 20:41 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 September 1, 2022 12:47 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 September 1, 2022 19:31 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 September 1, 2022 19:39 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 September 1, 2022 19:50 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 September 1, 2022 20:03 Inactive
@oudeismetis oudeismetis temporarily deployed to tn-spa-bootstrapper-pr-99 September 19, 2022 19:42 Inactive
CYPRESS_TEST_USER_EMAIL:
required: true
CYPRESS_TEST_USER_PASS:
required: true
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

workflow_call means it's called my other workflows (instead of on code push).
As a result, it doesn't have its own env or secrets so those have to be passed explicitly.

exit 1
else
echo "NOT in maintenance. Likely Heroku trigger after successful deploy";
fi
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test the URL to see if the app is not up yet (first commit) or if the app is in maintenance mode (waiting on deploy to finish)

path: my_project/
retention-days: 1
outputs:
BASE_URL: ${{ env.BASE_URL }}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

upload-artifacts allows us to do all the work we needed to do for cookiecutter only once. The later workflows can then do things like run inside a docker container and not worry about pip missing or not having permissions to install things (problem I ran into)

- uses: actions/download-artifact@v3
with:
name: my_project
path: my_project/
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only step needed to get the results of building code out during Setup

- uses: actions/download-artifact@v3
with:
name: my_project
path: my_project/
- name: Install frontend dependencies
env:
NPM_CONFIG_PRODUCTION: false
working-directory: ./my_project/client
run: npm install
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But for some reason npm install during Setup wouldn't work. Didn't bother digging into why.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it was a react app then it could be due to that Apollo peer dependencies error that is also behind the ESLint tests failing

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was on a Vue app. I think the error was something about the lock file missing. Something not getting carried over during the upload/download artifact step. I'm not really worried, though I like the idea of doing all the build steps during setup only.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand this better now. Makes perfect sense now that I think about.
Storing artifacts via actions/upload-artifact is only for files and folders. For things like installs via apt/python/npm there is a separate caches github action (actions/cache) which is also available inside actions like actions/setup-python (which we use). That is the proper way to install something once, and then reuse it between jobs or even separate workflow runs.
You can in fact install something when running the main branch and it'll use that cache by default on PRs.
artifacts are less powerful and are attached to a specific workflow run. So they can't be reused more widely.

with:
working-directory: my_project/client
browser: chrome
headless: true
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no longer a thing. It's headless by default. Use headed to actually have a browser available.

runs-on: ubuntu-latest
container:
image: cypress/browsers:node16.14.2-slim-chrome103-ff102 # https://github.com/cypress-io/cypress-docker-images/tree/master/browsers
options: --user 1001
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Firefox should now be more stable when it runs. (lots of questions/confusion/complaints online about running Firefox with Cypress. Hopefully this fix holds for a while)

echo "Turning off maintenance so Heroku triggering rerun of Cypress will succeed";
heroku maintenance:off --app=${{ needs.Setup.outputs.APP_NAME }}
env:
HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On every push of code we'll now immediately:

  • Put the app in maintenance mode
  • Run Cypress expecting it to fail fast (otherwise it'll be hidden on the PR and it won't exist to be re-run later)
  • Turn maintenance mode off

@@ -14,6 +14,6 @@ web: gunicorn {{ cookiecutter.project_slug }}.wsgi --chdir=server --log-file -
# 3. Up-to-date build numbers shown in app (ideally auto-generated at build-and-deploy time)
#
# Comment the line below to disable migrations automatically after a Heroku push.
release: python server/manage.py makemigrations --noinput && python server/manage.py migrate --noinput
release: python server/manage.py makemigrations --noinput && python server/manage.py migrate --noinput && ./scripts/release.sh
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When Heroku is finished deploying it'll call this new shell script

@@ -4,6 +4,10 @@

## Setup

### Github & Heroku
1. [Generate an auth token for Heroku](https://devcenter.heroku.com/articles/heroku-cli-commands#heroku-authorizations-create) and add it to the [repo secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets) so Github Actions can reach Heroku. `heroku authorizations:create -d "Github Actions" -s write-protected`
1. [Generate an auth token for Github](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-authentication-to-github#authenticating-with-the-api) and add it as [an environment variable](https://devcenter.heroku.com/articles/config-vars) so Heroku can trigger Github Actions
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heroku auth token is easy to generate and lives forever. Adding it to Github settings is safe as well.
The Github auth token is currently a personal auth token of mine (Ed) with an expiration in a week or so. That could be a long-lived token, but it also required authing the token with JumpCloud. Not sure how long that lives for. PLUS, you then add that token to Heroku and all devs can see it, so not as safe.

I did look into a solution for that. Github Actions DOES generate a temporary app token while the workflows are running and I was able to pass that to Heroku using the Heroku CLI (same spot where we turn maintenance mode on). Problem is that the token gets expired when the workflow finishes. Seems like the only way around that is to keep the workflow alive....so then we're back to sleeping for 5min.


workflow_id = self.find_cypress_workflow_id(branch)
job_id = self.find_job_id_for_cypress_step(workflow_id)
self.rerun_job(job_id)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A little complicated/convoluted, but basically we call Github's API to find the most recent Cypress run on this PR and tell it to run again.
At this point deployment is finished so rerunning will not only pass, but Cypress will be testing the most recently version of the code.

Copy link
Contributor

@brunogarciagonzalez brunogarciagonzalez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 🚀 🎸 ✅

@oudeismetis oudeismetis merged commit b201d1e into main Sep 26, 2022
@oudeismetis oudeismetis deleted the cypress-release-trigger branch September 26, 2022 14:47
@oudeismetis
Copy link
Member Author

Future me here 👋
This is not a good solution.
There is a much better and simpler way to accomplish this.
See #150

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants