diff --git a/.github/stack.md b/.github/stack.md new file mode 100644 index 0000000..96be1b2 --- /dev/null +++ b/.github/stack.md @@ -0,0 +1,13 @@ +# 🧱 Stack Overview + +## feature/final-touch 🟔 +- Parent: feature/generate-md +- PR: [#4](https://github.com/osaroadade/stacked/pull/4) + +## feature/generate-md 🟔 +- Parent: feature/stack-tracking +- PR: [#3](https://github.com/osaroadade/stacked/pull/3) + +## feature/stack-tracking 🟔 +- Parent: feature/base + diff --git a/.github/workflows/update-stackmd.yaml b/.github/workflows/update-stackmd.yaml new file mode 100644 index 0000000..b498ab8 --- /dev/null +++ b/.github/workflows/update-stackmd.yaml @@ -0,0 +1,39 @@ +name: Update Stack Markdown +on: + push: + branches-ignore: + - main + pull_request: + types: [opened, synchronize, reopened] + +permissions: + contents: write + +jobs: + generate-stackmd: + runs-on: ubuntu-latest + steps: + - name: ✨ Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: ā˜•ļø Set up Go + uses: actions/setup-go@v4 + with: + go-version: '1.24' + + - name: šŸ”Ø Build stack..md + run: go run ./cmd/genstack/main.go + + - name: šŸ” Check for changes + run: | + git config --local user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + if [[ -n $(git status --porcelain .github/stack.md) ]]; then + git add .github/stack.md + git commit -m "chore: auto-update stack.md" + git push origin HEAD:${{ github.ref_name }} + else + echo "No changes to commit." + fi \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/.stack.yaml b/.stack.yaml index 1d684c0..c09fe85 100644 --- a/.stack.yaml +++ b/.stack.yaml @@ -1,4 +1,12 @@ stack: + feature/final-touch: + parent: feature/generate-md + pr: 4 + status: open + feature/generate-md: + parent: feature/stack-tracking + pr: 3 + status: open feature/stack-tracking: parent: feature/base status: open diff --git a/README b/README new file mode 100644 index 0000000..d7f872a --- /dev/null +++ b/README @@ -0,0 +1 @@ +# Test trigger \ No newline at end of file diff --git a/cmd/create.go b/cmd/create.go index 4fe28f6..c33e6b2 100644 --- a/cmd/create.go +++ b/cmd/create.go @@ -56,16 +56,7 @@ to quickly create a Cobra application.`, body, _ := reader.ReadString('\n') body = strings.TrimSpace(body) - repoURL, err := getGitHubRepoURL() - if err != nil { - fmt.Println("āš ļø Could not get remote repo URL:", err) - repoURL = "https://github.com/unkown/repo" // fallback - } - - stackLink := fmt.Sprintf( - "\n\n---\nšŸ”— This PR is part of a stack. See full context: [stack.md](%s/blob/%s/stack.md)", - repoURL, currentBranch, - ) + stackLink := "\n\n---\nšŸ”— This PR is part of a stack. See full context: [stack.md](.github/stack.md)" var fullBody string if body == "" { @@ -93,11 +84,6 @@ to quickly create a Cobra application.`, return } - if err := createCmd.Run(); err != nil { - fmt.Println("āŒ Failed to create PR:", err) - return - } - prURL := strings.TrimSpace(prOutput.String()) fmt.Println("āœ… PR created successfully!", prURL) @@ -109,7 +95,7 @@ to quickly create a Cobra application.`, } prNumber, _ := strconv.Atoi(matches[1]) - err = stack.WriteSampleStack(currentBranch, parentBranch, prNumber) + err = stack.WriteBranchEntry(currentBranch, parentBranch, prNumber) if err != nil { fmt.Println("āš ļø Could not write to .stack.yml:", err) } @@ -179,29 +165,3 @@ func findParentBranch(currentBranch string) (string, error) { return bestParent, nil } - -func getGitHubRepoURL() (string, error) { - out, err := exec.Command("git", "remote", "get-url", "origin").Output() - if err != nil { - return "", err - } - rawURL := strings.TrimSpace(string(out)) - - // Convert SSH URL to HTTPS - if strings.HasPrefix(rawURL, "git@") { - // Example: git@github.com:user/repo.git - rawURL = strings.Replace(rawURL, "git@", "https://", 1) - rawURL = strings.Replace(rawURL, ":", "/", 1) - } else if strings.HasPrefix(rawURL, "https://") { - // already done - } else { - return "", fmt.Errorf("unsupported remote URL format") - } - - // Trim .git suffix - if strings.HasSuffix(rawURL, ".git") { - rawURL = strings.TrimSuffix(rawURL, ".git") - } - - return rawURL, nil -} diff --git a/cmd/genstack/main.go b/cmd/genstack/main.go new file mode 100644 index 0000000..401ea06 --- /dev/null +++ b/cmd/genstack/main.go @@ -0,0 +1,31 @@ +package main + +import ( + "fmt" + "os" + + "github.com/osaroadade/stacked/internal/stack" +) + +func main() { + content, err := os.ReadFile(".stack.yaml") + if err != nil { + fmt.Println("āŒ Could not read .stack.yaml:", err) + os.Exit(1) + } + + var data stack.StackData + err = stack.UnmarshalStack(content, &data) + if err != nil { + fmt.Println("āŒ Failed to parse .stack.yaml:", err) + os.Exit(1) + } + + err = stack.GenerateMarkdown(data) + if err != nil { + fmt.Println("āŒ Failed to generate stack.md:", err) + os.Exit(1) + } + + fmt.Println("āœ… Generated .github/stack.md successfully.") +} diff --git a/go.mod b/go.mod index cdb2f30..9db9ac1 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/osaroadade/stacked -go 1.24.2 +go 1.24 require github.com/spf13/cobra v1.9.1 // direct diff --git a/internal/stack/render.go b/internal/stack/render.go new file mode 100644 index 0000000..92362c4 --- /dev/null +++ b/internal/stack/render.go @@ -0,0 +1,49 @@ +package stack + +import ( + "fmt" + "os" + "sort" +) + +// GenerateMarkdown creates a human-readable stack.md file based on .stack.yml. +func GenerateMarkdown(data StackData) error { + var output string + output += "# 🧱 Stack Overview\n\n" + + // Sort branches alphabetically for consistency + branches := make([]string, 0, len(data.Stack)) + for branch := range data.Stack { + branches = append(branches, branch) + } + sort.Strings(branches) + + for _, branch := range branches { + entry := data.Stack[branch] + + // Status emoji + statusEmoji := map[string]string{ + "merged": "āœ…", + "open": "🟔", + "draft": "šŸ“", + }[entry.Status] + if statusEmoji == "" { + statusEmoji = "ā”" + } + + // PR link (if available) + prInfo := "" + if entry.PR != nil { + prInfo = fmt.Sprintf("[#%d](https://github.com/osaroadade/stacked/pull/%d)", *entry.PR, *entry.PR) + } + + output += fmt.Sprintf("## %s %s\n", branch, statusEmoji) + output += fmt.Sprintf("- Parent: %s\n", entry.Parent) + if prInfo != "" { + output += fmt.Sprintf("- PR: %s\n", prInfo) + } + output += "\n" + } + + return os.WriteFile(".github/stack.md", []byte(output), 0644) +} diff --git a/internal/stack/write.go b/internal/stack/write.go index 04241ad..f757f47 100644 --- a/internal/stack/write.go +++ b/internal/stack/write.go @@ -17,7 +17,7 @@ type StackData struct { Stack map[string]StackEntry `yaml:"stack"` } -func WriteSampleStack(branch, parent string, pr int) error { +func WriteBranchEntry(branch, parent string, pr int) error { entry := StackEntry{ Parent: parent, PR: &pr, @@ -49,5 +49,5 @@ func WriteSampleStack(branch, parent string, pr int) error { } fmt.Println("šŸ“ .stack.yml updated successfully.") - return nil + return GenerateMarkdown(data) } diff --git a/internal/stack/yaml.go b/internal/stack/yaml.go new file mode 100644 index 0000000..9b1be7c --- /dev/null +++ b/internal/stack/yaml.go @@ -0,0 +1,7 @@ +package stack + +import "gopkg.in/yaml.v3" + +func UnmarshalStack(data []byte, out *StackData) error { + return yaml.Unmarshal(data, out) +} diff --git a/stack.md b/stack.md new file mode 100644 index 0000000..96be1b2 --- /dev/null +++ b/stack.md @@ -0,0 +1,13 @@ +# 🧱 Stack Overview + +## feature/final-touch 🟔 +- Parent: feature/generate-md +- PR: [#4](https://github.com/osaroadade/stacked/pull/4) + +## feature/generate-md 🟔 +- Parent: feature/stack-tracking +- PR: [#3](https://github.com/osaroadade/stacked/pull/3) + +## feature/stack-tracking 🟔 +- Parent: feature/base +