Skip to content

Commit

Permalink
Merge pull request #44 from kosli-dev/jira-evidence-in-branch-name
Browse files Browse the repository at this point in the history
Add `--assert` option for reporting jira evidence
  • Loading branch information
tooky authored Nov 13, 2023
2 parents 630e998 + f6c6c26 commit 9bfd072
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 15 deletions.
30 changes: 28 additions & 2 deletions cmd/kosli/reportEvidenceCommitJira.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type reportEvidenceCommitJiraOptions struct {
pat string
srcRepoRoot string
payload JiraEvidencePayload
assert bool
}

const reportEvidenceCommitJiraShortDesc = `Report Jira evidence for a commit in Kosli flows.`
Expand Down Expand Up @@ -75,6 +76,20 @@ kosli report evidence commit jira \
--api-token yourAPIToken \
--org yourOrgName \
--user-data /path/to/json/file.json
# fail if no issue reference is found, or the issue is not found in your jira instance
kosli report evidence commit jira \
--commit yourGitCommitSha1 \
--name yourEvidenceName \
--jira-base-url https://kosli.atlassian.net \
--jira-username [email protected] \
--jira-api-token yourJiraAPIToken \
--flows yourFlowName \
--build-url https://exampleci.com \
--api-token yourAPIToken \
--org yourOrgName \
--assert
`

func newReportEvidenceCommitJiraCmd(out io.Writer) *cobra.Command {
Expand Down Expand Up @@ -117,6 +132,7 @@ func newReportEvidenceCommitJiraCmd(out io.Writer) *cobra.Command {
cmd.Flags().StringVar(&o.srcRepoRoot, "repo-root", ".", repoRootFlag)
cmd.Flags().StringVarP(&o.userDataFilePath, "user-data", "u", "", evidenceUserDataFlag)
cmd.Flags().StringSliceVarP(&o.evidencePaths, "evidence-paths", "e", []string{}, evidencePathsFlag)
cmd.Flags().BoolVar(&o.assert, "assert", false, assertJiraEvidenceFlag)
addDryRunFlag(cmd)

err := RequireFlags(cmd, []string{"commit", "build-url", "name", "jira-base-url"})
Expand Down Expand Up @@ -145,6 +161,7 @@ func (o *reportEvidenceCommitJiraOptions) run(args []string) error {
return err
}

logger.Debug("Resolving commit reference: %s", o.payload.CommitSHA)
o.payload.CommitSHA, err = gv.ResolveRevision(o.payload.CommitSHA)
if err != nil {
return err
Expand All @@ -157,14 +174,19 @@ func (o *reportEvidenceCommitJiraOptions) run(args []string) error {
// more info: https://support.atlassian.com/jira-software-cloud/docs/what-is-an-issue/#Workingwithissues-Projectandissuekeys
jiraIssueKeyPattern := `[A-Z][A-Z0-9]{1,9}-[0-9]+`

issueIDs, err := gv.MatchPatternInCommitMessageORBranchName(jiraIssueKeyPattern, o.payload.CommitSHA)
issueIDs, commitInfo, err := gv.MatchPatternInCommitMessageORBranchName(jiraIssueKeyPattern, o.payload.CommitSHA)
if err != nil {
return err
}

logger.Debug("Checked for Jira issue references in Git commit %s on branch %s commit message:\n%s", commitInfo.Sha1, commitInfo.Branch, commitInfo.Message)
logger.Debug("the following Jira references are found in commit message or branch name: %v", issueIDs)

if len(issueIDs) == 0 && o.assert {
return fmt.Errorf("no Jira references are found in commit message or branch name")
}

issueLog := ""
issueFoundCount := 0
for _, issueID := range issueIDs {
result, err := jc.GetJiraIssueInfo(issueID)
if err != nil {
Expand All @@ -174,9 +196,13 @@ func (o *reportEvidenceCommitJiraOptions) run(args []string) error {
issueExistLog := "issue not found"
if result.IssueExists {
issueExistLog = "issue found"
issueFoundCount++
}
issueLog += fmt.Sprintf("\n\t%s: %s", result.IssueID, issueExistLog)
}
if issueFoundCount != len(issueIDs) && o.assert {
return fmt.Errorf("missing Jira issues from references found in commit message or branch name%s", issueLog)
}

form, cleanupNeeded, evidencePath, err := newEvidenceForm(o.payload, o.evidencePaths)
// if we created a tar package, remove it after uploading it
Expand Down
63 changes: 56 additions & 7 deletions cmd/kosli/reportEvidenceCommitJira_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func (suite *CommitEvidenceJiraCommandTestSuite) TearDownSuite() {

type jiraTestsAdditionalConfig struct {
commitMessage string
branchName string
}

func (suite *CommitEvidenceJiraCommandTestSuite) TestCommitEvidenceJiraCommandCmd() {
Expand Down Expand Up @@ -122,6 +123,18 @@ func (suite *CommitEvidenceJiraCommandTestSuite) TestCommitEvidenceJiraCommandCm
commitMessage: "Lets test EX-1",
},
},
{
name: "report Jira commit evidence with reference as branch name works",
cmd: fmt.Sprintf(`report evidence commit jira --name jira-validation
--jira-base-url https://kosli-test.atlassian.net/ --jira-username [email protected]
--repo-root %s
--build-url example.com %s`, suite.tmpDir, suite.defaultKosliArguments),
goldenRegex: "Jira evidence is reported to commit: [0-9a-f]{40}\n.*Issues references reported:.*\n.*EX-1: issue found",
additionalConfig: jiraTestsAdditionalConfig{
branchName: "EX-1",
commitMessage: "test commit has no reference",
},
},
{
name: "report Jira commit evidence with a slash at the end of --jira-base-url works",
cmd: fmt.Sprintf(`report evidence commit jira --name jira-validation
Expand All @@ -136,7 +149,7 @@ func (suite *CommitEvidenceJiraCommandTestSuite) TestCommitEvidenceJiraCommandCm
{
wantError: true,
name: "report Jira commit evidence with --jira-pat and --jira-api-token fails",
cmd: fmt.Sprintf(`report evidence commit jira --name jira-validation
cmd: fmt.Sprintf(`report evidence commit jira --name jira-validation
--jira-base-url https://kosli-test.atlassian.net --jira-api-token xxx
--jira-pat xxxx --repo-root %s --commit 61ab3ea22bd4264996b35bfb82869c482d9f4a06
--build-url example.com %s`, suite.tmpDir, suite.defaultKosliArguments),
Expand All @@ -160,18 +173,54 @@ func (suite *CommitEvidenceJiraCommandTestSuite) TestCommitEvidenceJiraCommandCm
--build-url example.com %s`, suite.tmpDir, suite.defaultKosliArguments),
golden: "Error: required flag(s) \"commit\" not set\n",
},
{
wantError: true,
name: "assert for non-existing Jira issue gives an error",
cmd: fmt.Sprintf(`report evidence commit jira --name jira-validation
--jira-base-url https://kosli-test.atlassian.net --jira-username [email protected]
--repo-root %s
--assert
--build-url example.com %s`, suite.tmpDir, suite.defaultKosliArguments),
goldenRegex: "Error: missing Jira issues from references found in commit message or branch name.*",
additionalConfig: jiraTestsAdditionalConfig{
commitMessage: "SAMI-1 test commit",
},
},
{
wantError: true,
name: "assert for no Jira issue reference gives an error",
cmd: fmt.Sprintf(`report evidence commit jira --name jira-validation
--jira-base-url https://kosli-test.atlassian.net --jira-username [email protected]
--repo-root %s
--assert
--build-url example.com %s`, suite.tmpDir, suite.defaultKosliArguments),
goldenRegex: "Error: no Jira references are found in commit message or branch name",
additionalConfig: jiraTestsAdditionalConfig{
commitMessage: "test commit without reference",
},
},
}
for _, test := range tests {
if test.additionalConfig != nil {
msg := test.additionalConfig.(jiraTestsAdditionalConfig).commitMessage
commitSha, err := testHelpers.CommitToRepo(suite.workTree, suite.fs, msg)
require.NoError(suite.T(), err)
funcName(test, suite)
}
}

test.cmd = test.cmd + " --commit " + commitSha
func funcName(test cmdTestCase, suite *CommitEvidenceJiraCommandTestSuite) {
if test.additionalConfig != nil {
branchName := test.additionalConfig.(jiraTestsAdditionalConfig).branchName
if branchName != "" {
err := testHelpers.CheckoutNewBranch(suite.workTree, branchName)
require.NoError(suite.T(), err)
defer testHelpers.CheckoutMaster(suite.workTree, suite.T())
}
msg := test.additionalConfig.(jiraTestsAdditionalConfig).commitMessage
commitSha, err := testHelpers.CommitToRepo(suite.workTree, suite.fs, msg)
require.NoError(suite.T(), err)

runTestCmd(suite.T(), []cmdTestCase{test})
test.cmd = test.cmd + " --commit " + commitSha
}

runTestCmd(suite.T(), []cmdTestCase{test})
}

// In order for 'go test' to run this suite, we need to create
Expand Down
1 change: 1 addition & 0 deletions cmd/kosli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ The service principal needs to have the following permissions:
commitEvidenceFlag = "Git commit for which to verify and given evidence. (defaulted in some CIs: https://docs.kosli.com/ci-defaults )."
repositoryFlag = "Git repository. (defaulted in some CIs: https://docs.kosli.com/ci-defaults )."
assertPREvidenceFlag = "[optional] Exit with non-zero code if no pull requests found for the given commit."
assertJiraEvidenceFlag = "[optional] Exit with non-zero code if no jira issue reference found, or jira issue does not exist, for the given commit or branch."
assertStatusFlag = "[optional] Exit with non-zero code if Kosli server is not responding."
azureTokenFlag = "Azure Personal Access token."
azureProjectFlag = "Azure project.(defaulted if you are running in Azure Devops pipelines: https://docs.kosli.com/ci-defaults )."
Expand Down
10 changes: 5 additions & 5 deletions internal/gitview/gitView.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,23 +193,23 @@ func asCommitInfo(commit *object.Commit, branchName string) *CommitInfo {
// MatchPatternInCommitMessageORBranchName returns a slice of strings matching a pattern in a commit message or branch name
// matches lookup happens in the commit message first, and if none is found, matching against the branch name is done
// if no matches are found in both the commit message and the branch name, an empty slice is returned
func (gv *GitView) MatchPatternInCommitMessageORBranchName(pattern, commitSHA string) ([]string, error) {
func (gv *GitView) MatchPatternInCommitMessageORBranchName(pattern, commitSHA string) ([]string, *CommitInfo, error) {
commitInfo, err := gv.GetCommitInfoFromCommitSHA(commitSHA)
if err != nil {
return []string{}, err
return []string{}, nil, err
}

re := regexp.MustCompile(pattern)
matches := re.FindAllString(commitInfo.Message, -1)
if matches != nil {
return matches, nil
return matches, commitInfo, nil
} else {
matches := re.FindAllString(commitInfo.Branch, -1)
if matches != nil {
return matches, nil
return matches, commitInfo, nil
}
}
return []string{}, nil
return []string{}, commitInfo, nil
}

// ResolveRevision returns an explicit commit SHA1 from commit SHA or ref (e.g. HEAD~2)
Expand Down
2 changes: 1 addition & 1 deletion internal/gitview/gitView_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ func (suite *GitViewTestSuite) TestMatchPatternInCommitMessageORBranchName() {
gitView, err := New(suite.tmpDir)
require.NoError(suite.T(), err)

actual, err := gitView.MatchPatternInCommitMessageORBranchName(t.pattern, t.commitSha)
actual, _, err := gitView.MatchPatternInCommitMessageORBranchName(t.pattern, t.commitSha)
require.True(suite.T(), (err != nil) == t.wantError)
require.ElementsMatch(suite.T(), t.want, actual)

Expand Down
21 changes: 21 additions & 0 deletions internal/testHelpers/testHelpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package testHelpers

import (
"fmt"
"github.com/go-git/go-git/v5/plumbing"
"github.com/stretchr/testify/require"
"os"
"path/filepath"
"testing"
Expand Down Expand Up @@ -49,6 +51,11 @@ func InitializeGitRepo(repoPath string) (*git.Repository, *git.Worktree, billy.F
return repo, nil, fs, err
}

_, err = CommitToRepo(w, fs, "Initial Commit")
if err != nil {
return repo, w, fs, err
}

return repo, w, fs, nil
}

Expand Down Expand Up @@ -77,3 +84,17 @@ func CommitToRepo(w *git.Worktree, fs billy.Filesystem, commitMessage string) (s

return hash.String(), nil
}

func CheckoutNewBranch(w *git.Worktree, branchName string) error {
return w.Checkout(&git.CheckoutOptions{
Create: true,
Branch: plumbing.NewBranchReferenceName(branchName),
})
}

func CheckoutMaster(workTree *git.Worktree, t *testing.T) {
err := workTree.Checkout(&git.CheckoutOptions{
Branch: plumbing.Master,
})
require.NoError(t, err)
}

0 comments on commit 9bfd072

Please sign in to comment.