Skip to content

feat: fall back to manifest.json when get-manifest hook is unavailable - #629

Open
srtaalej wants to merge 17 commits into
mainfrom
ale-add-force-to-run
Open

feat: fall back to manifest.json when get-manifest hook is unavailable#629
srtaalej wants to merge 17 commits into
mainfrom
ale-add-force-to-run

Conversation

@srtaalej

@srtaalej srtaalej commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • GetManifestLocal now falls back to reading manifest.json directly from the project root when no get-manifest hook is available
  • Renamed readManifestFile to getManifestFromFile to match the getManifestFromHook naming convention

Closes #627

Context

Projects without a get-manifest hook but with a static manifest.json had no way to read the local manifest. This adds manifest.json as 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.json means it's CLI-managed.

Test plan

  • make test passes
  • Existing tests updated to verify hook-first, file-fallback behavior

Manual testing

Create a Bolt JS app using slack create with the bolt-js-starter-template:

slack create my-test-app --template bolt-js-starter-template
cd my-test-app

Test 1: Hook path still works (existing behavior)

slack manifest info --skip-update

Should display the manifest via the get-manifest hook.

Test 2: Fallback to manifest.json when no hook is defined

# Replace hooks with an empty definition
echo '{"hooks":{}}' > .slack/hooks.json

# CLI should fall back to reading manifest.json directly
slack manifest info --skip-update

# Restore
git checkout .slack/hooks.json

Should display the manifest read from manifest.json.

@srtaalej
srtaalej requested a review from a team as a code owner August 10, 2026 17:10
@srtaalej srtaalej self-assigned this Aug 10, 2026
@srtaalej srtaalej added enhancement M-T: A feature request for new functionality semver:minor Use on pull requests to describe the release version increment labels Aug 10, 2026
@srtaalej srtaalej changed the title feat: add --manifest-source flag to run and deploy commands feat: default to manifest.json over get-manifest hook Aug 10, 2026
@srtaalej srtaalej added this to the Next Release milestone Aug 10, 2026
@codecov

codecov Bot commented Aug 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.44444% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 78.20%. Comparing base (73dde37) to head (5a0ec27).

Files with missing lines Patch % Lines
internal/app/app.go 0.00% 1 Missing ⚠️
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.
📢 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.

@srtaalej srtaalej closed this Aug 10, 2026
@srtaalej srtaalej reopened this Aug 10, 2026
@srtaalej srtaalej closed this Aug 10, 2026
@srtaalej
srtaalej deleted the ale-add-force-to-run branch August 10, 2026 17:41
@srtaalej
srtaalej restored the ale-add-force-to-run branch August 10, 2026 17:41
@srtaalej srtaalej reopened this Aug 10, 2026

@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.

@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.

Comment thread internal/app/manifest.go Outdated
Comment on lines +82 to +85
if exists, _ := afero.Exists(c.fs, manifestPath); exists {
return c.readManifestFile(manifestPath)
}
return c.getManifestFromHook(ctx, sdkConfig, hookExecutor)

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.

🔭 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 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.

🔍 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!

Comment on lines 47 to 56
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
}

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.

🦠 suggestion: Let's keep this change for a separate PR!

Comment thread internal/app/manifest.go Outdated
return c.readManifestFile(manifestPath)
}

func (c *ManifestClient) readManifestFile(path string) (types.SlackYaml, 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.

Suggested change
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!

@srtaalej srtaalej changed the title feat: default to manifest.json over get-manifest hook feat: fall back to manifest.json when get-manifest hook is unavailable Aug 17, 2026
@srtaalej
srtaalej requested a review from zimeg August 27, 2026 15:15
@zimeg zimeg modified the milestones: v4.7.0, Next Release Aug 28, 2026

@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.

@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 sync command 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-manifest from 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! 🪬 ✨

Comment on lines -141 to +193
assert.Equal(t, tc.expectedManifest, actualManifest)
assert.Equal(t, tc.expectedName, result.DisplayInformation.Name)

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.

🧪 suggestion: Might we keep the entire manifest assertion here? These unit tests are capturing a meaningful interface to build confidence to IMHO.

Comment on lines +146 to +151
hookTests := map[string]struct {
hookOutput string
hookErr error
expectedName string
expectedErr string
}{

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.

🧪 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 {

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.

👁️‍🗨️ 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.

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

Labels

enhancement M-T: A feature request for new functionality semver:minor Use on pull requests to describe the release version increment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Default to manifest.json over get-manifest hook in SDK templates

2 participants