Skip to content

Commit

Permalink
deprecation: retire .ignore_pull_request_template variable
Browse files Browse the repository at this point in the history
feat: add .pull_request_template_path to customize the template path
enhancement: support finding the pr template and .gh-prx.yaml paths from nested repo directories
  • Loading branch information
ilaif committed Apr 16, 2024
1 parent beec302 commit 1590fd9
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 23 deletions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,20 +82,19 @@ pr:
issue:
provider: github # The provider to use for fetching issue details (supported: github,jira,linear)
types: ["fix", "feat", "chore", "docs", "refactor", "test", "style", "build", "ci", "perf", "revert"] # The issue types to prompt the user when creating a new branch
pull_request_template_path: "./pull_request_template.md" # The pull request template file to use when creating a new PR. Relative to the .gh-prx.yaml file location.
ignore_pull_request_template: false # If true, the pull request template in the repository will be ignored.
checkout_new:
jira:
project: "" # The Jira project key to use when creating a new branch
issue_jql: "[<jira_project>+AND+]assignee=currentUser()+AND+statusCategory!=Done+ORDER+BY+updated+DESC" # The Jira JQL to use when fetching issues. <jira_project> is optional and will be replaced with the project key that is configured in the `project` field.
github:
issue_list_flags: ["--state", open", "--assignee", "@me"] # The flags to use when fetching issues from GitHub
# linear: # Due to Linear's GraphQL API, the issue list is not configurable. The default is: `assignedIssues(orderBy: updatedAt, filter: { state: { type: { neq: \"completed\" } } })`
pull_request_template_path: "./pull_request_template.md" # The pull request template file to use when creating a new PR. Relative to the repository root.
```
### PR Description (Body)
The PR description is based on the repo's `.github/pull_request_template.md`. If this file does not exist, a default template is used:
The PR description is based on the `pull_request_template_path` variable which defaults to the repo's `.github/pull_request_template.md`. If this file does not exist, a default template is used:

```markdown
{{with .Issue}}Closes #{{.}}.
Expand Down
23 changes: 11 additions & 12 deletions pkg/cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,16 +148,15 @@ func create(ctx context.Context, opts *CreateOpts) error {
}

if cfg.PullRequestTemplatePath != "" {
prTemplateBytes, err := utils.ReadFile(cfg.PullRequestTemplatePath)
prTemplatePath, err := utils.FindRelativePathInRepo(cfg.PullRequestTemplatePath)
if err != nil {
return errors.Wrap(err, "Failed to find pull request template path")
}
prTemplateBytes, err := utils.ReadFile(prTemplatePath)
if err != nil {
return errors.Wrap(err, "Failed to read pull request template")
}
cfg.PR.Body = string(prTemplateBytes)
} else if cfg.IgnorePullRequestTemplate == nil || !*cfg.IgnorePullRequestTemplate {
prTemplateBytes, err := utils.ReadFile(".github/pull_request_template.md")
if err == nil {
cfg.PR.Body = string(prTemplateBytes)
}
}

out, err := utils.Exec("git", "log", "--pretty=format:%s", "--no-merges", b.Original, "^"+baseBranch)
Expand Down Expand Up @@ -197,18 +196,18 @@ func create(ctx context.Context, opts *CreateOpts) error {
log.Debug(fmt.Sprintf("Pull request body:\n\n%s", pr.Body))
log.Debug(fmt.Sprintf("Pull request labels: %v", pr.Labels))

if len(pr.Labels) > 0 {
if err := createLabels(pr.Labels); err != nil {
return err
}
}

if opts.DryRun {
log.Info("Dry run enabled, skipping pull request creation")

return nil
}

if len(pr.Labels) > 0 {
if err := createLabels(pr.Labels); err != nil {
return err
}
}

s := utils.StartSpinner("Creating pull request...", "Created pull request")
args := []string{"pr", "create", "--title", pr.Title, "--body", pr.Body, "--base", baseBranch}
args = append(args, generatePrCreateArgsFromOpts(opts, pr.Labels)...)
Expand Down
24 changes: 16 additions & 8 deletions pkg/config/repository_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,22 @@ var (
)

type RepositoryConfig struct {
Branch BranchConfig `yaml:"branch"`
PR PullRequestConfig `yaml:"pr"`
Issue IssueConfig `yaml:"issue"`
PullRequestTemplatePath string `yaml:"pull_request_template_path"`
IgnorePullRequestTemplate *bool `yaml:"ignore_pull_request_template"`
CheckoutNew CheckoutNewConfig `yaml:"checkout_new"`
Branch BranchConfig `yaml:"branch"`
PR PullRequestConfig `yaml:"pr"`
Issue IssueConfig `yaml:"issue"`
CheckoutNew CheckoutNewConfig `yaml:"checkout_new"`
PullRequestTemplatePath string `yaml:"pull_request_template_path"`
}

func (c *RepositoryConfig) SetDefaults() {
c.Branch.SetDefaults()
c.PR.SetDefaults()
c.Issue.SetDefaults()
c.CheckoutNew.SetDefaults()

if c.PullRequestTemplatePath == "" {
c.PullRequestTemplatePath = ".github/pull_request_template.md"
}
}

func (c *RepositoryConfig) Validate() error {
Expand Down Expand Up @@ -251,12 +254,17 @@ func (c *CheckoutNewGitHubConfig) SetDefaults() {

func LoadRepositoryConfig(globalRepoConfig *RepositoryConfig) (*RepositoryConfig, error) {
cfg := &RepositoryConfig{}
if err := utils.ReadYaml(DefaultConfigFilepath, cfg); err != nil {

if actualConfigFilepath, err := utils.FindRelativePathInRepo(DefaultConfigFilepath); err != nil {
if !errors.Is(err, os.ErrNotExist) {
return nil, errors.Wrap(err, "Failed to load config")
}

log.Infof("No config file found at '%s', using defaults", DefaultConfigFilepath)
} else {
log.Debug(fmt.Sprintf("Loading repository config from '%s'", actualConfigFilepath))
if err := utils.ReadYaml(actualConfigFilepath, cfg); err != nil {
return nil, errors.Wrap(err, "Failed to load config")
}
}

if globalRepoConfig != nil {
Expand Down
31 changes: 31 additions & 0 deletions pkg/utils/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,34 @@ func WriteYaml(filename string, data interface{}) error {

return nil
}

// FindRelativePathInRepo traverses up from the current directory recursively until a relative path is found.
// It returns the first relative path found, or os.ErrNotExists if no relative path is found.
func FindRelativePathInRepo(path string) (string, error) {
// Get the current working directory
currentDir, err := os.Getwd()
if err != nil {
return "", errors.Wrap(err, "Failed to get current working directory")
}

// Start traversing up from the current directory
for {
// Check if the current directory contains a relative path
if _, err := os.Stat(filepath.Join(currentDir, path)); err == nil {
return filepath.Join(currentDir, path), nil
}

// Move up to the parent directory
parentDir := filepath.Dir(currentDir)

// Check if we have reached the git root directory
if _, err := os.Stat(filepath.Join(currentDir, ".git")); err == nil {
break // Break the loop if we have reached the git root directory
}

// Update the current directory to the parent directory
currentDir = parentDir
}

return "", os.ErrNotExist // Return an error if no relative path is found
}

0 comments on commit 1590fd9

Please sign in to comment.