-
Notifications
You must be signed in to change notification settings - Fork 9
feat(jira): add --jira-trailer flag to extract Jira issue key from git trailer #1109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
8ebcaf2
7f8d11d
537dd16
2d7398a
11c68b5
d166591
b2fb1c3
678021b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -30,6 +30,7 @@ type attestJiraOptions struct { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| projectKeys []string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| issueFields string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| secondarySource string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| trailerKey string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ignoreBranchMatch bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| payload JiraAttestationPayload | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -38,8 +39,13 @@ type attestJiraOptions struct { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const attestJiraShortDesc = `Report a jira attestation to an artifact or a trail in a Kosli flow. ` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const attestJiraLongDesc = attestJiraShortDesc + ` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Parses the given commit's message, current branch name or the content of the ^--jira-secondary-source^ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| argument for Jira issue references of the form: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| By default, parses the given commit's message, current branch name, or the content of the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ^--jira-secondary-source^ argument for Jira issue references of the form. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Use ^--jira-trailer^ to read issue keys exclusively from a named git trailer line instead | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (e.g. ^Jira: PROJ-42^); when set, the commit message body, branch name, and | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ^--jira-secondary-source^ are not scanned. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+42
to
+46
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This paragraph now contradicts the validation added in this same commit. It tells the user that with Also a leftover from the last round: line 43 still ends
Suggested change
Comment on lines
+42
to
+46
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This paragraph tells the user something the code now rejects. Line 46 says that when Also still open from the previous round: line 43 ends
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Jira issue references have the form: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'at least 2 characters long, starting with an uppercase letter project key followed by | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dash and one or more digits'. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -59,13 +65,16 @@ because ^CVE-2026^ would be followed by ^-4^. This applies across all parsed sou | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (commit message, branch name, and secondary source). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Note: if your Jira project key collides with this pattern (e.g. a project key of ^CVE^), an | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| issue reference that happens to be the prefix of a longer hyphenated number (such as a CVE | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| identifier) will be filtered out. Use ^--jira-secondary-source^ with a different identifier | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| format as a workaround. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| identifier) will be filtered out. Use ^--jira-trailer^ to read issue keys from a dedicated | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| git trailer line (e.g. ^Jira: CVE-42^), which bypasses pattern-scanning entirely. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Alternatively, use ^--jira-secondary-source^ with a different identifier format. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
66
to
+70
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "bypasses pattern-scanning entirely" isn't true, and this paragraph is the one place a user acts on it. Trailer values still go through Concretely, a user with project key The flag genuinely does help — it removes the surrounding commit text that causes most collisions — so the fix is just to scope the claim:
Suggested change
Comment on lines
66
to
+70
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "bypasses pattern-scanning entirely" is still not true — this was raised last round and the wording is unchanged. Trailer values are joined and passed straight to This matters here specifically because this is the CVE-collision paragraph: a user with project key The flag genuinely does help — it removes the surrounding commit text that causes most collisions — so it's just the scope of the claim that needs fixing:
Suggested change
Comment on lines
66
to
+70
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "bypasses pattern-scanning entirely" is still inaccurate — third round on this one, wording unchanged. Trailer values are joined and handed to It matters here specifically because this is the CVE-collision paragraph — the one place the user acts on this claim. A user with project key The flag does help — it removes the surrounding commit text that causes most collisions — so only the scope of the claim needs fixing:
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| If you want to restrict the Jira issue matching to a specific project, use the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ^--jira-project-key^ flag to specify your own project key. You can specify multiple project keys if needed. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| If the ^--ignore-branch-match^ is set, the branch name is not parsed for a match. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ^--ignore-branch-match^ has no effect when ^--jira-trailer^ is set, since the branch is | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| never scanned in trailer mode. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| The found issue references will be checked against Jira to confirm their existence. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| The attestation is reported in all cases, and its compliance status depends on referencing | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -190,6 +199,20 @@ kosli attest jira \ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --jira-api-token yourJiraAPIToken \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --api-token yourAPIToken \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --org yourOrgName | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # read the jira issue key exclusively from a git trailer line (e.g. "Jira: PROJ-42") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # bypasses commit message and branch scanning entirely — useful when project keys | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # collide with patterns like CVE identifiers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| kosli attest jira \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --name yourAttestationName \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --flow yourFlowName \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --trail yourTrailName \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --jira-trailer Jira \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --jira-base-url https://kosli.atlassian.net \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --jira-username user@domain.com \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --jira-api-token yourJiraAPIToken \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --api-token yourAPIToken \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --org yourOrgName | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func newAttestJiraCmd(out io.Writer) *cobra.Command { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -234,6 +257,11 @@ func newAttestJiraCmd(out io.Writer) *cobra.Command { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err = MuXRequiredFlags(cmd, []string{"jira-trailer", "jira-secondary-source"}, false) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err = ValidateSliceValues(o.redactedCommitInfo, allowedCommitRedactionValues) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return fmt.Errorf("%s for --redact-commit-info", err.Error()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -263,6 +291,7 @@ func newAttestJiraCmd(out io.Writer) *cobra.Command { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cmd.Flags().StringSliceVar(&o.projectKeys, "jira-project-key", []string{}, jiraProjectKeyFlag) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cmd.Flags().StringVar(&o.issueFields, "jira-issue-fields", "", jiraIssueFieldFlag) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cmd.Flags().StringVar(&o.secondarySource, "jira-secondary-source", "", jiraSecondarySourceFlag) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cmd.Flags().StringVar(&o.trailerKey, "jira-trailer", "", jiraTrailerFlag) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cmd.Flags().BoolVar(&o.ignoreBranchMatch, "ignore-branch-match", false, ignoreBranchMatchFlag) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cmd.Flags().BoolVar(&o.assert, "assert", false, attestationAssertFlag) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -304,11 +333,30 @@ func (o *attestJiraOptions) run(args []string) error { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Search commit message, branch name, and secondary source for Jira issue keys, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // filtering out false positives from multi-segment identifiers like CVE-2026-41284. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| issueIDs := jira.FindJiraIssueKeys(jiraSearchText(commitInfo, o.secondarySource, o.ignoreBranchMatch), o.projectKeys) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Find Jira issue keys either from a named git trailer or by scanning the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // commit message, branch name, and secondary source. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var issueIDs []string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if o.trailerKey != "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if o.ignoreBranchMatch { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.Warn("--ignore-branch-match has no effect when --jira-trailer is set") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| trailerValues := gitview.GetTrailerValues(commitInfo.Message, o.trailerKey) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| combinedTrailerText := strings.Join(trailerValues, "\n") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| issueIDs = jira.FindJiraIssueKeys(combinedTrailerText, o.projectKeys) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.Debug("Checked for Jira issue references in trailer '%s' of Git commit %s: %v", o.trailerKey, commitInfo.Sha1, trailerValues) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
vidhu-balad marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if len(trailerValues) > 0 && len(issueIDs) == 0 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.Warn("trailer '%s' was found but contained no valid Jira issue keys: %v", o.trailerKey, trailerValues) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| issueIDs = jira.FindJiraIssueKeys(jiraSearchText(commitInfo, o.secondarySource, o.ignoreBranchMatch), o.projectKeys) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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: %v", issueIDs) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
vidhu-balad marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| issueSource := "commit message or branch name" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if o.trailerKey != "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| issueSource = fmt.Sprintf("trailer '%s'", o.trailerKey) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| issueLog := "" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| issueFoundCount := 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -368,7 +416,7 @@ func (o *attestJiraOptions) run(args []string) error { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| errString = fmt.Sprintf("%s\nError: ", err.Error()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err = fmt.Errorf("%sno Jira references are found in commit message or branch name", errString) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err = fmt.Errorf("%sno Jira references are found in %s", errString, issueSource) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if issueFoundCount != len(issueIDs) && o.assert && !global.DryRun { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -381,8 +429,8 @@ func (o *attestJiraOptions) run(args []string) error { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for _, reason := range unconfirmedReasons { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| reasonLog += fmt.Sprintf("\n\treason: %s", reason) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err = fmt.Errorf("%s%s from references found in commit message or branch name%s%s", errString, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jiraAssertHeadline(len(issueIDs)-issueFoundCount-len(unconfirmedIDs), len(unconfirmedIDs)), issueLog, reasonLog) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err = fmt.Errorf("%s%s from references found in %s%s%s", errString, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jiraAssertHeadline(len(issueIDs)-issueFoundCount-len(unconfirmedIDs), len(unconfirmedIDs)), issueSource, issueLog, reasonLog) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return wrapAttestationError(err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -366,6 +366,62 @@ func (suite *AttestJiraCommandTestSuite) TestAttestJiraCmd() { | |||||||||||||||||||||||||||||||||||||||||||||||||
| cmd: fmt.Sprintf("attest jira --name .foo --commit HEAD --jira-base-url https://kosli-test.atlassian.net %s", suite.defaultKosliArguments), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| golden: "Error: failed to parse attestation name: invalid attestation name format: .foo\n", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| name: "27 can attest jira using --jira-trailer to extract issue key from commit trailer", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| cmd: fmt.Sprintf(`attest jira --name bar | ||||||||||||||||||||||||||||||||||||||||||||||||||
| --jira-base-url https://kosli-test.atlassian.net | ||||||||||||||||||||||||||||||||||||||||||||||||||
| --jira-trailer Jira | ||||||||||||||||||||||||||||||||||||||||||||||||||
| --assert | ||||||||||||||||||||||||||||||||||||||||||||||||||
| --repo-root %s %s`, suite.tmpDir, suite.defaultKosliArguments), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| golden: "jira attestation 'bar' is reported to trail: test-123\n", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| additionalConfig: jiraTestsAdditionalConfig{ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| commitMessage: "fix: some change\n\nJira: EX-1\nOna-Environment-Id: ONA-999", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
vidhu-balad marked this conversation as resolved.
vidhu-balad marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| name: "28 --jira-trailer with no matching trailer produces no issue IDs (non-compliant but reported)", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| cmd: fmt.Sprintf(`attest jira --name bar | ||||||||||||||||||||||||||||||||||||||||||||||||||
| --jira-base-url https://kosli-test.atlassian.net | ||||||||||||||||||||||||||||||||||||||||||||||||||
| --jira-trailer Jira | ||||||||||||||||||||||||||||||||||||||||||||||||||
| --repo-root %s %s`, suite.tmpDir, suite.defaultKosliArguments), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| golden: "jira attestation 'bar' is reported to trail: test-123\n", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| additionalConfig: jiraTestsAdditionalConfig{ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| commitMessage: "fix: some change with no jira trailer", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| wantError: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| name: "29 --jira-trailer with --assert fails when trailer is absent", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| cmd: fmt.Sprintf(`attest jira --name bar | ||||||||||||||||||||||||||||||||||||||||||||||||||
| --jira-base-url https://kosli-test.atlassian.net | ||||||||||||||||||||||||||||||||||||||||||||||||||
| --jira-trailer Jira | ||||||||||||||||||||||||||||||||||||||||||||||||||
| --assert | ||||||||||||||||||||||||||||||||||||||||||||||||||
| --repo-root %s %s`, suite.tmpDir, suite.defaultKosliArguments), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| golden: "jira attestation 'bar' is reported to trail: test-123\nError: no Jira references are found in trailer 'Jira'\n", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| additionalConfig: jiraTestsAdditionalConfig{ | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Three behaviours added in the latest commit have no test, which is worth closing given the TDD discipline in
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| commitMessage: "fix: some change with no jira trailer", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| wantError: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| name: "30 --jira-trailer and --jira-secondary-source are mutually exclusive", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| cmd: fmt.Sprintf("attest jira --name bar --jira-base-url https://kosli-test.atlassian.net --jira-trailer Jira --jira-secondary-source foo --commit HEAD --repo-root %s %s", suite.tmpDir, suite.defaultKosliArguments), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| golden: "Error: only one of --jira-trailer, --jira-secondary-source is allowed\n", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| wantError: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| name: "31 --jira-trailer does not scan branch name even when branch contains a Jira key", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| cmd: fmt.Sprintf(`attest jira --name bar | ||||||||||||||||||||||||||||||||||||||||||||||||||
| --jira-base-url https://kosli-test.atlassian.net | ||||||||||||||||||||||||||||||||||||||||||||||||||
| --jira-trailer Jira | ||||||||||||||||||||||||||||||||||||||||||||||||||
| --assert | ||||||||||||||||||||||||||||||||||||||||||||||||||
| --repo-root %s %s`, suite.tmpDir, suite.defaultKosliArguments), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| golden: "jira attestation 'bar' is reported to trail: test-123\nError: no Jira references are found in trailer 'Jira'\n", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| additionalConfig: jiraTestsAdditionalConfig{ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| branchName: "EX-1-some-feature", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| commitMessage: "fix: some change with no jira trailer", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test 30 is a good one — The one remaining gap is the new error path added in this commit:
Suggested change
Note this case must not carry |
||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| for _, test := range tests { | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -169,6 +169,7 @@ The ^.kosli_ignore^ will be treated as part of the artifact like any other file, | |||||
| jiraIssueFieldFlag = "[optional] The comma separated list of fields to include from the Jira issue. Default no fields are included. '*all' will give all fields." | ||||||
| jiraSecondarySourceFlag = "[optional] An optional string to search for Jira ticket reference, e.g. '--jira-secondary-source ${{ github.head_ref }}'" | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It's worth the one line because
Suggested change
|
||||||
| ignoreBranchMatchFlag = "Ignore branch name when searching for Jira ticket reference." | ||||||
| jiraTrailerFlag = "[optional] The git trailer key to use as the sole source of Jira issue references (e.g. '--jira-trailer Jira' extracts the value of 'Jira: <issue-key>' lines from the commit message). When set, the commit message body and branch name are not scanned. Mutually exclusive with --jira-secondary-source." | ||||||
| envDescriptionFlag = "[optional] The environment description." | ||||||
| flowDescriptionFlag = "[optional] The Kosli flow description." | ||||||
| trailDescriptionFlag = "[optional] The Kosli trail description." | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -276,6 +276,24 @@ func getCommitURL(repoURL, commitHash string) string { | |||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // GetTrailerValues extracts the values of all trailer lines in a commit message | ||||||||||||||||||||||
| // that match the given key. The key comparison is case-insensitive. Trailer lines | ||||||||||||||||||||||
| // have the format "<key>: <value>". Returns an empty (non-nil) slice if none are found. | ||||||||||||||||||||||
|
vidhu-balad marked this conversation as resolved.
Comment on lines
+279
to
+281
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The key trimming is in and unit-tested (
Suggested change
|
||||||||||||||||||||||
| func GetTrailerValues(message, key string) []string { | ||||||||||||||||||||||
|
Comment on lines
+279
to
+282
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The key trimming from last round is in (
Suggested change
|
||||||||||||||||||||||
| result := []string{} | ||||||||||||||||||||||
| prefix := strings.ToLower(strings.TrimRight(strings.TrimSpace(key), ":")) + ":" | ||||||||||||||||||||||
| for _, line := range strings.Split(message, "\n") { | ||||||||||||||||||||||
| trimmed := strings.TrimSpace(line) | ||||||||||||||||||||||
| if strings.HasPrefix(strings.ToLower(trimmed), prefix) { | ||||||||||||||||||||||
| value := strings.TrimSpace(trimmed[len(prefix):]) | ||||||||||||||||||||||
| if value != "" { | ||||||||||||||||||||||
| result = append(result, value) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| return result | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // ResolveRevision returns an explicit commit SHA1 from commit SHA or ref (e.g. HEAD~2) | ||||||||||||||||||||||
| func (gv *GitView) ResolveRevision(commitSHAOrRef string) (string, error) { | ||||||||||||||||||||||
| hash, err := gv.repository.ResolveRevision(plumbing.Revision(commitSHAOrRef)) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leftover from splitting the sentence: line 43 ends
for Jira issue references of the form.— the "of the form" now dangles, since the form is defined two lines later under its own heading. This is the first thingkosli attest jira --helpprints.