Skip to content

feat: support png, jpg, jpeg, gif for icon auto-detection#509

Open
srtaalej wants to merge 2 commits intomainfrom
ale-icon-assets-fallback
Open

feat: support png, jpg, jpeg, gif for icon auto-detection#509
srtaalej wants to merge 2 commits intomainfrom
ale-icon-assets-fallback

Conversation

@srtaalej
Copy link
Copy Markdown
Contributor

@srtaalej srtaalej commented Apr 27, 2026

Summary

  • Extracts resolveIconPath function to centralize icon fallback logic used by both Install and InstallLocalApp
  • Searches for icon.{png,jpg,jpeg,gif} in assets/ first, then project root — matching all formats the API accepts
  • Updates hasValidIconPath() in slack_yaml.go to also recognize jpg, jpeg, gif in assets/
  • PNG has highest priority when multiple icon files exist

Test plan

Unit tests

go test ./internal/pkg/apps/ -run Test_resolveIconPath -v   # 11 cases: all formats, priority, fallback paths
go test ./internal/shared/types/ -run Test_SlackYaml -v      # existing + new cases for jpg/gif/priority
go test ./...                                                # full suite

Manual testing

1. Build the branch

git fetch origin ale-icon-assets-fallback
git checkout ale-icon-assets-fallback
go build -o bin/slack .

2. Set up a test app (or use an existing bolt app)

./bin/slack create
cd <app-name>

3. Test assets/ auto-detection with different formats

Place an icon in assets/ and run:

mkdir -p assets
cp /path/to/icon.png assets/icon.png
../bin/slack run -e set-icon

Verify: Updated app icon: assets/icon.png

Repeat with assets/icon.jpg (remove icon.png first) — should pick up the jpg.

4. Test project root fallback

Remove any icon from assets/. Place icon.png in the project root:

rm assets/icon.*
cp /path/to/icon.png icon.png
../bin/slack run -e set-icon

Verify: Updated app icon: icon.png

5. Test priority (assets/ wins over root)

Place icons in both locations:

cp /path/to/icon.png assets/icon.png
cp /path/to/icon.png icon.png
../bin/slack run -e set-icon

Verify: Updated app icon: assets/icon.png (assets/ takes precedence)

6. Test manifest takes precedence

Set icon: "custom/my-icon.png" in the manifest. Run again — should use the manifest path, not auto-detection.

The icon upload fallback only checked for icon.png in the project root.
This adds assets/icon.png as the first fallback path, matching the
convention used by slack-samples template repos and the existing
auto-detection in slack_yaml.go.
@srtaalej srtaalej requested a review from a team as a code owner April 27, 2026 19:46
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 27, 2026

Codecov Report

❌ Patch coverage is 0% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.17%. Comparing base (1a7c949) to head (23afd93).

Files with missing lines Patch % Lines
internal/pkg/apps/install.go 0.00% 4 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #509      +/-   ##
==========================================
- Coverage   71.17%   71.17%   -0.01%     
==========================================
  Files         222      222              
  Lines       18678    18682       +4     
==========================================
+ Hits        13294    13296       +2     
- Misses       4201     4206       +5     
+ Partials     1183     1180       -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.

@zimeg zimeg changed the title fix: add assets/icon.png fallback for icon auto-detection feat: add assets/icon.png fallback for icon auto-detection Apr 27, 2026
Extract resolveIconPath to centralize icon fallback logic across
Install and InstallLocalApp. Search for icon.{png,jpg,jpeg,gif}
in assets/ then project root, matching all formats the API accepts.
@srtaalej srtaalej changed the title feat: add assets/icon.png fallback for icon auto-detection feat: support png, jpg, jpeg, gif for icon auto-detection Apr 28, 2026
Copy link
Copy Markdown
Member

@mwbrooks mwbrooks left a comment

Choose a reason for hiding this comment

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

🙇🏻 Thanks for putting this PR together @srtaalej!

✏️ I've left a couple feedback questions and suggestions, but overall this is looking good.

❓ Curious, have you tested this on both Deno/ROSI and Bolt using multiple image formats for each?

❓ This implementation is using manifest.json to define the icon. Personally, I like how clean this is but it does put us in a pickle if someone tries to copy & paste the manifest into App Settings or use our manifest-schema package for validation. Are we planning to explore defining the icon in config.json?


const additionalManifestInfoNotice = "App manifest contains some components that may require additional information"

var supportedIconExtensions = []string{".png", ".jpg", ".jpeg", ".gif"}
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: Just curious, have you tested all of these images types? I just want to make sure that the API supports each.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

will do 🫡

Comment on lines +50 to +56
for _, dir := range []string{"assets", "."} {
for _, ext := range supportedIconExtensions {
candidate := filepath.Join(dir, "icon"+ext)
if _, err := fs.Stat(candidate); err == nil {
return candidate
}
}
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: It looks like the implementation will attempt to find the first image that matches the file extensions and use it when there is no path defined?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yes thats the fallback. it doesnt have to be that way but im worried the assets/icon.png convention is a little strict since the image also has to be named icon


var supportedIconExtensions = []string{".png", ".jpg", ".jpeg", ".gif"}

func resolveIconPath(fs afero.Fs, manifestIcon string) 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: Thoughts on moving this to internal/icon/icon.go or maybe internal/config/icon.go. My preference is the first to avoid cluttering our already messy package config.

Comment on lines +37 to +42
for _, ext := range supportedIconExtensions {
candidate := filepath.Join(wd, "assets", "icon"+ext)
if _, err := os.Stat(candidate); !os.IsNotExist(err) {
sy.Icon = filepath.Join("assets", "icon"+ext)
break
}
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: Since we're using this loop logic in 2 places, I think it would make sense to implement it as a function in internal/icon/icon.go.

@srtaalej
Copy link
Copy Markdown
Contributor Author

srtaalej commented Apr 30, 2026

@mwbrooks

❓ Curious, have you tested this on both Deno/ROSI and Bolt using multiple image formats for each?

i have tested with both Deno and Bolt - will update once all format types are tested!

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.

2 participants