Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion scripts/bash/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -372,4 +372,3 @@ except Exception:
# Callers running under set -e should use: TEMPLATE=$(resolve_template ...) || true
return 1
}

10 changes: 10 additions & 0 deletions scripts/bash/create-new-feature.sh
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ fi

FEATURE_DIR="$SPECS_DIR/$BRANCH_NAME"
SPEC_FILE="$FEATURE_DIR/spec.md"
FEATURE_METADATA_FILE="$REPO_ROOT/.specify/feature.json"

if [ "$DRY_RUN" != true ]; then
if [ "$HAS_GIT" = true ]; then
Expand Down Expand Up @@ -366,6 +367,7 @@ if [ "$DRY_RUN" != true ]; then
fi

mkdir -p "$FEATURE_DIR"
mkdir -p "$(dirname "$FEATURE_METADATA_FILE")"

if [ ! -f "$SPEC_FILE" ]; then
TEMPLATE=$(resolve_template "spec-template" "$REPO_ROOT") || true
Expand All @@ -377,6 +379,14 @@ if [ "$DRY_RUN" != true ]; then
fi
fi

if command -v jq >/dev/null 2>&1; then
jq -cn \
--arg feature_directory "specs/$BRANCH_NAME" \
'{feature_directory:$feature_directory}' >"$FEATURE_METADATA_FILE"
else
printf '{"feature_directory":"%s"}\n' "$(json_escape "specs/$BRANCH_NAME")" >"$FEATURE_METADATA_FILE"
fi

# Inform the user how to persist the feature variable in their own shell
printf '# To persist: export SPECIFY_FEATURE=%q\n' "$BRANCH_NAME" >&2
fi
Expand Down
1 change: 0 additions & 1 deletion scripts/powershell/common.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -353,4 +353,3 @@ function Resolve-Template {

return $null
}

6 changes: 6 additions & 0 deletions scripts/powershell/create-new-feature.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ if ($branchName.Length -gt $maxBranchLength) {

$featureDir = Join-Path $specsDir $branchName
$specFile = Join-Path $featureDir 'spec.md'
$featureMetadataFile = Join-Path $repoRoot '.specify/feature.json'

if (-not $DryRun) {
if ($hasGit) {
Expand Down Expand Up @@ -346,6 +347,7 @@ if (-not $DryRun) {
}

New-Item -ItemType Directory -Path $featureDir -Force | Out-Null
New-Item -ItemType Directory -Path (Split-Path $featureMetadataFile -Parent) -Force | Out-Null

if (-not (Test-Path -PathType Leaf $specFile)) {
$template = Resolve-Template -TemplateName 'spec-template' -RepoRoot $repoRoot
Expand All @@ -356,6 +358,10 @@ if (-not $DryRun) {
}
}

[PSCustomObject]@{
feature_directory = "specs/$branchName"
} | ConvertTo-Json -Compress | Set-Content -Path $featureMetadataFile -Encoding utf8

# Set the SPECIFY_FEATURE environment variable for the current session
$env:SPECIFY_FEATURE = $branchName
}
Expand Down
31 changes: 31 additions & 0 deletions tests/test_timestamp_branches.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,19 @@ def test_json_output_keys(self, git_repo: Path):
assert key in data, f"missing {key} in JSON: {data}"
assert re.match(r"^\d{8}-\d{6}$", data["FEATURE_NUM"])

def test_writes_feature_metadata_file(self, git_repo: Path):
"""Feature creation persists .specify/feature.json with the created spec dir."""
import json

result = run_script(git_repo, "--json", "--short-name", "meta-test", "Metadata test")
assert result.returncode == 0, result.stderr
data = json.loads(result.stdout)

metadata_file = git_repo / ".specify" / "feature.json"
assert metadata_file.exists(), "feature metadata file was not created"
metadata = json.loads(metadata_file.read_text(encoding="utf-8"))
assert metadata == {"feature_directory": f"specs/{data['BRANCH_NAME']}"}

def test_long_name_truncation(self, git_repo: Path):
"""Test 5: Long branch name is truncated to <= 244 chars."""
long_name = "a-" * 150 + "end"
Expand Down Expand Up @@ -644,6 +657,12 @@ def test_powershell_supports_allow_existing_branch_flag(self):
# Ensure the flag is referenced in script logic, not just declared
assert "AllowExistingBranch" in contents.replace("-AllowExistingBranch", "")

def test_powershell_persists_feature_metadata(self):
"""Static guard: PS script writes .specify/feature.json."""
contents = CREATE_FEATURE_PS.read_text(encoding="utf-8")
assert "feature_directory = \"specs/$branchName\"" in contents
assert "feature.json" in contents

def test_powershell_surfaces_checkout_errors(self):
"""Static guard: PS script preserves checkout stderr on existing-branch failures."""
contents = CREATE_FEATURE_PS.read_text(encoding="utf-8")
Expand Down Expand Up @@ -993,7 +1012,19 @@ def test_ps_dry_run_json_absent_without_flag(self, ps_git_repo: Path):
assert result.returncode == 0, result.stderr
data = json.loads(result.stdout)
assert "DRY_RUN" not in data, f"DRY_RUN should not be in normal JSON: {data}"

def test_ps_writes_feature_metadata_file(self, ps_git_repo: Path):
"""PowerShell create script persists .specify/feature.json."""
result = run_ps_script(
ps_git_repo, "-Json", "-ShortName", "ps-meta", "PowerShell metadata"
)
assert result.returncode == 0, result.stderr
data = json.loads(result.stdout)

metadata_file = ps_git_repo / ".specify" / "feature.json"
assert metadata_file.exists(), "feature metadata file was not created"
metadata = json.loads(metadata_file.read_text(encoding="utf-8-sig"))
assert metadata == {"feature_directory": f"specs/{data['BRANCH_NAME']}"}

# ── GIT_BRANCH_NAME Override Tests ──────────────────────────────────────────

Expand Down