Skip to content

feat: add mk env for generating .env files#46

Merged
vitali87 merged 2 commits into
mainfrom
feat/mk-env
Mar 28, 2026
Merged

feat: add mk env for generating .env files#46
vitali87 merged 2 commits into
mainfrom
feat/mk-env

Conversation

@vitali87

Copy link
Copy Markdown
Owner

Summary

  • Add env entity to u7 mk for generating .env files from .env.example or custom templates
  • u7 mk env copies .env.example to .env with existence checks
  • u7 mk env from <template> [to <output>] supports custom template and output paths
  • Includes dry-run support, file existence guards, tab completion, and 7 new tests

Test plan

  • u7 mk env copies .env.example to .env
  • Errors when .env already exists
  • Errors when template file is missing
  • u7 mk env from <template> uses custom template
  • u7 mk env from <template> to <output> uses custom output path
  • Dry-run prints command without creating file
  • All tests pass

@vitali87

Copy link
Copy Markdown
Owner Author

@greptile

@vitali87

Copy link
Copy Markdown
Owner Author

/gemini review

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

Copy link
Copy Markdown

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 the mk env command to generate environment files from templates, including shell completions and tests. The review feedback points out that the implementation for the sh ports command is missing from the PR despite being included in the completions and test files. Additionally, there are suggestions to improve the test suite's robustness by ensuring proper file cleanup and making tests more self-contained.

Comment thread lib/completions.sh Outdated
Comment thread test.sh
echo -e "${RED}✗${NC} mk env copies .env.example to .env (file not created)"
((FAILED++))
fi
rm -f .env

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

To make tests more robust and independent, each test should clean up all the files it creates. This test creates .env.example but only removes .env. The next test then implicitly depends on this leftover file. Please clean up .env.example here as well. You will then need to create it in the next test block.

Suggested change
rm -f .env
rm -f .env .env.example

Comment thread test.sh
rm -f .env

# Test: mk env errors when .env already exists
echo "existing" > .env

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

To make this test self-contained, it should create its own prerequisite files. Since the previous test should now be cleaning up .env.example, you need to create it here.

Suggested change
echo "existing" > .env
echo "DB_HOST=localhost" > .env.example
echo "existing" > .env

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

Copy link
Copy Markdown

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 new mk env command to generate .env files from templates, including shell completions and comprehensive tests. Feedback focuses on the fragile argument parsing in lib/make.sh, which should be refactored into a loop to support flexible argument ordering. Additionally, error messages should be redirected to stderr. The PR also includes completions and tests for a sh ports command that appears to be missing its core implementation, leading to potential test failures and unrelated code changes that should be separated.

Comment thread lib/completions.sh Outdated
Comment thread lib/make.sh
Comment on lines +177 to +190
if [[ "$1" == "from" ]]; then
if [[ -z "$2" ]]; then
echo "Usage: u7 mk env from <template> [to <output>]"
return 1
fi
template="$2"
if [[ "$3" == "to" ]]; then
if [[ -z "$4" ]]; then
echo "Usage: u7 mk env from <template> to <output>"
return 1
fi
output="$4"
fi
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The current argument parsing for mk env is not robust. It only handles a fixed order of arguments (from then to) and will ignore arguments if they don't appear in this exact sequence (e.g., u7 mk env to .env.local will be ignored). This doesn't match the flexibility suggested by the help text: env [from <template>] [to <output>].

To handle keyword arguments correctly, it's better to process them in a loop. This makes the command more user-friendly and less prone to errors. I've also updated the error messages to print to stderr, which is a best practice.

      while [[ $# -gt 0 ]]; do
        case "$1" in
          from)
            if [[ -z "$2" ]]; then
              echo "Usage: u7 mk env from <template> [to <output>]" >&2
              return 1
            fi
            template="$2"
            shift 2
            ;;
          to)
            if [[ -z "$2" ]]; then
              echo "Usage: u7 mk env [from <template>] to <output>" >&2
              return 1
            fi
            output="$2"
            shift 2
            ;;
          *)
            echo "Error: Unknown argument '$1' for 'mk env'" >&2
            echo "Usage: u7 mk env [from <template>] [to <output>]" >&2
            return 1
            ;;
        esac
      done

Comment thread test.sh
Comment on lines +954 to +977
# Test: sh ports lists listening ports
result=$(u7 sh ports 2>&1)
if [[ $? -eq 0 ]]; then
echo -e "${GREEN}✓${NC} sh ports runs without error"
((PASSED++))
else
echo -e "${RED}✗${NC} sh ports runs without error"
echo " Got: $result"
((FAILED++))
fi

# Test: sh ports shows usage on invalid arg
result=$(u7 sh ports badarg 2>&1)
assert_contains "sh ports rejects invalid arg" "Usage:" "$result"

# Test: sh ports match requires pattern
result=$(u7 sh ports match 2>&1)
assert_contains "sh ports match requires pattern" "Usage:" "$result"

# Test: sh ports match filters output (may return nothing, just check it runs)
result=$(u7 sh ports match ssh 2>&1)
echo -e "${GREEN}✓${NC} sh ports match runs without crash"
((PASSED++))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

These tests for sh ports are for a feature that is not implemented in this PR (the ports entity is missing from lib/show.sh). As a result, these tests will fail.

This feature is also unrelated to the main goal of the PR (mk env). It's a good practice to submit unrelated features in separate pull requests. Please remove these tests and other ports-related code from this branch.

Comment thread lib/make.sh
Comment on lines +192 to +198
if [[ ! -f "$template" ]]; then
echo "Error: template '$template' not found"
return 1
fi
if [[ -f "$output" ]]; then
echo "Error: '$output' already exists"
return 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

It's a good practice to redirect error messages to standard error (stderr). This separates diagnostic messages from the script's main output, which is helpful for scripting and redirection.

Suggested change
if [[ ! -f "$template" ]]; then
echo "Error: template '$template' not found"
return 1
fi
if [[ -f "$output" ]]; then
echo "Error: '$output' already exists"
return 1
if [[ ! -f "$template" ]]; then
echo "Error: template '$template' not found" >&2
return 1
fi
if [[ -f "$output" ]]; then
echo "Error: '$output' already exists" >&2
return 1
fi

@greptile-apps

greptile-apps Bot commented Mar 27, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds a u7 mk env subcommand that copies .env.example (or a custom template) to .env, with file-existence guards, dry-run support, and tab completion. The implementation is clean and consistent with the rest of the make.sh module.

  • lib/make.sh: New env entity correctly checks for missing template and pre-existing output before calling _u7_exec cp; argument parsing for from <template> [to <output>] works as expected.
  • lib/completions.sh: env added to mk entity list and from surfaced as its first-level argument; a bonus fix adds ports completion under show. File-path completion after from is not wired up.
  • test.sh: 7 focused tests cover the happy path, both error guards, custom template/output, and dry-run behaviour; all run safely inside a TEST_DIR temp directory.
  • Minor polish items: the help text renders [to <output>] as if it is independent of [from <template>] (it is not), and the command produces no success message on copy (unlike u7 mk copy).

Confidence Score: 5/5

Safe to merge — all remaining findings are P2 style/UX suggestions with no correctness impact.

The core logic is correct: template existence is checked, output clobbering is prevented, dry-run is respected, and the test suite covers all documented scenarios. The three open comments are purely cosmetic (help text wording, missing success echo, incomplete tab completion after from) and do not affect runtime behaviour.

No files require special attention; lib/make.sh line 235 has a minor help-text wording issue worth fixing before the next docs pass.

Important Files Changed

Filename Overview
lib/make.sh Adds env entity with correct template/output guards, dry-run support, and argument parsing; help text syntax is slightly misleading and there is no success message on copy.
lib/completions.sh Adds env and ports to completion lists correctly; file-path completion after from keyword is missing for the mk env entity.
test.sh Adds 7 well-structured tests for mk env (default, exists-guard, missing-template, custom template, custom output, dry-run) and 4 tests for sh ports; all run inside an isolated TEST_DIR.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A([u7 mk env ...]) --> B{first arg == 'from'?}
    B -- yes --> C{second arg empty?}
    C -- yes --> D[print Usage & return 1]
    C -- no --> E[template = arg2]
    E --> F{third arg == 'to'?}
    F -- yes --> G{fourth arg empty?}
    G -- yes --> H[print Usage & return 1]
    G -- no --> I[output = arg4]
    F -- no --> J[output = .env]
    I --> K
    J --> K
    B -- no --> L[template = .env.example
output = .env]
    L --> K{template file exists?}
    K -- no --> M[Error: template not found
return 1]
    K -- yes --> N{output file exists?}
    N -- yes --> O[Error: output already exists
return 1]
    N -- no --> P[_u7_exec cp template output]
    P --> Q{dry-run mode?}
    Q -- yes --> R[echo dry-run command]
    Q -- no --> S[copy file to disk]
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: lib/make.sh
Line: 235

Comment:
**Misleading syntax in help text**

The current help text implies `[to <output>]` can be used independently of `[from <template>]`:

```
env [from <template>] [to <output>]
```

However, in the implementation `to <output>` is only parsed when `from <template>` is already present — calling `u7 mk env to custom.env` silently ignores `to custom.env` and falls back to the default `.env` output. The help text should reflect the actual nested-optional structure:

```suggestion
  env [from <template> [to <output>]]   Generate .env from .env.example or a custom template
```

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

---

This is a comment left during a code review.
Path: lib/completions.sh
Line: 48

Comment:
**No file-path completion after `from` keyword**

The current completion only suggests `from` as the first argument after `env`. Once the user types `u7 mk env from <TAB>`, there is no further completion, so the template file path cannot be tab-completed. Adding a `_filedir` fallback when no keyword matches — similar to how `copy|link` already does — would improve usability:

```suggestion
        env) COMPREPLY=($(compgen -W "from" -- "$cur")); [[ -z "$COMPREPLY" ]] && _filedir ;;
```

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

---

This is a comment left during a code review.
Path: lib/make.sh
Line: 200

Comment:
**No success feedback message**

The `cp` command produces no output on success, leaving the user with no confirmation that `.env` was created. Other similar entities (e.g., `copy`, `template`) print a success line. Adding one here would keep the UX consistent:

```suggestion
      _u7_exec cp "$template" "$output" && echo "Created '$output' from '$template'"
```

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

Reviews (1): Last reviewed commit: "feat: add mk env entity for generating ...." | Re-trigger Greptile

Comment thread lib/make.sh
archive <output> from <files...> Create archive from <files...> to <output>
clone <repo> [to <directory>] Git clone a repository
template <python|node|bash|web> <name> Scaffold a project structure
env [from <template>] [to <output>] Generate .env from .env.example or a custom template

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Misleading syntax in help text

The current help text implies [to <output>] can be used independently of [from <template>]:

env [from <template>] [to <output>]

However, in the implementation to <output> is only parsed when from <template> is already present — calling u7 mk env to custom.env silently ignores to custom.env and falls back to the default .env output. The help text should reflect the actual nested-optional structure:

Suggested change
env [from <template>] [to <output>] Generate .env from .env.example or a custom template
env [from <template> [to <output>]] Generate .env from .env.example or a custom template
Prompt To Fix With AI
This is a comment left during a code review.
Path: lib/make.sh
Line: 235

Comment:
**Misleading syntax in help text**

The current help text implies `[to <output>]` can be used independently of `[from <template>]`:

```
env [from <template>] [to <output>]
```

However, in the implementation `to <output>` is only parsed when `from <template>` is already present — calling `u7 mk env to custom.env` silently ignores `to custom.env` and falls back to the default `.env` output. The help text should reflect the actual nested-optional structure:

```suggestion
  env [from <template> [to <output>]]   Generate .env from .env.example or a custom template
```

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

Comment thread lib/completions.sh
make|mk)
case "$entity" in
copy|link) _filedir ;;
env) COMPREPLY=($(compgen -W "from" -- "$cur")) ;;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 No file-path completion after from keyword

The current completion only suggests from as the first argument after env. Once the user types u7 mk env from <TAB>, there is no further completion, so the template file path cannot be tab-completed. Adding a _filedir fallback when no keyword matches — similar to how copy|link already does — would improve usability:

Suggested change
env) COMPREPLY=($(compgen -W "from" -- "$cur")) ;;
env) COMPREPLY=($(compgen -W "from" -- "$cur")); [[ -z "$COMPREPLY" ]] && _filedir ;;
Prompt To Fix With AI
This is a comment left during a code review.
Path: lib/completions.sh
Line: 48

Comment:
**No file-path completion after `from` keyword**

The current completion only suggests `from` as the first argument after `env`. Once the user types `u7 mk env from <TAB>`, there is no further completion, so the template file path cannot be tab-completed. Adding a `_filedir` fallback when no keyword matches — similar to how `copy|link` already does — would improve usability:

```suggestion
        env) COMPREPLY=($(compgen -W "from" -- "$cur")); [[ -z "$COMPREPLY" ]] && _filedir ;;
```

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

Comment thread lib/make.sh
echo "Error: '$output' already exists"
return 1
fi
_u7_exec cp "$template" "$output"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 No success feedback message

The cp command produces no output on success, leaving the user with no confirmation that .env was created. Other similar entities (e.g., copy, template) print a success line. Adding one here would keep the UX consistent:

Suggested change
_u7_exec cp "$template" "$output"
_u7_exec cp "$template" "$output" && echo "Created '$output' from '$template'"
Prompt To Fix With AI
This is a comment left during a code review.
Path: lib/make.sh
Line: 200

Comment:
**No success feedback message**

The `cp` command produces no output on success, leaving the user with no confirmation that `.env` was created. Other similar entities (e.g., `copy`, `template`) print a success line. Adding one here would keep the UX consistent:

```suggestion
      _u7_exec cp "$template" "$output" && echo "Created '$output' from '$template'"
```

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

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@vitali87 vitali87 merged commit f0d9939 into main Mar 28, 2026
2 checks passed
@vitali87 vitali87 deleted the feat/mk-env branch March 28, 2026 21:20
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