feat: fall back to manifest.json when get-manifest hook is unavailable - #629
feat: fall back to manifest.json when get-manifest hook is unavailable#629srtaalej wants to merge 17 commits into
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #629 +/- ##
==========================================
+ Coverage 78.18% 78.20% +0.02%
==========================================
Files 239 239
Lines 18136 18149 +13
==========================================
+ Hits 14179 14193 +14
+ Misses 3957 3956 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
zimeg
left a comment
There was a problem hiding this comment.
@srtaalej Super appreciate the changes toward this 🌟
I left a comment on precedence of manifestations and am thinking that the fallback manifest.json file allows us to consider the manifest "CLI-managed" while with a hook ought mean not.
This pattern has a slow rollout with hooks needing to be updated too, but I'm most optimistic for the changes it'll unlock with confidence in changing a project manifest.
| if exists, _ := afero.Exists(c.fs, manifestPath); exists { | ||
| return c.readManifestFile(manifestPath) | ||
| } | ||
| return c.getManifestFromHook(ctx, sdkConfig, hookExecutor) |
There was a problem hiding this comment.
🔭 thought: We should reverse this order to check if a get-manifest hook exists and fallback to reading "manifest.json" file. Deprecating the hook might happen at the hook package while the CLI continues to support it.
zimeg
left a comment
There was a problem hiding this comment.
🔍 Before testing more I want to cut scope on this change. I think other PRs can follow to ensure we're not clobbering an SDK managed manifest!
| if !exists { | ||
| return WriteBackResult{ | ||
| Warning: fmt.Sprintf("No %s found in project root — merged manifest was not written locally", manifestFileName), | ||
| }, nil | ||
| fresh, err := marshalFresh(manifest) | ||
| if err != nil { | ||
| return WriteBackResult{}, fmt.Errorf("failed to serialize merged manifest: %w", err) | ||
| } | ||
| if err := atomicWriteFile(fs, manifestPath, fresh, 0644); err != nil { | ||
| return WriteBackResult{}, fmt.Errorf("failed to write %s: %w", manifestFileName, err) | ||
| } | ||
| return WriteBackResult{Written: true, FilePath: manifestPath}, nil | ||
| } |
There was a problem hiding this comment.
🦠 suggestion: Let's keep this change for a separate PR!
| return c.readManifestFile(manifestPath) | ||
| } | ||
|
|
||
| func (c *ManifestClient) readManifestFile(path string) (types.SlackYaml, error) { |
There was a problem hiding this comment.
| func (c *ManifestClient) readManifestFile(path string) (types.SlackYaml, error) { | |
| func (c *ManifestClient) getManifestFromFile(sdkConfig hooks.SDKCLIConfig) (types.SlackYaml, error) { |
🌵 thought: I think we should match the function name convention here and also keep path specific logic contained within this function. I'm less confident of the second thought FWIW!
zimeg
left a comment
There was a problem hiding this comment.
@srtaalej Nice I think this'll be a big unlock before the experiment concludes! I'm leaving a few comments but logic LGTM.
- 🧪 Tests can perhaps be scoped more narrow to the hook and fallback changes? I'm interested in this so we keep confidence in both what's changing and what's not.
- 🔭 The
synccommand might have follow up to require a manifest hook doesn't exist. IMHO this is important so we're confident in writing back to expected JSON instead of whatever a hook might gather from. - 🪝 We should discuss a plan to remove
get-manifestfrom the Bolt hook implementations. I forget if we can confirm current CLI versions as part of hooks but we might prefer the plain JSON for apps going forward.
If test changes seem alright and so do discussion points above let me know for a final test and review! 🪬 ✨
| assert.Equal(t, tc.expectedManifest, actualManifest) | ||
| assert.Equal(t, tc.expectedName, result.DisplayInformation.Name) |
There was a problem hiding this comment.
🧪 suggestion: Might we keep the entire manifest assertion here? These unit tests are capturing a meaningful interface to build confidence to IMHO.
| hookTests := map[string]struct { | ||
| hookOutput string | ||
| hookErr error | ||
| expectedName string | ||
| expectedErr string | ||
| }{ |
There was a problem hiding this comment.
🧪 suggestion: Let's combine these test cases with the ones above for this function. This'll help us extend these later if needed with a solid foundation.
| // Verify remote value was used — the merged manifest should have "Remote" description | ||
| assert.Equal(t, "Remote", result.Merged.DisplayInformation.Description) | ||
| }) | ||
| mergeStrategyTests := map[string]struct { |
There was a problem hiding this comment.
👁️🗨️ question: Were these test expectations changed? I'm noticing we don't assert a call to the UpdateApp function now which concerns me somewhat since logic adjacent is being changed in this PR too.
Summary
GetManifestLocalnow falls back to readingmanifest.jsondirectly from the project root when noget-manifesthook is availablereadManifestFiletogetManifestFromFileto match thegetManifestFromHooknaming conventionCloses #627
Context
Projects without a
get-manifesthook but with a staticmanifest.jsonhad no way to read the local manifest. This addsmanifest.jsonas a fallback source when the hook isn't defined, allowing the CLI to manage the manifest directly for projects that don't use the hook.The hook remains the preferred source when available — a hook means the SDK manages the manifest, while a bare
manifest.jsonmeans it's CLI-managed.Test plan
make testpassesManual testing
Create a Bolt JS app using
slack createwith thebolt-js-starter-template:slack create my-test-app --template bolt-js-starter-template cd my-test-appTest 1: Hook path still works (existing behavior)
Should display the manifest via the
get-manifesthook.Test 2: Fallback to manifest.json when no hook is defined
Should display the manifest read from
manifest.json.