Skip to content

feat: add mk template for scaffolding project structures#40

Merged
vitali87 merged 7 commits intomainfrom
feat/mk-template
Mar 27, 2026
Merged

feat: add mk template for scaffolding project structures#40
vitali87 merged 7 commits intomainfrom
feat/mk-template

Conversation

@vitali87
Copy link
Owner

Summary

  • mk template python <name> — creates src/, tests/, main.py, README
  • mk template node <name> — creates src/, test/, package.json, index.js
  • mk template bash <name> — creates main.sh with shebang and set flags
  • mk template web <name> — creates index.html, css/, js/
  • Validates arguments, supports dry-run via _u7_exec for mkdir

Test plan

  • u7 mk template python myapp creates correct structure
  • u7 mk template node mynode creates package.json
  • u7 mk template without args shows usage
  • Run full test suite

@vitali87
Copy link
Owner Author

@greptile

@vitali87
Copy link
Owner Author

/gemini review

@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant new feature to the u7 utility: a mk template command. This command allows users to quickly scaffold new project structures for Python, Node.js, Bash, and Web development, providing a standardized starting point with essential files and directories. The implementation includes robust argument validation and integrates with existing dry-run capabilities, enhancing developer productivity by automating initial project setup.

Highlights

  • New mk template command: Introduced a new mk template command to scaffold various project structures.
  • Python Project Template: The mk template python <name> command now creates src/, tests/, main.py, and README.md for Python projects.
  • Node.js Project Template: The mk template node <name> command now creates src/, test/, package.json, and index.js for Node.js projects.
  • Bash Script Template: The mk template bash <name> command now creates main.sh with a shebang and set flags for Bash projects.
  • Web Project Template: The mk template web <name> command now creates index.html, css/, and js/ directories for web projects.
  • Argument Validation and Dry-Run Support: The mk template command includes argument validation and supports dry-run functionality via _u7_exec for directory creation.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a useful mk template command for scaffolding new projects. The implementation is straightforward, but there are a few areas for improvement. My main concerns are around input sanitization for the project name, which can lead to broken file content or a Cross-Site Scripting vulnerability in the node and web templates respectively. Additionally, the test coverage should be expanded to include all template types and verify all generated files to make the feature more robust. I've added specific suggestions to address these points.

utility.sh Outdated
node)
_u7_exec mkdir -p "$name/src" "$name/test"
echo "# $name" > "$name/README.md"
echo '{"name": "'"$name"'", "version": "0.1.0", "main": "src/index.js"}' > "$name/package.json"

Choose a reason for hiding this comment

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

high

The project name is directly embedded into the package.json string. If the name contains a double quote ("), it will result in invalid JSON. Consider escaping the name to prevent this.

Suggested change
echo '{"name": "'"$name"'", "version": "0.1.0", "main": "src/index.js"}' > "$name/package.json"
echo '{"name": "'"${name//\"/\\\"}"'", "version": "0.1.0", "main": "src/index.js"}' > "$name/package.json"

utility.sh Outdated
;;
web)
_u7_exec mkdir -p "$name/css" "$name/js"
echo "<!DOCTYPE html><html><head><title>$name</title><link rel=\"stylesheet\" href=\"css/style.css\"></head><body><h1>$name</h1><script src=\"js/main.js\"></script></body></html>" > "$name/index.html"

Choose a reason for hiding this comment

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

high

The project name is directly embedded into the HTML content without escaping. This creates a Cross-Site Scripting (XSS) vulnerability. If a project name contains HTML tags (e.g., <script>...), they will be rendered by the browser.

You should HTML-escape the $name variable before using it. A simple approach in bash is to replace special characters:

local name_html_escaped="$name"
name_html_escaped="${name_html_escaped//&/&amp;}"
name_html_escaped="${name_html_escaped//</&lt;}"
name_html_escaped="${name_html_escaped//>/&gt;}"
# ... and then use $name_html_escaped in the echo command.

utility.sh Outdated
touch "$name/css/style.css" "$name/js/main.js"
echo "Created Web project: $name"
;;
*) echo "Usage: u7 mk template <python|node|bash|web> <project-name>" ; return 1 ;;

Choose a reason for hiding this comment

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

medium

The usage message here is identical to the one on line 533. This duplication can make maintenance harder. To improve clarity, consider making this error message more specific to an invalid template type, distinguishing it from the missing-argument error.

Suggested change
*) echo "Usage: u7 mk template <python|node|bash|web> <project-name>" ; return 1 ;;
*) echo "Error: Invalid template type '$tmpl'. Must be one of python, node, bash, web." ; return 1 ;;

test.sh Outdated
# Test: mk template python
cd "$TEST_DIR"
u7 mk template python myapp >/dev/null 2>&1
if [[ -f "myapp/src/main.py" && -f "myapp/README.md" && -f "myapp/tests/__init__.py" ]]; then

Choose a reason for hiding this comment

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

medium

This test for the Python template is incomplete. The scaffolding logic creates src/__init__.py, but this check doesn't verify its existence. Adding this check will make the test more thorough and prevent future regressions.

Suggested change
if [[ -f "myapp/src/main.py" && -f "myapp/README.md" && -f "myapp/tests/__init__.py" ]]; then
if [[ -f "myapp/src/main.py" && -f "myapp/README.md" && -f "myapp/tests/__init__.py" && -f "myapp/src/__init__.py" ]]; then


# Test: mk template node
u7 mk template node mynode >/dev/null 2>&1
if [[ -f "mynode/package.json" && -f "mynode/src/index.js" ]]; then

Choose a reason for hiding this comment

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

medium

This test for the Node.js template is incomplete. The scaffolding logic also creates a README.md file and a test directory, but this test doesn't verify their existence. Expanding the check will make the test more robust.

Suggested change
if [[ -f "mynode/package.json" && -f "mynode/src/index.js" ]]; then
if [[ -f "mynode/package.json" && -f "mynode/src/index.js" && -f "mynode/README.md" && -d "mynode/test" ]]; then

@greptile-apps
Copy link

greptile-apps bot commented Mar 24, 2026

Greptile Summary

This PR adds a mk template subcommand to utility.sh that scaffolds four project types (Python, Node, Bash, Web), along with a matching test suite. The implementation is well-structured and addresses most previously raised concerns: input is validated against ^[a-zA-Z0-9_-]+$, an existing-directory guard prevents accidental overwrites, dry-run mode exits early with a single message, and jq --arg is used for safe JSON generation in the Node template.

Key observations:

  • The input validation regex allows project names starting with - (e.g., -myapp), which could be misinterpreted as flags by some tools not using -- separators.
  • The HTML escaping variables (escaped_name) in the web template are now dead code — the input validation already blocks all characters they would catch.
  • The web template test verifies that css/ and js/ are directories but does not assert that style.css and main.js were actually created, leaving a small regression gap.
  • All four template types now have test coverage, including error paths for missing args, existing directories, and invalid names.

Confidence Score: 4/5

  • Safe to merge; all remaining findings are minor style improvements with no impact on correctness or security.
  • The core logic is correct and well-guarded. Previous critical issues (dry-run bypass, format-string injection, path traversal, missing jq guard) have all been addressed in this iteration. The three remaining findings are low-severity: one test coverage gap, one dead-code cleanup, and one defensive input constraint suggestion. None block functionality.
  • No files require special attention; all findings are minor suggestions.

Important Files Changed

Filename Overview
utility.sh Adds the template subcommand to _u7_make() with input validation (alphanumeric+hyphen/underscore regex, existing-dir guard, dry-run early return), four template types (python, node, bash, web), and uses jq --arg for safe JSON generation. Minor issues: the validation regex allows names starting with -, and the HTML-escaping variables on lines 573-574 are dead code now that all special characters are blocked by the input guard.
test.sh Adds tests for all four template types plus error-path coverage (no args, existing dir, special chars in name). The web template test only checks for directory existence of css/ and js/ rather than the actual style.css and main.js files, leaving a small regression gap.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["u7 mk template tmpl name"] --> B{tmpl or name empty?}
    B -- yes --> C["echo Usage; return 1"]
    B -- no --> D{name is alphanumeric?}
    D -- no --> E["Error: alphanumerics only; return 1"]
    D -- yes --> F{directory already exists?}
    F -- yes --> G["Error: already exists; return 1"]
    F -- no --> H{DRY_RUN == 1?}
    H -- yes --> I["echo dry-run message; return 0"]
    H -- no --> J{template type?}
    J -- python --> K["mkdir src/ tests/ \n README.md, main.py, __init__.py x2"]
    J -- node --> L["_u7_require jq \n mkdir src/ test/ \n package.json via jq \n index.js, README.md"]
    J -- bash --> M["mkdir name/ \n README.md \n printf main.sh \n chmod +x"]
    J -- web --> N["mkdir css/ js/ \n index.html \n touch style.css, main.js"]
    J -- other --> O["Error: Unknown template; return 1"]
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: test.sh
Line: 872-879

Comment:
**Web template test missing file-level assertions**

The test verifies that `css` and `js` are directories but never checks that `css/style.css` or `js/main.js` were actually created. The template uses `touch "$name/css/style.css" "$name/js/main.js"`, so a regression that removes those `touch` calls would still let this test pass.

```suggestion
u7 mk template web myweb >/dev/null 2>&1
if [[ -f "myweb/index.html" && -f "myweb/css/style.css" && -f "myweb/js/main.js" ]]; then
    echo -e "${GREEN}✓${NC} mk template web works"
    ((PASSED++))
else
    echo -e "${RED}✗${NC} mk template web failed"
    ((FAILED++))
fi
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: utility.sh
Line: 536-538

Comment:
**Regex permits names starting with `-`**

The pattern `^[a-zA-Z0-9_-]+$` allows project names that begin with a hyphen (e.g., `-myapp`, `--help`). Although most path-based operations are safe once a `/` is present in the full path, some downstream tools called with a bare `$name` (e.g., tools that don't use `--`) could misinterpret it as a flag. Anchoring the first character to an alphanumeric avoids the ambiguity:

```suggestion
      if [[ ! "$name" =~ ^[a-zA-Z0-9][a-zA-Z0-9_-]*$ ]]; then
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: utility.sh
Line: 573-574

Comment:
**HTML escaping is now dead code**

The `<``&lt;` and `>``&gt;` substitutions on these two lines can never trigger because the input validation on line 536 (`^[a-zA-Z0-9_-]+$`) already rejects any name containing `<`, `>`, or `&`. The `escaped_name` variable is identical to `$name` in every reachable code path, so the variable and both assignments can be removed:

```suggestion
          echo "<!DOCTYPE html><html><head><title>$name</title><link rel=\"stylesheet\" href=\"css/style.css\"></head><body><h1>$name</h1><script src=\"js/main.js\"></script></body></html>" > "$name/index.html"
```

Removing the dead escaping also makes it immediately obvious that the name is safe to embed directly, thanks to the earlier validation guard.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (6): Last reviewed commit: "fix: validate project name to alphanumer..." | Re-trigger Greptile

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a useful mk template command for scaffolding new projects. The implementation is a good start, but there are a couple of critical issues with how project names are handled when generating files, which can lead to corrupted or invalid files if the name contains special characters. I've left comments on the specific lines in utility.sh. Additionally, the test suite for this new feature is incomplete; it's missing tests for the bash and web templates, and the existing tests could be more thorough. Please see my comment in test.sh for details.

utility.sh Outdated
node)
_u7_exec mkdir -p "$name/src" "$name/test"
echo "# $name" > "$name/README.md"
echo '{"name": "'"$name"'", "version": "0.1.0", "main": "src/index.js"}' > "$name/package.json"

Choose a reason for hiding this comment

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

high

The project name is not escaped when being inserted into package.json. If the project name contains a double quote, it will result in an invalid JSON file. You should use a tool like jq to safely generate the JSON. Since jq seems to be a dependency for other parts of the script, you could use it like this: jq -n --arg name "$name" '{name: $name, version: "0.1.0", main: "src/index.js"}' > "$name/package.json"

utility.sh Outdated
;;
web)
_u7_exec mkdir -p "$name/css" "$name/js"
echo "<!DOCTYPE html><html><head><title>$name</title><link rel=\"stylesheet\" href=\"css/style.css\"></head><body><h1>$name</h1><script src=\"js/main.js\"></script></body></html>" > "$name/index.html"

Choose a reason for hiding this comment

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

high

The project name is not escaped when being inserted into index.html. If the project name contains HTML special characters like < or >, it will result in an invalid or malformed HTML file. The project name should be HTML-escaped before being embedded in the title and body. You can use sed for basic escaping, for example: escaped_name=$(printf '%s' "$name" | sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g;')

Comment on lines +841 to +864
# Test: mk template python
cd "$TEST_DIR"
u7 mk template python myapp >/dev/null 2>&1
if [[ -f "myapp/src/main.py" && -f "myapp/README.md" && -f "myapp/tests/__init__.py" ]]; then
echo -e "${GREEN}✓${NC} mk template python works"
((PASSED++))
else
echo -e "${RED}✗${NC} mk template python failed"
((FAILED++))
fi

# Test: mk template node
u7 mk template node mynode >/dev/null 2>&1
if [[ -f "mynode/package.json" && -f "mynode/src/index.js" ]]; then
echo -e "${GREEN}✓${NC} mk template node works"
((PASSED++))
else
echo -e "${RED}✗${NC} mk template node failed"
((FAILED++))
fi

# Test: mk template requires args
result=$(u7 mk template 2>&1)
assert_contains "mk template requires args" "Usage:" "$result"

Choose a reason for hiding this comment

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

medium

The test coverage for the new mk template feature is incomplete and could be improved:

  • Tests for the bash and web templates are missing.
  • The existing tests for python and node only check for file existence. They should also verify file contents to ensure the templates are generated correctly (e.g., check for valid JSON in package.json, check for shebangs in scripts).
  • There are no tests for project names containing spaces or special characters, which would have helped catch the injection bugs in utility.sh.

@vitali87
Copy link
Owner Author

@greptile

@vitali87
Copy link
Owner Author

@greptile

Comment on lines +569 to +571
local escaped_name="${name//</&lt;}"
escaped_name="${escaped_name//>/&gt;}"
echo "<!DOCTYPE html><html><head><title>$escaped_name</title><link rel=\"stylesheet\" href=\"css/style.css\"></head><body><h1>$escaped_name</h1><script src=\"js/main.js\"></script></body></html>" > "$name/index.html"
Copy link

Choose a reason for hiding this comment

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

P1 & not escaped in HTML template (incomplete fix)

The previous fix added <&lt; and >&gt; escaping, but &&amp; is still missing. This means a project name like foo & bar will produce:

<title>foo & bar</title>
<h1>foo & bar</h1>

A bare & not followed by a valid entity reference is technically invalid HTML and can cause browsers to issue parse warnings. Additionally, the & substitution must happen first — if it were added after the current </> substitutions, the &lt; and &gt; sequences already written would get double-encoded into &amp;lt; / &amp;gt;.

Suggested change
local escaped_name="${name//</&lt;}"
escaped_name="${escaped_name//>/&gt;}"
echo "<!DOCTYPE html><html><head><title>$escaped_name</title><link rel=\"stylesheet\" href=\"css/style.css\"></head><body><h1>$escaped_name</h1><script src=\"js/main.js\"></script></body></html>" > "$name/index.html"
local escaped_name="${name//&/&amp;}"
escaped_name="${escaped_name//</&lt;}"
escaped_name="${escaped_name//>/&gt;}"
Prompt To Fix With AI
This is a comment left during a code review.
Path: utility.sh
Line: 569-571

Comment:
**`&` not escaped in HTML template (incomplete fix)**

The previous fix added `<``&lt;` and `>``&gt;` escaping, but `&``&amp;` is still missing. This means a project name like `foo & bar` will produce:

```html
<title>foo & bar</title>
<h1>foo & bar</h1>
```

A bare `&` not followed by a valid entity reference is technically invalid HTML and can cause browsers to issue parse warnings. Additionally, the `&` substitution **must happen first** — if it were added after the current `<`/`>` substitutions, the `&lt;` and `&gt;` sequences already written would get double-encoded into `&amp;lt;` / `&amp;gt;`.

```suggestion
          local escaped_name="${name//&/&amp;}"
          escaped_name="${escaped_name//</&lt;}"
          escaped_name="${escaped_name//>/&gt;}"
```

How can I resolve this? If you propose a fix, please make it concise.

@vitali87
Copy link
Owner Author

@greptile

@vitali87
Copy link
Owner Author

@greptile

@vitali87
Copy link
Owner Author

@greptile

Comment on lines +536 to +538
if [[ ! "$name" =~ ^[a-zA-Z0-9_-]+$ ]]; then
echo "Error: project name must contain only alphanumerics, hyphens, and underscores"
return 1
Copy link

Choose a reason for hiding this comment

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

P2 Regex permits names starting with -

The pattern ^[a-zA-Z0-9_-]+$ allows project names that begin with a hyphen (e.g., -myapp, --help). Although most path-based operations are safe once a / is present in the full path, some downstream tools called with a bare $name (e.g., tools that don't use --) could misinterpret it as a flag. Anchoring the first character to an alphanumeric avoids the ambiguity:

Suggested change
if [[ ! "$name" =~ ^[a-zA-Z0-9_-]+$ ]]; then
echo "Error: project name must contain only alphanumerics, hyphens, and underscores"
return 1
if [[ ! "$name" =~ ^[a-zA-Z0-9][a-zA-Z0-9_-]*$ ]]; then
Prompt To Fix With AI
This is a comment left during a code review.
Path: utility.sh
Line: 536-538

Comment:
**Regex permits names starting with `-`**

The pattern `^[a-zA-Z0-9_-]+$` allows project names that begin with a hyphen (e.g., `-myapp`, `--help`). Although most path-based operations are safe once a `/` is present in the full path, some downstream tools called with a bare `$name` (e.g., tools that don't use `--`) could misinterpret it as a flag. Anchoring the first character to an alphanumeric avoids the ambiguity:

```suggestion
      if [[ ! "$name" =~ ^[a-zA-Z0-9][a-zA-Z0-9_-]*$ ]]; then
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +573 to +574
local escaped_name="${name//</&lt;}"
escaped_name="${escaped_name//>/&gt;}"
Copy link

Choose a reason for hiding this comment

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

P2 HTML escaping is now dead code

The <&lt; and >&gt; substitutions on these two lines can never trigger because the input validation on line 536 (^[a-zA-Z0-9_-]+$) already rejects any name containing <, >, or &. The escaped_name variable is identical to $name in every reachable code path, so the variable and both assignments can be removed:

Suggested change
local escaped_name="${name//</&lt;}"
escaped_name="${escaped_name//>/&gt;}"
echo "<!DOCTYPE html><html><head><title>$name</title><link rel=\"stylesheet\" href=\"css/style.css\"></head><body><h1>$name</h1><script src=\"js/main.js\"></script></body></html>" > "$name/index.html"

Removing the dead escaping also makes it immediately obvious that the name is safe to embed directly, thanks to the earlier validation guard.

Prompt To Fix With AI
This is a comment left during a code review.
Path: utility.sh
Line: 573-574

Comment:
**HTML escaping is now dead code**

The `<``&lt;` and `>``&gt;` substitutions on these two lines can never trigger because the input validation on line 536 (`^[a-zA-Z0-9_-]+$`) already rejects any name containing `<`, `>`, or `&`. The `escaped_name` variable is identical to `$name` in every reachable code path, so the variable and both assignments can be removed:

```suggestion
          echo "<!DOCTYPE html><html><head><title>$name</title><link rel=\"stylesheet\" href=\"css/style.css\"></head><body><h1>$name</h1><script src=\"js/main.js\"></script></body></html>" > "$name/index.html"
```

Removing the dead escaping also makes it immediately obvious that the name is safe to embed directly, thanks to the earlier validation guard.

How can I resolve this? If you propose a fix, please make it concise.

@vitali87 vitali87 merged commit 859911b into main Mar 27, 2026
2 checks passed
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.

1 participant