Skip to content

Comments

Add GitLab MR ref-ticket label parsing#59

Merged
WZ merged 1 commit intomainfrom
codex/gitlab-ref-ticket-label
Feb 20, 2026
Merged

Add GitLab MR ref-ticket label parsing#59
WZ merged 1 commit intomainfrom
codex/gitlab-ref-ticket-label

Conversation

@WZ
Copy link
Owner

@WZ WZ commented Feb 20, 2026

What changed

  • Add gitlab_ref_ticket_label config (GITLAB_REF_TICKET_LABEL) for parsing ticket IDs from GitLab MR descriptions
  • Parse values from the configured field line (same-line or next-line), supporting comma-separated IDs
  • Normalize IDs by trimming spaces and removing leading # and - prefixes
  • Disable parsing when gitlab_ref_ticket_label is empty
  • Store parsed IDs on imported GitLab work items (ticket_ids)

Tests

  • Add parser unit tests with fake project/ticket data
  • Add GitLab fetch integration test coverage for configured label parsing
  • go test ./...

Notes

  • This applies only to GitLab fetch flow; GitHub fetch behavior is unchanged.
  • Replaced /report examples to use generic ticket_id wording.

Copilot AI review requested due to automatic review settings February 20, 2026 23:25
@WZ WZ merged commit d33a26c into main Feb 20, 2026
3 checks passed
@WZ WZ deleted the codex/gitlab-ref-ticket-label branch February 20, 2026 23:27
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds configurable parsing of ticket IDs from GitLab MR descriptions and persists the parsed IDs onto imported GitLab work items, while keeping GitHub behavior unchanged.

Changes:

  • Introduce gitlab_ref_ticket_label (GITLAB_REF_TICKET_LABEL) config to enable/disable GitLab MR ticket parsing.
  • Parse and normalize ticket IDs from a labeled field in GitLab MR descriptions and store them on GitLabMR.TicketIDs, then import into WorkItem.TicketIDs.
  • Add unit/integration tests for parsing and GitLab fetch; update /report examples and docs to use generic “ticket_id” wording.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
internal/integrations/gitlab/gitlab.go Adds MR description ingestion and ticket parsing/normalization into GitLabMR.TicketIDs.
internal/integrations/gitlab/ticket_parse_test.go Unit tests for description-field ticket parsing behavior.
internal/integrations/gitlab/gitlab_fetch_test.go Integration test asserting FetchMRs populates TicketIDs when configured.
internal/domain/models.go Extends GitLabMR with TicketIDs.
internal/fetch/auto_fetch.go Persists mr.TicketIDs into imported WorkItem.TicketIDs.
internal/config/config.go Adds GitLabRefTicketLabel config + env override allowing empty value.
internal/config/config_test.go Tests default/override/empty behavior for GitLabRefTicketLabel.
internal/integrations/slack/slack.go Updates /report help/usage examples to [ticket_id].
internal/nudge/nudge.go Updates nudge message example to [ticket_id].
README.md Documents the new config/env var.
config.yaml Adds gitlab_ref_ticket_label sample config and explanation.
docs/agentic-architecture.md Updates example wording from “mantis” to “ticket”.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

gitlab_url: "https://gitlab.example.com"
gitlab_token: "glpat-your-gitlab-token"
gitlab_group_id: "my-team-group"
# GitLab MR description field label used to parse ticket IDs (e.g. "Jira:")
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment suggests configuring gitlab_ref_ticket_label with a trailing colon (e.g. "Jira:"). The parser already matches the colon after the label, so including a colon in the config value will make it look for "Jira::" and prevent ticket parsing. Update the example to "Jira" (no colon) to match the implementation.

Suggested change
# GitLab MR description field label used to parse ticket IDs (e.g. "Jira:")
# GitLab MR description field label used to parse ticket IDs (e.g. "Jira")

Copilot uses AI. Check for mistakes.
gitlab_url: "https://gitlab.example.com"
gitlab_token: "glpat-..."
gitlab_group_id: "my-team"
gitlab_ref_ticket_label: "Jira" # optional: parse ticket IDs from "Jira:" field in GitLab MR description; empty disables parsing
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This README example implies the configured value might include the colon ("Jira:" field) but doesn’t explicitly say the config value should exclude it. Since the parser appends ':' in its match, clarify here that GITLAB_REF_TICKET_LABEL should be the label text without the trailing colon (e.g. Jira, not Jira:).

Suggested change
gitlab_ref_ticket_label: "Jira" # optional: parse ticket IDs from "Jira:" field in GitLab MR description; empty disables parsing
gitlab_ref_ticket_label: "Jira" # optional: label text without trailing colon; parser matches "Jira:" field in GitLab MR description; empty disables parsing

Copilot uses AI. Check for mistakes.
Comment on lines +192 to +197
ticket = strings.TrimLeft(ticket, "#")
fieldPrefix := strings.TrimSpace(fieldLabel) + "-"
if fieldPrefix != "-" && len(ticket) >= len(fieldPrefix) && strings.EqualFold(ticket[:len(fieldPrefix)], fieldPrefix) {
ticket = ticket[len(fieldPrefix):]
}
ticket = strings.TrimSpace(strings.Trim(ticket, "[]"))
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

normalizeTicketToken trims surrounding brackets after stripping a leading '#'. Inputs like "[#7001005]" will keep the '#' because it isn’t at the start until after trimming brackets, so the function returns "#7001005" instead of "7001005". Consider trimming brackets first (and then removing a leading '#'/prefix), and add a unit test to cover the "[#123]" form.

Suggested change
ticket = strings.TrimLeft(ticket, "#")
fieldPrefix := strings.TrimSpace(fieldLabel) + "-"
if fieldPrefix != "-" && len(ticket) >= len(fieldPrefix) && strings.EqualFold(ticket[:len(fieldPrefix)], fieldPrefix) {
ticket = ticket[len(fieldPrefix):]
}
ticket = strings.TrimSpace(strings.Trim(ticket, "[]"))
// First, trim surrounding brackets so forms like "[#123]" are normalized correctly.
ticket = strings.Trim(ticket, "[]")
// Then, remove any leading '#' characters.
ticket = strings.TrimLeft(ticket, "#")
fieldPrefix := strings.TrimSpace(fieldLabel) + "-"
if fieldPrefix != "-" && len(ticket) >= len(fieldPrefix) && strings.EqualFold(ticket[:len(fieldPrefix)], fieldPrefix) {
ticket = ticket[len(fieldPrefix):]
}
ticket = strings.TrimSpace(ticket)

Copilot uses AI. Check for mistakes.
Comment on lines +157 to +166
for j := i + 1; j < len(lines); j++ {
next := strings.TrimSpace(lines[j])
if next == "" {
continue
}
if markdownHeadingRe.MatchString(next) {
break
}
raw = next
break
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the configured field label line has no inline value, the next non-empty line is taken verbatim as the raw ticket string. If the value is provided as a markdown list item (e.g. "- #123" or "* TRACKER-123"), normalizeTicketToken won’t strip the list marker and the stored ticket ID will include the leading "-"/"". Consider stripping leading list markers ("- ", " ") from the next-line value (or handling them in normalizeTicketToken) and add a unit test for that format.

Copilot uses AI. Check for mistakes.
Comment on lines +140 to +142
fieldRe := regexp.MustCompile(`(?i)^\s*(?:#{1,6}\s*)?(?:[-*]\s*)?(?:\*\*|__)?\s*` +
regexp.QuoteMeta(fieldLabel) + `\s*(?:\*\*|__)?\s*:\s*(.*)$`)

Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parseTicketIDsFromDescription compiles fieldRe with regexp.MustCompile on every call (i.e., once per MR). Since FetchMRs already computes ticketFieldLabel once, consider compiling the regexp once per fetch (or caching per label) to avoid repeated regexp compilation when importing large numbers of MRs.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant