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

Build, test, and deploy a Heroku slug instead of re-building on Heroku #857

Merged
merged 7 commits into from
May 13, 2024

Conversation

tsibley
Copy link
Member

@tsibley tsibley commented May 10, 2024

See commit messages.

Resolves: #850

Checklist

  • Checks pass
  • Post-merge: Delete "heroku" GitHub environment
  • Post-merge: Delete Heroku API token for bot@nextstrain.org that was associated with the "heroku" GitHub environment:
    curl -n -X DELETE https://api.heroku.com/oauth/authorizations/6716fa11-cb1e-443a-be34-f9051cbb33b3 \
      -H 'Accept: application/vnd.heroku+json; version=3'
    

@nextstrain-bot nextstrain-bot temporarily deployed to nextstrain-s-trs-give-m-onbxlv May 10, 2024 22:25 Inactive
@tsibley tsibley requested a review from a team May 10, 2024 22:25
@tsibley tsibley force-pushed the trs/give-me-a-build-ci-one-build-only-please branch from a6a8a3a to 2ab1460 Compare May 10, 2024 22:37
@tsibley tsibley temporarily deployed to nextstrain-s-trs-give-m-onbxlv May 10, 2024 22:38 Inactive
Copy link
Member

@victorlin victorlin left a comment

Choose a reason for hiding this comment

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

Didn't test much, just ran the two scripts locally and skimmed commits. Looking forward to faster build times!

.github/workflows/ci.yml Show resolved Hide resolved
--env SOURCE_VERSION \
--env SOURCE_DESCRIPTION \
--env NODE_MODULES_CACHE=false \
heroku/heroku:20-build bash -c '
Copy link
Member

Choose a reason for hiding this comment

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

note

heroku/heroku:20-build (and 22-build) are single-platform linux/amd64 - no linux/arm64 variant. This means scripts/heroku-build runs slower on Apple silicon, but not terribly slow - 7m17s on my M1 just now.

heroku/heroku:24-build is multi-platform with a linux/arm64 variant. Just noting a reason to upgrade in the future.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good to note! Upgrading should be pretty painless, but I wanted to save that for another PR.

scripts/heroku-exec Show resolved Hide resolved
…Heroku

Building the Heroku app slug locally avoids the need to re-build on
Heroku.  Heroku build dynos are much slower than GitHub Action runners
and building twice is a waste of time regardless.  This also means that
we deploy the exact thing that we test instead of a new build, making
this now a true CI flow.

The CI jobs are now:

    ┌─────────────┐
    │ lint (~40s) │
    └─────────────┘
    ┌─────────────┐     ┌───────────────┐     ┌───────────────┐
    │ build (~4m) │────▶│ test (~1m15s) │────▶│ deploy (~30s) │
    └─────────────┘     └───────────────┘     └───────────────┘
        │                                             ▲
        └─────────────────────────────────────────────┘

Lint is moved out of test, because test now happens after build and it
doesn't make sense to lint _after_ build (since, as a previous comment
noted, the build will fail if linting fails).

Review apps are still built twice—once on GitHub Actions and once on
Heroku—and deployed from the Heroku build, but we can address that in
future work if desired.

For troubleshooting and debugging, the Heroku app slug can be built
locally as well with `./scripts/heroku-build`.  Docker is required.

Resolves: <#850>
This is handy for testing the "deploy" job and potentially for deploying
a larger work-in-progress change to dev.nextstrain.org (i.e. before its
ready for next.nextstrain.org).

The "deploy" job now references a GitHub environment¹ named after the
Heroku app to access Heroku API credentials and record the deployment.
I've provisioned the "nextstrain-canary"² and "nextstrain-dev"³
environments in the repo settings.  Each has the same Heroku API token
attached to bot@nextstrain.org, scoped down to "write-protected"
(instead of the default of "global").⁴  The "nextstrain-canary"
environment can only be used when running on master and so is only
usable by those who can push to master.  The "nextstrain-dev"
environment, however, can be used from any branch, and thus as a
safeguard requires manual approval of the deployment by
@nextstrain/core.  Unfortunately the Heroku API tokens can't be scoped
down to a single app instead; they always allow access to all apps the
bot@ account can manage.

¹ <https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment>
² <https://github.com/nextstrain/nextstrain.org/settings/environments/440351004/edit>
³ <https://github.com/nextstrain/nextstrain.org/settings/environments/13941227/edit>
⁴ <https://devcenter.heroku.com/articles/oauth#scopes>
No need to be a secret, and makes it clearer what token we're working
with.  I've adjusted the "nextstrain-canary" and "nextstrain-dev"
environments to account for this.
@tsibley
Copy link
Member Author

tsibley commented May 10, 2024

Looking forward to faster build times!

Yeah! For CI runs that deploy, it'll mean faster times. For CI runs that don't deploy, it may be a bit slower. Need to look into that more closely. OTOH, if we're going to start deploying review apps ourselves (and I think we probably should?) then all CI runs will do deploys.

@victorlin noted in review that the previous construct threw an "unbound
variable" error on macOS's system Bash 3.2.57.¹  This is because after
3.2.57 and at least by 4.4.20 (but maybe earlier), Bash stopped treating
the "@" and "*" parameters as unset under -u when empty.²

Use an array slice³ (i.e. substring expansion, ${parameter:offset},
applied to an array) as a workaround.  Note that testing if
"docker_args" is empty, e.g. "${docker_args:+${docker_args[@]}}", won't
work because it leaves us with an empty string argument when unset.

¹ <#857 (comment)>
² <nextstrain/ingest#17 (comment)>
³ <https://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion>
@tsibley tsibley force-pushed the trs/give-me-a-build-ci-one-build-only-please branch from 2ab1460 to 0f76b4b Compare May 13, 2024 17:27
@tsibley tsibley temporarily deployed to nextstrain-s-trs-give-m-onbxlv May 13, 2024 17:28 Inactive
@tsibley
Copy link
Member Author

tsibley commented May 13, 2024

For CI runs that deploy, it'll mean faster times. For CI runs that don't deploy, it may be a bit slower.

One thing we could do here (even if we're going to move review apps into CI and make all CI runs do deploys) is run tests against both the "deployment-style" build as is done in this PR currently and a "development-style" build as we used to. They could run concurrently and wouldn't change the overall duration of the CI run while still giving us faster deploys. Put another way, we'd make the current lint job in this PR also continue to run tests (and rename the job).

@tsibley tsibley requested a review from victorlin May 13, 2024 17:41
…instead of a potentially not-yet-released version.  "latest" is a tag
that Heroku updates to keep pointed at the latest numbered release tag,
e.g. it points to "v247" currently.
@tsibley tsibley temporarily deployed to nextstrain-s-trs-give-m-onbxlv May 13, 2024 18:11 Inactive
Copy link
Member

@victorlin victorlin left a comment

Choose a reason for hiding this comment

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

run tests against both the "deployment-style" build as is done in this PR currently and a "development-style" build as we used to

Is the only benefit to have a slightly faster build result? If so, I don't think it's worth the added complexity.

We could always merge as-is and reconsider later if build results seem painfully slower.

@tsibley tsibley merged commit eb29ccf into master May 13, 2024
6 checks passed
@tsibley tsibley deleted the trs/give-me-a-build-ci-one-build-only-please branch May 13, 2024 20:36
@tsibley
Copy link
Member Author

tsibley commented May 13, 2024

Is the only benefit to have a slightly faster build result?

Slightly faster time-to-test-failure for failing CI runs. Yeah, wasn't suggesting I do it now in this PR but as an option for the future.

Copy link
Contributor

@joverlee521 joverlee521 left a comment

Choose a reason for hiding this comment

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

Hooray for faster deploys!

Will need to read more on buildspacks...I'm assuming this will inform the implementation details for creating Heroku review apps.

scripts/heroku-build Show resolved Hide resolved
scripts/heroku-build Show resolved Hide resolved
@tsibley
Copy link
Member Author

tsibley commented May 13, 2024

First deploy to canary with this PR went smoothly. Note the lack of a Heroku build before the Heroku deploy:

image

GitHub CI run and GitHub deployment record.

image

I've done the post-merge tidy ups I'd previously identified.

tsibley added a commit that referenced this pull request May 13, 2024
…ort options

The long options are from GNU coreutils, but macOS ships a BSD tty and
du.  Only one of the swapped options is POSIX.

Noted by @joverlee521 in post-merge review.¹

¹ <#857 (review)>
Comment on lines 120 to +122
environment:
name: heroku
url: https://next.nextstrain.org
name: ${{ inputs.heroku-app || 'nextstrain-canary' }}
url: ${{ inputs.heroku-app && format('https://{0}.herokuapp.com', inputs.heroku-app) || 'https://next.nextstrain.org' }}
Copy link
Member

Choose a reason for hiding this comment

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

On the deployments page, nextstrain-canary maps to next.nextstrain.org and nextstrain-dev to nextstrain-dev.herokuapp.com (as opposed to dev.nextstrain.org). I thought that was weird, but it makes sense after looking back at this.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, we could improve that various ways later.

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

Successfully merging this pull request may close these issues.

Use same build in CI for both testing and deploy to Heroku
4 participants