Skip to content

refactor: remove context.Background() references from hooks#50

Merged
mwbrooks merged 3 commits into
mainfrom
mbrooks-hooks-context-background
Apr 21, 2025
Merged

refactor: remove context.Background() references from hooks#50
mwbrooks merged 3 commits into
mainfrom
mbrooks-hooks-context-background

Conversation

@mwbrooks

@mwbrooks mwbrooks commented Apr 18, 2025

Copy link
Copy Markdown
Member

Summary

Draft until after our upcoming release. Release v3.0.5 is ready

This pull request updates the package hooks by removing all references to context.Background().

Reviewers

This is a bit of a nasty change, so I've dedicated a PR to it.

The key change updates .Execute(opts) to .Execute(ctx, opts). This causes a ripple effect of changes in order to pass ctx into the hooks executor. The majority of the changes occur in the tests, where mocks must be updated to work with the new argument. 🪝

Really appreciate the time of reviewer going through these changes!

Requirements

@mwbrooks mwbrooks added code health M-T: Test improvements and anything that improves code health semver:patch Use on pull requests to describe the release version increment labels Apr 18, 2025
@mwbrooks mwbrooks added this to the Next Release milestone Apr 18, 2025
@mwbrooks mwbrooks self-assigned this Apr 18, 2025
@codecov

codecov Bot commented Apr 18, 2025

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 95.45455% with 2 lines in your changes missing coverage. Please review.

Project coverage is 62.89%. Comparing base (f3ba824) to head (e1b1e44).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
internal/pkg/platform/deploy.go 0.00% 1 Missing ⚠️
internal/update/sdk.go 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #50      +/-   ##
==========================================
- Coverage   62.91%   62.89%   -0.02%     
==========================================
  Files         210      210              
  Lines       22152    22154       +2     
==========================================
- Hits        13936    13934       -2     
- Misses       7132     7133       +1     
- Partials     1084     1087       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@mwbrooks mwbrooks left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

📝 Notes to help the very much appreciated reviewer!

Comment thread cmd/app/add_test.go

manifestMock := &app.ManifestMockObject{}
manifestMock.On("GetManifestLocal", mock.Anything, mock.Anything).Return(types.SlackYaml{
manifestMock.On("GetManifestLocal", mock.Anything, mock.Anything, mock.Anything).Return(types.SlackYaml{

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

note: A common change is updating mocks to support the added ctx context.Context argument.

Comment thread cmd/doctor/check_test.go
mockDoctorHook := `{"versions": [{"name": "deno", "current": "1.0.0", "message": "Secure runtimes make safer code", "error": {"message": "Something isn't right with this installation"}}]}`
mockDoctorScript := hooks.HookScript{Command: "echo checkup"}
cm.HookExecutor.On("Execute", hooks.HookExecOpts{Hook: mockDoctorScript}).
cm.HookExecutor.On("Execute", mock.Anything, hooks.HookExecOpts{Hook: mockDoctorScript}).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

note: I know a few of these lines are getting longer and could be expanded to multiple lines, but I wanted to keep the changes low since this PR was already getting a little large.

Comment thread cmd/doctor/doctor.go
Hook: clients.SDKConfig.Hooks.Doctor,
}
getDoctorHookJSON, err := clients.HookExecutor.Execute(hookExecOpts)
getDoctorHookJSON, err := clients.HookExecutor.Execute(ctx, hookExecOpts)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

note: This is the final result of the work - the new signature is .Execute(ctx, opts).

Comment thread cmd/manifest/info.go
Comment on lines +109 to 111
return getManifestInfoProject(ctx, clients)
case source.Equals(config.MANIFEST_SOURCE_REMOTE):
return getManifestInfoRemote(ctx, clients)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

note: It's nice to see that both getManifestInfoProject(ctx, clients) and getManifestInfoRemote(ctx, clients) have the same function signatures.

Comment thread cmd/triggers/create.go
}

func triggerRequestViaHook(clients *shared.ClientFactory, path string, isDev bool) (api.TriggerRequest, error) {
func triggerRequestViaHook(ctx context.Context, clients *shared.ClientFactory, path string, isDev bool) (api.TriggerRequest, error) {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

note: Example of the cascading changes to pass ctx into areas where .Execute is called.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@mwbrooks Legend ⭐

These changes seem tedious, but I am so hopeful that future changes can make use of the real ctx without hassle now.

Comment thread internal/app/manifest.go
Comment on lines +37 to 38
GetManifestLocal(ctx context.Context, sdkConfig hooks.SDKCLIConfig, hookExecutor hooks.HookExecutor) (types.SlackYaml, error)
GetManifestRemote(ctx context.Context, token string, appID string) (types.SlackYaml, error)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

note: It's nice to see that both GetManifestLocal(ctx, ... and GetManifestRemote(ctx, ... now except context.


// Execute processes the data received by the SDK.
func (e *HookExecutorDefaultProtocol) Execute(opts HookExecOpts) (string, error) {
func (e *HookExecutorDefaultProtocol) Execute(ctx context.Context, opts HookExecOpts) (string, error) {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

⭐ ⭐ ⭐
note: This is 1 of 2 key changes in this PR. Here we update the default hook executor protocol to accept a context argument. This allows us to remove the context.Background() usage inside this function.
⭐ ⭐ ⭐

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@mwbrooks Fantastic catch here!

IIRC a "background" context was used as a quick workaround for debug printing. It's now more clear that a follow up for this is important and having it broken into a standalone PR makes reviewing swell 🫡


// Execute processes the data received by the SDK.
func (e *HookExecutorMessageBoundaryProtocol) Execute(opts HookExecOpts) (string, error) {
func (e *HookExecutorMessageBoundaryProtocol) Execute(ctx context.Context, opts HookExecOpts) (string, error) {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

⭐ ⭐ ⭐
note: This is 2 of 2 key changes in this PR. Here we update the V2 hook executor protocol to accept a context argument. This allows us to remove the context.Background() usage inside this function.
⭐ ⭐ ⭐

AuthTokens: authTokens,
}
if err := clients.Runtime.PreparePackage(clients.SDKConfig, clients.HookExecutor, preparePackageOpts); err != nil {
if err := clients.Runtime.PreparePackage(ctx, clients.SDKConfig, clients.HookExecutor, preparePackageOpts); err != nil {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

note: We also needed to update the package runtime interface for PreparePackage to accept a ctx argument. On the upside, this aligns with the other functions in the interface, which also accept a ctx.

SetVersion(string)
HooksJSONTemplate() []byte
PreparePackage(hooks.SDKCLIConfig, hooks.HookExecutor, types.PreparePackageOpts) error
PreparePackage(context.Context, hooks.SDKCLIConfig, hooks.HookExecutor, types.PreparePackageOpts) error

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

note: Here we are updating the package runtime interface. Now both InstallProjectDependencies(ctx, ... and PreparePackage(ctx, ... accept context.

@zimeg zimeg modified the milestones: v3.0.5, Next Release Apr 18, 2025
@mwbrooks mwbrooks marked this pull request as ready for review April 21, 2025 18:57
@mwbrooks mwbrooks requested a review from a team as a code owner April 21, 2025 18:57

@zimeg zimeg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@mwbrooks All super awesome changes within! 👾 ✨

The key change updates .Execute(opts) to .Execute(ctx, opts).

This is big 🔑 I know a missing context here has confused me before!

Finding that we were using "background" contexts and replacing it with the shared and single context used elsewhere is so good for keeping things consistent.

With this in mind, all of the other (many) changes go well!

I might've commented this elsewhere, but thanks for keeping these changes scoped to single PRs 💌

Comment thread cmd/platform/deploy.go
IO: clients.IO,
}
if _, err := shell.Execute(hookExecOpts); err != nil {
if _, err := shell.Execute(ctx, hookExecOpts); err != nil {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🔭 This change is super great to find!

Comment thread cmd/triggers/create.go
}

func triggerRequestViaHook(clients *shared.ClientFactory, path string, isDev bool) (api.TriggerRequest, error) {
func triggerRequestViaHook(ctx context.Context, clients *shared.ClientFactory, path string, isDev bool) (api.TriggerRequest, error) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@mwbrooks Legend ⭐

These changes seem tedious, but I am so hopeful that future changes can make use of the real ctx without hassle now.

@@ -256,7 +256,7 @@ func TestTriggersCreateCommand(t *testing.T) {
appSelectTeardown = setupMockCreateAppSelection(installedProdApp)
// TODO: testing chicken and egg: we need the default mocks in place before we can use any of the `clients` methods

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

📚 Unrelated to the changes of this PR, we might revisit these comments soon since setting up default mocks is seeming standard before customized mocks from what I can tell.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

🗒️ Good call! I'll add a note to loop back on this after I finish the context work. It almost looks like we can just remove this TODO because it's setting up the default mocks and then adding custom ones. 🤔

Comment thread internal/app/manifest.go
}

slackManifestInfo, err := hookExecutor.Execute(manifestHookOpts)
slackManifestInfo, err := hookExecutor.Execute(ctx, manifestHookOpts)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

One 👏 true 👏 context 👏 ✨


// Execute processes the data received by the SDK.
func (e *HookExecutorDefaultProtocol) Execute(opts HookExecOpts) (string, error) {
func (e *HookExecutorDefaultProtocol) Execute(ctx context.Context, opts HookExecOpts) (string, error) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@mwbrooks Fantastic catch here!

IIRC a "background" context was used as a quick workaround for debug printing. It's now more clear that a follow up for this is important and having it broken into a standalone PR makes reviewing swell 🫡

Comment on lines +76 to 81
mockHookExecutor.On("Execute", mock.Anything, mock.Anything).
Run(func(args mock.Arguments) {
opts := args.Get(0).(hooks.HookExecOpts)
opts := args.Get(1).(hooks.HookExecOpts)
_, err := opts.Stdout.Write([]byte(tt.hookExecuteStdout))
require.NoError(t, err)
}).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

👁️‍🗨️ Good catch!!

@mwbrooks

Copy link
Copy Markdown
Member Author

🙏🏻 @zimeg Thanks for the quick review and I've made a few notes about your suggestions for the future. Always appreciate that you're willing to review these PRs - they're not exciting, but hopefully moving the code into a better place. One PR at a time.

@mwbrooks mwbrooks merged commit edb8e97 into main Apr 21, 2025
@mwbrooks mwbrooks deleted the mbrooks-hooks-context-background branch April 21, 2025 20:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

code health M-T: Test improvements and anything that improves code health semver:patch Use on pull requests to describe the release version increment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants