Skip to content

slack-bot add optional Activity Type to Slack modals and Jira filing#5115

Open
deepsm007 wants to merge 1 commit intoopenshift:mainfrom
deepsm007:slack-modals-activity-type-defaults
Open

slack-bot add optional Activity Type to Slack modals and Jira filing#5115
deepsm007 wants to merge 1 commit intoopenshift:mainfrom
deepsm007:slack-modals-activity-type-defaults

Conversation

@deepsm007
Copy link
Copy Markdown
Contributor

@deepsm007 deepsm007 commented Apr 20, 2026

/cc @openshift/test-platform

Summary by CodeRabbit

  • New Features

    • Added an optional "Activity Type" selection to all issue-reporting modals (bug, consultation, incident, enhancement) with sensible per-modal defaults.
    • Activity Type values are captured and included when creating Jira issues; Jira custom-field use can be configured.
  • Tests

    • Added tests validating allowed Activity Type values and updated modal submission fixtures.

@openshift-ci openshift-ci bot requested a review from a team April 20, 2026 14:08
@openshift-merge-bot
Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: automatic mode

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 20, 2026

Walkthrough

Adds an "Activity Type" selection to Slack modals, validates allowed values, threads a CLI-configurable Jira custom field ID into the IssueFiler, and includes the activity type when creating Jira issues across bug, consultation, enhancement, and incident flows.

Changes

Cohort / File(s) Summary
CLI Configuration
cmd/slack-bot/main.go
Added --jira-activity-type-custom-field flag and pass-through to jira.NewIssueFiler(...).
Jira Activity Type
pkg/jira/activity_type.go, pkg/jira/activity_type_test.go
Introduce ActivityTypeCustomFieldKey, AllowedActivityTypes, and IsValidActivityType(...) with tests for allowed/empty/unknown values.
Jira Filing API & Fake
pkg/jira/issues.go, pkg/jira/fake.go
Extended IssueFiler.FileIssue(...) and NewIssueFiler(...) signatures to accept activityType and activityTypeCustomField; validate activity type, conditionally populate Jira unknowns field; updated fake to include ActivityType in IssueRequest.
Slack UI Component
pkg/slack/modals/activity_type.go
New ActivityTypeInputBlock(initial string), block ID constant, and activity-type option constants/options helper.
Modal Views
pkg/slack/modals/bug/view.go, pkg/slack/modals/consultation/view.go, pkg/slack/modals/enhancement/view.go, pkg/slack/modals/incident/view.go
Inserted activity-type input block into each modal, added conditional activity-type section to Jira templates, and included block ID in submitted Fields.
Modal Handlers
pkg/slack/modals/handlers.go
Added ActivityTypeBlockID to JiraIssueParameters, activityTypeFromCallback(...) helper, updated ToJiraIssue to extract and forward activityType to FileIssue.
Tests & Payloads
pkg/slack/modals/*_view_test.go, pkg/slack/modals/payload_test.go
Updated test fixtures and expected modal payloads to include activity_type block and an ActivityType field in expected jira.IssueRequest payloads.
Module Metadata
go.mod
Removed // indirect marker for github.com/trivago/tgo v1.0.7.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant SlackModal
    participant Handler
    participant Validator
    participant IssueFiler
    participant Jira

    User->>SlackModal: Fill form (select Activity Type + fields)
    SlackModal->>Handler: Submit payload
    Handler->>Handler: Extract values (including ActivityType)
    Handler->>Validator: IsValidActivityType(value)
    Validator-->>Handler: valid / invalid
    Handler->>IssueFiler: FileIssue(..., activityType, ...)
    IssueFiler->>IssueFiler: Validate & set custom field (if configured)
    IssueFiler->>Jira: Create issue request (includes custom field)
    Jira-->>IssueFiler: Issue created
    IssueFiler-->>Handler: Success
    Handler-->>SlackModal: Acknowledge
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 9 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (9 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and directly summarizes the main change: adding an optional Activity Type feature to Slack modals and Jira filing, which aligns with the changeset's core modifications across multiple modal types and Jira integration.
Stable And Deterministic Test Names ✅ Passed The custom check for stable and deterministic Ginkgo test names is not applicable to this PR, which exclusively uses standard Go testing package with static, descriptive test names.
Test Structure And Quality ✅ Passed Repository uses standard Go testing with *testing.T and table-driven tests, not Ginkgo BDD framework. Check requirements are inapplicable.
Microshift Test Compatibility ✅ Passed This PR adds only standard Go unit tests using the testing package, not Ginkgo e2e tests, so no MicroShift compatibility concerns apply.
Single Node Openshift (Sno) Test Compatibility ✅ Passed This pull request does not add any Ginkgo e2e tests; all test files are standard Go unit tests using the testing package.
Topology-Aware Scheduling Compatibility ✅ Passed This pull request does not introduce any deployment manifests, operators, controllers, or code that creates Kubernetes scheduling constraints. All changes are contained within a Slack bot integration application.
Ote Binary Stdout Contract ✅ Passed The PR introduces new activity type support for Slack modals and Jira filing without violating the OTE Binary Stdout Contract. All logging uses logrus exclusively with no direct stdout writes.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed This PR contains only standard Go unit tests for a Slack bot feature, not Ginkgo e2e tests.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Apr 20, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
pkg/slack/modals/activity_type.go (1)

20-38: Minor: Unnecessary variable assignment in loop.

The assignment v := o on line 31 is redundant since o is already a string value (not a pointer or reference type). You can use o directly.

♻️ Suggested simplification
 func activityTypeSelectOptions() []*slack.OptionBlockObject {
 	opts := []string{
 		ActivityTypeAssociateWellness,
 		ActivityTypeFutureSustainability,
 		ActivityTypeQualityStabilityReliability,
 		ActivityTypeProductPortfolioWork,
 		ActivityTypeSecurityCompliance,
 		ActivityTypeIncidentsSupport,
 	}
 	out := make([]*slack.OptionBlockObject, 0, len(opts))
 	for _, o := range opts {
-		v := o
 		out = append(out, &slack.OptionBlockObject{
-			Text:  &slack.TextBlockObject{Type: slack.PlainTextType, Text: v},
-			Value: v,
+			Text:  &slack.TextBlockObject{Type: slack.PlainTextType, Text: o},
+			Value: o,
 		})
 	}
 	return out
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/slack/modals/activity_type.go` around lines 20 - 38, In
activityTypeSelectOptions, remove the redundant loop variable assignment v := o
and use o directly when building the slack.OptionBlockObject (replace usages of
v with o); this simplifies the loop in activityTypeSelectOptions and avoids an
unnecessary local variable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/slack/modals/activity_type.go`:
- Around line 20-38: In activityTypeSelectOptions, remove the redundant loop
variable assignment v := o and use o directly when building the
slack.OptionBlockObject (replace usages of v with o); this simplifies the loop
in activityTypeSelectOptions and avoids an unnecessary local variable.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 853e6733-ca65-42a4-a510-cfbf51fbbfec

📥 Commits

Reviewing files that changed from the base of the PR and between 4be58f4 and 35e5221.

📒 Files selected for processing (16)
  • cmd/slack-bot/main.go
  • pkg/jira/activity_type.go
  • pkg/jira/activity_type_test.go
  • pkg/jira/fake.go
  • pkg/jira/issues.go
  • pkg/slack/modals/activity_type.go
  • pkg/slack/modals/bug/view.go
  • pkg/slack/modals/bug/view_test.go
  • pkg/slack/modals/consultation/view.go
  • pkg/slack/modals/consultation/view_test.go
  • pkg/slack/modals/enhancement/view.go
  • pkg/slack/modals/enhancement/view_test.go
  • pkg/slack/modals/handlers.go
  • pkg/slack/modals/incident/view.go
  • pkg/slack/modals/incident/view_test.go
  • pkg/slack/modals/payload_test.go

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Apr 20, 2026
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci bot commented Apr 20, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: deepsm007, Prucek

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-merge-bot
Copy link
Copy Markdown
Contributor

/retest-required

Remaining retests: 0 against base HEAD 4be58f4 and 2 for PR HEAD 35e5221 in total

@deepsm007
Copy link
Copy Markdown
Contributor Author

/retest-required

@openshift-merge-bot
Copy link
Copy Markdown
Contributor

/retest-required

Remaining retests: 0 against base HEAD fb45e8f and 1 for PR HEAD 35e5221 in total

@deepsm007
Copy link
Copy Markdown
Contributor Author

/retest-required

@deepsm007 deepsm007 force-pushed the slack-modals-activity-type-defaults branch from 35e5221 to 6e84cd5 Compare April 21, 2026 01:44
@openshift-ci openshift-ci bot removed the lgtm Indicates that a PR is ready to be merged. label Apr 21, 2026
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci bot commented Apr 21, 2026

New changes are detected. LGTM label has been removed.

@deepsm007 deepsm007 force-pushed the slack-modals-activity-type-defaults branch from 6e84cd5 to 75d387c Compare April 21, 2026 01:44
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
pkg/slack/modals/activity_type.go (1)

29-36: Minor: Unnecessary variable copy.

The local variable v := o on line 31 is unnecessary since o is already a string value (not a loop variable capturing a pointer). You can use o directly in the struct literal.

♻️ Suggested simplification
 	out := make([]*slack.OptionBlockObject, 0, len(opts))
 	for _, o := range opts {
-		v := o
 		out = append(out, &slack.OptionBlockObject{
-			Text:  &slack.TextBlockObject{Type: slack.PlainTextType, Text: v},
-			Value: v,
+			Text:  &slack.TextBlockObject{Type: slack.PlainTextType, Text: o},
+			Value: o,
 		})
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/slack/modals/activity_type.go` around lines 29 - 36, The loop in
activity_type.go creates an unnecessary local copy v := o before building each
*slack.OptionBlockObject; remove the redundant assignment and use the loop
variable o directly when constructing the TextBlockObject and Value (i.e.,
replace references to v with o in the loop that produces out :=
make([]*slack.OptionBlockObject, ...) so you only append
&slack.OptionBlockObject{ Text: &slack.TextBlockObject{Type:
slack.PlainTextType, Text: o}, Value: o }).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/jira/issues.go`:
- Around line 98-110: The Jira custom select field is being set using
jira.Option (in the block guarded by activityType != "" and
f.activityTypeCustomField) but go-jira expects a map with "id" or "value" keys;
update the assignment to toCreate.Fields.Unknowns[f.activityTypeCustomField] =
map[string]interface{}{"value": activityType} (keeping the existing Nil-check
that creates tcontainer.NewMarshalMap()) so the custom field is serialized in
the correct format.

---

Nitpick comments:
In `@pkg/slack/modals/activity_type.go`:
- Around line 29-36: The loop in activity_type.go creates an unnecessary local
copy v := o before building each *slack.OptionBlockObject; remove the redundant
assignment and use the loop variable o directly when constructing the
TextBlockObject and Value (i.e., replace references to v with o in the loop that
produces out := make([]*slack.OptionBlockObject, ...) so you only append
&slack.OptionBlockObject{ Text: &slack.TextBlockObject{Type:
slack.PlainTextType, Text: o}, Value: o }).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a5f13037-02f6-4660-a662-d5d85f11cb81

📥 Commits

Reviewing files that changed from the base of the PR and between 35e5221 and 75d387c.

📒 Files selected for processing (17)
  • cmd/slack-bot/main.go
  • go.mod
  • pkg/jira/activity_type.go
  • pkg/jira/activity_type_test.go
  • pkg/jira/fake.go
  • pkg/jira/issues.go
  • pkg/slack/modals/activity_type.go
  • pkg/slack/modals/bug/view.go
  • pkg/slack/modals/bug/view_test.go
  • pkg/slack/modals/consultation/view.go
  • pkg/slack/modals/consultation/view_test.go
  • pkg/slack/modals/enhancement/view.go
  • pkg/slack/modals/enhancement/view_test.go
  • pkg/slack/modals/handlers.go
  • pkg/slack/modals/incident/view.go
  • pkg/slack/modals/incident/view_test.go
  • pkg/slack/modals/payload_test.go
✅ Files skipped from review due to trivial changes (3)
  • pkg/slack/modals/consultation/view_test.go
  • pkg/jira/activity_type_test.go
  • pkg/jira/activity_type.go
🚧 Files skipped from review as they are similar to previous changes (7)
  • pkg/slack/modals/bug/view_test.go
  • pkg/slack/modals/bug/view.go
  • pkg/slack/modals/enhancement/view_test.go
  • pkg/slack/modals/handlers.go
  • pkg/slack/modals/payload_test.go
  • pkg/jira/fake.go
  • pkg/slack/modals/enhancement/view.go

Comment thread pkg/jira/issues.go
Comment on lines +98 to +110
if activityType != "" {
if !IsValidActivityType(activityType) {
return nil, fmt.Errorf("invalid activity type %q: must be one of the configured Slack options", activityType)
}
if f.activityTypeCustomField == "" {
logger.WithField("activity_type", activityType).Warn("Activity Type is set but Jira custom field id is not configured; omitting from Jira API request")
} else {
if toCreate.Fields.Unknowns == nil {
toCreate.Fields.Unknowns = tcontainer.NewMarshalMap()
}
toCreate.Fields.Unknowns[f.activityTypeCustomField] = jira.Option{Value: activityType}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

go-jira library custom field select option format

💡 Result:

In the go-jira library (github.com/andygrunwald/go-jira), custom fields, including select options, are handled via the IssueFields.Unknowns field, which is a tcontainer.MarshalMap from github.com/trivago/tgo. For a single-select custom field, set the value as a map with the "id" or "value" key matching the option's ID or display value: unknowns := tcontainer.NewMarshalMap unknowns["customfield_XXXXX"] = map[string]string{"id": "12345"} // or unknowns["customfield_XXXXX"] = map[string]string{"value": "Option Display Name"} Then assign to the issue: i := jira.Issue{ Fields: &jira.IssueFields{ // ... other fields ... Unknowns: unknowns, }, } This matches Jira REST API format for select fields: {"id": "optionId"} or {"value": "optionValue"}. For reading values from existing issues, use issue.Fields.Unknowns.Value("customfield_XXXXX") or issue.GetCustomField("customfield_XXXXX"). Note: v2 is in development with better custom field support, but current stable (v1.x) uses this approach. Use tcontainer.NewMarshalMap instead of plain map[string]interface{} for proper JSON marshaling of nested objects.

Citations:


Fix custom field format for Jira select fields.

The code uses jira.Option{Value: activityType}, but the go-jira library expects custom select fields to be set as a map with "id" or "value" keys. Change to:

toCreate.Fields.Unknowns[f.activityTypeCustomField] = map[string]interface{}{"value": activityType}

The current implementation will fail when creating issues because jira.Option is not the correct format for the Jira REST API.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/jira/issues.go` around lines 98 - 110, The Jira custom select field is
being set using jira.Option (in the block guarded by activityType != "" and
f.activityTypeCustomField) but go-jira expects a map with "id" or "value" keys;
update the assignment to toCreate.Fields.Unknowns[f.activityTypeCustomField] =
map[string]interface{}{"value": activityType} (keeping the existing Nil-check
that creates tcontainer.NewMarshalMap()) so the custom field is serialized in
the correct format.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants