feat: v0.3.0b — add repo edit command, fix repo create --public flag
- Add `fgj repo edit` for changing visibility, description, homepage, and default branch on existing repositories - Fix `repo create --public` flag which was defined but never read
This commit is contained in:
parent
43e43e7024
commit
7ee5a61910
4 changed files with 146 additions and 3 deletions
11
CHANGELOG.md
11
CHANGELOG.md
|
|
@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [0.3.0b] - 2026-03-21
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
#### Repository Management
|
||||||
|
- `fgj repo edit` - Edit repository settings (visibility, description, homepage, default branch)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- `fgj repo create --public` flag was defined but never read; now properly wired up
|
||||||
|
|
||||||
## [0.3.0a] - 2026-03-21
|
## [0.3.0a] - 2026-03-21
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
@ -165,6 +175,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- Cobra framework for CLI structure
|
- Cobra framework for CLI structure
|
||||||
- Viper for configuration management
|
- Viper for configuration management
|
||||||
|
|
||||||
|
[0.3.0b]: https://forgejo.zerova.net/sid/fgj-sid/releases/tag/v0.3.0b
|
||||||
[0.3.0a]: https://forgejo.zerova.net/sid/fgj-sid/releases/tag/v0.3.0a
|
[0.3.0a]: https://forgejo.zerova.net/sid/fgj-sid/releases/tag/v0.3.0a
|
||||||
[0.3.0]: https://codeberg.org/romaintb/fgj/releases/tag/v0.3.0
|
[0.3.0]: https://codeberg.org/romaintb/fgj/releases/tag/v0.3.0
|
||||||
[0.2.0]: https://codeberg.org/romaintb/fgj/releases/tag/v0.2.0
|
[0.2.0]: https://codeberg.org/romaintb/fgj/releases/tag/v0.2.0
|
||||||
|
|
|
||||||
10
README.md
10
README.md
|
|
@ -12,7 +12,7 @@
|
||||||
- Multi-instance support (works with any Forgejo or Gitea instance)
|
- Multi-instance support (works with any Forgejo or Gitea instance)
|
||||||
- Pull request management (create, list, view, merge, diff, comment, review)
|
- Pull request management (create, list, view, merge, diff, comment, review)
|
||||||
- Issue tracking (create, list, view, comment, close, labels)
|
- Issue tracking (create, list, view, comment, close, labels)
|
||||||
- Repository operations (view, list, create, clone, fork)
|
- Repository operations (view, list, create, edit, clone, fork)
|
||||||
- Forgejo Actions (workflow runs, watch/rerun/cancel, enable/disable, secrets, variables)
|
- Forgejo Actions (workflow runs, watch/rerun/cancel, enable/disable, secrets, variables)
|
||||||
- Releases (create, upload, delete)
|
- Releases (create, upload, delete)
|
||||||
- Raw API access (`fgj api`) for arbitrary REST calls
|
- Raw API access (`fgj api`) for arbitrary REST calls
|
||||||
|
|
@ -207,6 +207,12 @@ fgj repo clone owner/repo -p ssh
|
||||||
|
|
||||||
# Fork a repository
|
# Fork a repository
|
||||||
fgj repo fork owner/repo
|
fgj repo fork owner/repo
|
||||||
|
|
||||||
|
# Edit repository settings
|
||||||
|
fgj repo edit owner/repo --public
|
||||||
|
fgj repo edit owner/repo --private
|
||||||
|
fgj repo edit owner/repo -d "New description" --homepage https://example.com
|
||||||
|
fgj repo edit --default-branch develop
|
||||||
```
|
```
|
||||||
|
|
||||||
### Releases
|
### Releases
|
||||||
|
|
@ -460,7 +466,7 @@ Contributions are welcome! Please feel free to submit a Pull Request at [forgejo
|
||||||
- `pr checks`, `pr ready/draft`
|
- `pr checks`, `pr ready/draft`
|
||||||
- `issue reopen`, `issue assign`
|
- `issue reopen`, `issue assign`
|
||||||
- `release edit`, `release download`, `release generate-notes`
|
- `release edit`, `release download`, `release generate-notes`
|
||||||
- `repo delete`, `repo rename`, `repo visibility`
|
- `repo delete`, `repo rename`
|
||||||
|
|
||||||
We welcome contributions to implement any of these features!
|
We welcome contributions to implement any of these features!
|
||||||
|
|
||||||
|
|
|
||||||
126
cmd/repo.go
126
cmd/repo.go
|
|
@ -62,10 +62,33 @@ Name can be "reponame" (creates under your account) or "org/reponame"
|
||||||
RunE: runRepoCreate,
|
RunE: runRepoCreate,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var repoEditCmd = &cobra.Command{
|
||||||
|
Use: "edit [owner/name]",
|
||||||
|
Short: "Edit repository settings",
|
||||||
|
Long: "Edit settings of an existing repository such as visibility, description, homepage, and default branch.",
|
||||||
|
Example: ` # Make a repository private
|
||||||
|
fgj repo edit owner/repo --private
|
||||||
|
|
||||||
|
# Make a repository public
|
||||||
|
fgj repo edit owner/repo --public
|
||||||
|
|
||||||
|
# Update description and homepage
|
||||||
|
fgj repo edit owner/repo -d "New description" --homepage https://example.com
|
||||||
|
|
||||||
|
# Change default branch
|
||||||
|
fgj repo edit --default-branch develop
|
||||||
|
|
||||||
|
# Edit current repo (auto-detected from git context)
|
||||||
|
fgj repo edit --public`,
|
||||||
|
Args: cobra.MaximumNArgs(1),
|
||||||
|
RunE: runRepoEdit,
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(repoCmd)
|
rootCmd.AddCommand(repoCmd)
|
||||||
repoCmd.AddCommand(repoCloneCmd)
|
repoCmd.AddCommand(repoCloneCmd)
|
||||||
repoCmd.AddCommand(repoCreateCmd)
|
repoCmd.AddCommand(repoCreateCmd)
|
||||||
|
repoCmd.AddCommand(repoEditCmd)
|
||||||
repoCmd.AddCommand(repoForkCmd)
|
repoCmd.AddCommand(repoForkCmd)
|
||||||
repoCmd.AddCommand(repoListCmd)
|
repoCmd.AddCommand(repoListCmd)
|
||||||
repoCmd.AddCommand(repoViewCmd)
|
repoCmd.AddCommand(repoViewCmd)
|
||||||
|
|
@ -82,6 +105,15 @@ func init() {
|
||||||
repoCreateCmd.MarkFlagsMutuallyExclusive("public", "private")
|
repoCreateCmd.MarkFlagsMutuallyExclusive("public", "private")
|
||||||
|
|
||||||
repoCloneCmd.Flags().StringP("protocol", "p", "https", "Clone protocol: https or ssh")
|
repoCloneCmd.Flags().StringP("protocol", "p", "https", "Clone protocol: https or ssh")
|
||||||
|
|
||||||
|
repoEditCmd.Flags().StringP("repo", "R", "", "Repository in owner/name format")
|
||||||
|
repoEditCmd.Flags().StringP("description", "d", "", "Repository description")
|
||||||
|
repoEditCmd.Flags().String("homepage", "", "Repository home page URL")
|
||||||
|
repoEditCmd.Flags().String("default-branch", "", "Default branch name")
|
||||||
|
repoEditCmd.Flags().Bool("private", false, "Make the repository private")
|
||||||
|
repoEditCmd.Flags().Bool("public", false, "Make the repository public")
|
||||||
|
repoEditCmd.Flags().Bool("json", false, "Output updated repository as JSON")
|
||||||
|
repoEditCmd.MarkFlagsMutuallyExclusive("public", "private")
|
||||||
}
|
}
|
||||||
|
|
||||||
func runRepoView(cmd *cobra.Command, args []string) error {
|
func runRepoView(cmd *cobra.Command, args []string) error {
|
||||||
|
|
@ -270,6 +302,7 @@ func runRepoCreate(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
private, _ := cmd.Flags().GetBool("private")
|
private, _ := cmd.Flags().GetBool("private")
|
||||||
|
public, _ := cmd.Flags().GetBool("public")
|
||||||
description, _ := cmd.Flags().GetString("description")
|
description, _ := cmd.Flags().GetString("description")
|
||||||
addReadme, _ := cmd.Flags().GetBool("add-readme")
|
addReadme, _ := cmd.Flags().GetBool("add-readme")
|
||||||
gitignore, _ := cmd.Flags().GetString("gitignore")
|
gitignore, _ := cmd.Flags().GetString("gitignore")
|
||||||
|
|
@ -278,6 +311,11 @@ func runRepoCreate(cmd *cobra.Command, args []string) error {
|
||||||
doClone, _ := cmd.Flags().GetBool("clone")
|
doClone, _ := cmd.Flags().GetBool("clone")
|
||||||
team, _ := cmd.Flags().GetString("team")
|
team, _ := cmd.Flags().GetString("team")
|
||||||
|
|
||||||
|
// --public explicitly sets private=false (default behavior, but makes intent clear)
|
||||||
|
if public {
|
||||||
|
private = false
|
||||||
|
}
|
||||||
|
|
||||||
cfg, err := config.Load()
|
cfg, err := config.Load()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -383,3 +421,91 @@ func parseCreateName(name string) (org, repoName string, isOrg bool, err error)
|
||||||
}
|
}
|
||||||
return "", name, false, nil
|
return "", name, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func runRepoEdit(cmd *cobra.Command, args []string) error {
|
||||||
|
var repo string
|
||||||
|
if len(args) > 0 {
|
||||||
|
repo = args[0]
|
||||||
|
}
|
||||||
|
if r, _ := cmd.Flags().GetString("repo"); r != "" {
|
||||||
|
repo = r
|
||||||
|
}
|
||||||
|
|
||||||
|
owner, name, err := parseRepo(repo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg, err := config.Load()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := api.NewClientFromConfig(cfg, "", getDetectedHost())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
opt := gitea.EditRepoOption{}
|
||||||
|
changed := false
|
||||||
|
|
||||||
|
if cmd.Flags().Changed("description") {
|
||||||
|
d, _ := cmd.Flags().GetString("description")
|
||||||
|
opt.Description = &d
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
if cmd.Flags().Changed("homepage") {
|
||||||
|
h, _ := cmd.Flags().GetString("homepage")
|
||||||
|
opt.Website = &h
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
if cmd.Flags().Changed("default-branch") {
|
||||||
|
b, _ := cmd.Flags().GetString("default-branch")
|
||||||
|
opt.DefaultBranch = &b
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
if cmd.Flags().Changed("private") {
|
||||||
|
p := true
|
||||||
|
opt.Private = &p
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
if cmd.Flags().Changed("public") {
|
||||||
|
p := false
|
||||||
|
opt.Private = &p
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !changed {
|
||||||
|
return fmt.Errorf("no changes specified; use flags like --public, --private, --description, --homepage, or --default-branch")
|
||||||
|
}
|
||||||
|
|
||||||
|
repository, _, err := client.EditRepo(owner, name, opt)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to edit repository: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonFlag, _ := cmd.Flags().GetBool("json")
|
||||||
|
if jsonFlag {
|
||||||
|
return writeJSON(repository)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Repository updated: %s\n", repository.HTMLURL)
|
||||||
|
if opt.Private != nil {
|
||||||
|
if *opt.Private {
|
||||||
|
fmt.Println("Visibility: private")
|
||||||
|
} else {
|
||||||
|
fmt.Println("Visibility: public")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if opt.Description != nil {
|
||||||
|
fmt.Printf("Description: %s\n", *opt.Description)
|
||||||
|
}
|
||||||
|
if opt.Website != nil {
|
||||||
|
fmt.Printf("Homepage: %s\n", *opt.Website)
|
||||||
|
}
|
||||||
|
if opt.DefaultBranch != nil {
|
||||||
|
fmt.Printf("Default branch: %s\n", *opt.DefaultBranch)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ var rootCmd = &cobra.Command{
|
||||||
Short: "Forgejo CLI tool - work seamlessly with Forgejo from the command line",
|
Short: "Forgejo CLI tool - work seamlessly with Forgejo from the command line",
|
||||||
Long: `fgj is a command line tool for Forgejo instances (including Codeberg).
|
Long: `fgj is a command line tool for Forgejo instances (including Codeberg).
|
||||||
It brings pull requests, issues, and other Forgejo concepts to the terminal.`,
|
It brings pull requests, issues, and other Forgejo concepts to the terminal.`,
|
||||||
Version: "0.3.0a",
|
Version: "0.3.0b",
|
||||||
SilenceErrors: true,
|
SilenceErrors: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue