feat: 'app link' supports run-on-slack apps with local manifest source#56
Conversation
mwbrooks
left a comment
There was a problem hiding this comment.
✏️ A few notes for the reviewer, so the test-cases don't look overwhelming!
| func LinkAppHeaderSection(ctx context.Context, clients *shared.ClientFactory, shouldConfirm bool) { | ||
| var secondaryText = []string{ | ||
| "Add an existing app created on app settings", | ||
| "Add an existing app from app settings", |
There was a problem hiding this comment.
note: App Settings now displays Slack CLI created apps as read-only, un-clickable. So, I figured we should update this text to not be restricted to "created on app settings" because the app may be created by the CLI.
| manifestSource, err := clients.Config.ProjectConfig.GetManifestSource(ctx) | ||
|
|
||
| if !manifestSource.Equals(config.MANIFEST_SOURCE_REMOTE) || err != nil { | ||
| if err != nil || (!manifestSource.Equals(config.MANIFEST_SOURCE_REMOTE) && cmdutil.IsSlackHostedProject(ctx, clients) != nil) { |
There was a problem hiding this comment.
note: This is the main change. We only want to display the manifest source update prompt when the manifest is not already remote AND it's not a ROSI app.
There was a problem hiding this comment.
Nit: I am perhaps low on brainpower right now, but this is not so obvious to me...
At the expense of an extra line or two, what do you think about a separate variable for:
isSlackHostedProject := cmdutil.IsSlackHostedProject(ctx, clients) == nilThere was a problem hiding this comment.
You and I were both low on brain power. I originally separated it to a variable in order to make sense of the conditional. Then I combined it afterwards. I'm happy to separate it out and I may do the same with the remote manifest conditional because the ! and .Equals take a moment to make sense.
There was a problem hiding this comment.
Commt 30e69a7 takes your suggestion to heart and it's so much better!
isManifestSourceRemote := manifestSource.Equals(config.MANIFEST_SOURCE_REMOTE)
isSlackHostedProject := cmdutil.IsSlackHostedProject(ctx, clients) == nil
if err != nil || (!isManifestSourceRemote && !isSlackHostedProject) {| ExpectedError: slackerror.New(slackerror.ErrAppNotFound), | ||
| }, | ||
| "accept manifest source prompt and saves information about the provided deployed app": { | ||
| "accepting manifest source prompt should save information about the provided deployed app": { |
There was a problem hiding this comment.
note: Just re-wording after reading over the test cases for clarity.
| require.Len(t, apps, 0) | ||
| }, | ||
| }, | ||
| "manifest source prompt should not display for Run-on-Slack apps with local manifest source": { |
There was a problem hiding this comment.
note: New test case to assert that the manifest update prompt is NOT displayed for ROSI apps with a local manifest. I don't check for remote manifests, because that's handled in an existing test-case.
| ) | ||
| }, | ||
| }, | ||
| "manifest source prompt should display for GBP apps with local manifest source": { |
There was a problem hiding this comment.
note: Added a test-case to assert that the manifest update prompt is still displayed for GBP apps with a local manifest. This case might be redundant, but I felt high confidence after adding it.
There was a problem hiding this comment.
Thanks for adding it! I had a good feeling when running the dev build and reading code, but this will be so helpful in guarding against unexpected updates to these prompts.
The assert prompting at the end is very very good for this 🏆 ✨
| // Mock manifest | ||
| manifestMock := &app.ManifestMockObject{} | ||
| manifestMock.On("GetManifestLocal", mock.Anything, mock.Anything).Return(types.SlackYaml{}, nil) | ||
| cf.AppClient().Manifest = manifestMock |
There was a problem hiding this comment.
note: Just a little reflection on how we don't actually have a nice way to mock the Manifest client atm. We have a ManifestMockObject but it's not automatically setup in the clients mock.
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #56 +/- ##
==========================================
- Coverage 62.89% 62.89% -0.01%
==========================================
Files 210 210
Lines 22154 22156 +2
==========================================
Hits 13934 13934
- Misses 7132 7134 +2
Partials 1088 1088 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
zimeg
left a comment
There was a problem hiding this comment.
@mwbrooks Thanks tons for tackling the initial issue with careful resolution and also finding a fix for future encounters! 💌
I got a bit stumped on logic within, but all testing is working well so marking this as approved 🚢 💨
In following comments I left a note on the confusion I had and another thought about testing. Please feel free to ignore and merge or respond if that feels right 👾
| manifestSource, err := clients.Config.ProjectConfig.GetManifestSource(ctx) | ||
|
|
||
| if !manifestSource.Equals(config.MANIFEST_SOURCE_REMOTE) || err != nil { | ||
| if err != nil || (!manifestSource.Equals(config.MANIFEST_SOURCE_REMOTE) && cmdutil.IsSlackHostedProject(ctx, clients) != nil) { |
There was a problem hiding this comment.
Nit: I am perhaps low on brainpower right now, but this is not so obvious to me...
At the expense of an extra line or two, what do you think about a separate variable for:
isSlackHostedProject := cmdutil.IsSlackHostedProject(ctx, clients) == nil| func LinkAppHeaderSection(ctx context.Context, clients *shared.ClientFactory, shouldConfirm bool) { | ||
| var secondaryText = []string{ | ||
| "Add an existing app created on app settings", | ||
| "Add an existing app from app settings", |
| ) | ||
| }, | ||
| }, | ||
| "manifest source prompt should display for GBP apps with local manifest source": { |
There was a problem hiding this comment.
Thanks for adding it! I had a good feeling when running the dev build and reading code, but this will be so helpful in guarding against unexpected updates to these prompts.
The assert prompting at the end is very very good for this 🏆 ✨
| // Mock manifest | ||
| manifestMock := &app.ManifestMockObject{} | ||
| manifestMock.On("GetManifestLocal", mock.Anything, mock.Anything, mock.Anything).Return(types.SlackYaml{}, nil) | ||
| cf.AppClient().Manifest = manifestMock |
There was a problem hiding this comment.
📝 Perhaps personal preference, but I'm curious what you think about:
Having standalone and shared "setup"..."mock" functions I find to be confusing, even if convenient. IMO inlining mocks is super helpful in table tests to keep each unit separate.
No blocker at all for this PR, but does this seem like a longterm idea we should nudge towards?
There was a problem hiding this comment.
🧠 I agree with you. I also find the .DefaultMocks() method confusing. Sometimes it can be very convenient because I just need a standard happy path mock, but often tests don't require it. The same can be true for the "setup" helpers, where they become overloaded with defaults that can actually drift some of the tests away from their target.
It would be nice to settle on some practice that keeps the tests short(er) while explicit.
Summary
This pull request updates the
app linkcommand to work with run-on-Slack apps that have a local manifest source.📝 1 line change and the rest are test-cases.
Perhaps, this as the beginning of loosening up the
app linkcommand to not always require a remote manifest source.This work came about from the GitHub Issue slackapi/deno-slack-sdk#451. In the issue, I wasn't able to suggest using the
app linkcommand because it would force the Deno SDK app to have a remote manifest. This seemed silly, since all Deno SDK apps have a local manifest. Since developer can now see their Deno SDK apps in https://api.slack.com/apps, we should allow them to link the app in their project.Preview
Deno SDK
2025-04-21-app-link-deno.mov
Bolt for JavaScript
2025-04-21-app-link-gbp.mov
Reviewers
Requirements