feat(create): update app name in 'pyproject.toml' and 'package.json'#344
feat(create): update app name in 'pyproject.toml' and 'package.json'#344
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #344 +/- ##
==========================================
+ Coverage 64.73% 64.80% +0.06%
==========================================
Files 212 212
Lines 17805 17827 +22
==========================================
+ Hits 11526 11552 +26
+ Misses 5204 5203 -1
+ Partials 1075 1072 -3 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
zimeg
left a comment
There was a problem hiding this comment.
@srtaalej LGTM! I tested this with the following commands 🧪 ✨
$ ./bin/slack create asdf -t slack-samples/bolt-js-starter-template
$ ./bin/slack create asdf -t slack-samples/bolt-python-assistant-template
I'm not confident in regex in general but let's be optimistic about these finds - the unit tests are appreciated toward the happy path but I'm leaving a comment toward expected coverages 👁️🗨️
mwbrooks
left a comment
There was a problem hiding this comment.
🎉 Super cool @srtaalej! Nice work on putting this together and I'm sorry that I didn't remember package.json also didn't work.
🛠️ I've marked this as Request changes because we will need to improve the package.json regex to avoid replacing multiple names. I've left a few suggestions. I think it's important to add test cases for these, so we don't accidentally introduce a bug in the future.
| // regexReplaceAppNameInPackageJSON replaces the top-level "name" field in a package.json file | ||
| func regexReplaceAppNameInPackageJSON(src []byte, appName string) []byte { | ||
| re := regexp.MustCompile(`(?m)^(\s*"name"\s*:\s*")([^"]*)(")`) | ||
| repl := fmt.Sprintf("${1}%s${3}", appName) | ||
| return re.ReplaceAll(src, []byte(repl)) | ||
| } |
There was a problem hiding this comment.
suggestion(blocking): I think this regex will match all "name" keys in package.json instead of just the top-level "name" field. While other "name" keys are rare, I think that's a little too risky.
A few ideas:
- Update the regex to only match the top-level key
- Not trivial in regex
- This may work where
$2is the name field: (.*\{[^{]*"name"\s*:\s*")([^"]*)(".*)
- Just match the name key with 2 spaces
- The standard indentation used by
npm init - This may work:
(?m)^(\s{2}"name"\s*:\s*")([^"]*)(") - Personally, this is my preference since it feels "safer"
- The standard indentation used by
- Do nothing when we more than one
"name"key exists (better to error on doing nothing than corrupting thepackage.jsonfile)
Here is an example of multiple matches and why we'd need a fix:
There was a problem hiding this comment.
wow thank you for the detailed explanantion! this is super helpful ❤️ looking into this ASAP 🚀
| // regexReplaceAppNameInPyprojectToml replaces the "name" field under the [project] section in a pyproject.toml file | ||
| func regexReplaceAppNameInPyprojectToml(src []byte, appName string) []byte { | ||
| re := regexp.MustCompile(`(\[project\][^\[]*?name\s*=\s*")([^"]*)(")`) | ||
| repl := fmt.Sprintf("${1}%s${3}", appName) | ||
| return re.ReplaceAll(src, []byte(repl)) | ||
| } |
There was a problem hiding this comment.
note: I've confirmed that this will only match name= under the [project] section. Great work @srtaalej!
While we're using teh re.ReplaceAll it should only match "all" names under the project and seems okay.
| } | ||
| } | ||
|
|
||
| func Test_RegexReplaceAppNameInPackageJSON(t *testing.T) { |
There was a problem hiding this comment.
suggestion: Can we add a test where package.json contains 2 name keys. I think this would build confidence in our regex and help avoid regretful regressions later in life by developers unfamiliar with the regex.
We could put the "name" in the config section:
{
"name": "vibrant-butterfly-1234",
"version": "1.0.0",
"description": "A Slack app built with Bolt",
"main": "app.js",
"scripts": {
"start": "node app.js"
},
"dependencies": {
"@slack/bolt": "^4.0.0"
},
"config": {
"name": "local-server-name",
"host": "localhost",
"port": "8080"
}
}| } | ||
| } | ||
|
|
||
| func Test_RegexReplaceAppNameInPyprojectToml(t *testing.T) { |
There was a problem hiding this comment.
suggestion: Likewise, I think we should add an extra name = under another section to make sure we never replace other name keys.
An example could be:
[project]
name = "vibrant-butterfly-1234"
version = "0.1.0"
requires-python = ">=3.9"
dependencies = [
"slack-sdk==3.40.0",
"slack-bolt==1.27.0",
"slack-cli-hooks<1.0.0",
]
[tool.ruff]
[tool.ruff.lint]
[tool.ruff.format]
[tool.pytest.ini_options]
testpaths = ["tests"]
[project.scripts]
name = "my_package.name:main_function"
| //go:embed package.json | ||
| var PackageJSON []byte | ||
|
|
||
| //go:embed package-app-name.json | ||
| var PackageJSONAppName []byte | ||
|
|
||
| //go:embed pyproject.toml | ||
| var PyprojectTOML []byte | ||
|
|
||
| //go:embed pyproject-app-name.toml | ||
| var PyprojectTOMLAppName []byte |
There was a problem hiding this comment.
praise: Great use of the embeds to keep test data clean and easy to maintain!
Co-authored-by: Eden Zimbelman <eden.zimbelman@salesforce.com>
Co-authored-by: Eden Zimbelman <eden.zimbelman@salesforce.com>
Changelog
The
createcommand now updates the app name inpackage.jsonandpyproject.tomlproject files.Summary
This PR extends UpdateDefaultProjectFiles to also replace the app name in package.json and pyproject.toml when creating a new project
Requirements