Modify file location according to new structure - #129
Conversation
Co-authored-by: Haritha Hasathcharu <42366642+hasathcharu@users.noreply.github.com>
Co-authored-by: Haritha Hasathcharu <42366642+hasathcharu@users.noreply.github.com>
Co-authored-by: Haritha Hasathcharu <42366642+hasathcharu@users.noreply.github.com>
Co-authored-by: Haritha Hasathcharu <42366642+hasathcharu@users.noreply.github.com>
Co-authored-by: Haritha Hasathcharu <42366642+hasathcharu@users.noreply.github.com>
📝 WalkthroughOverviewReorganizes and completes the GitHub Issues to Salesforce integration sample under the new directory structure ( Key ChangesIntegration Implementation
Configuration & Metadata
Documentation & Setup
Project Structure
Technical Details
WalkthroughThis PR adds a complete GitHub Issues to Salesforce Case integration sample package. The sample includes a Ballerina webhook listener that receives GitHub issue events, filters by configured trigger labels, extracts issue details, and creates corresponding Salesforce Case records with field mapping and a custom GitHub issue URL field. Supporting files include configuration schema, setup instructions, type definitions, client initialization, and comprehensive documentation. Additionally, a reference to a new Sequence DiagramsequenceDiagram
actor GitHub
participant Listener as Ballerina Listener
participant Service as Issues Service
participant Salesforce as Salesforce API
GitHub->>Listener: POST webhook (IssuesEvent)
Listener->>Service: onLabeled(payload)
Service->>Service: Extract label name
Service->>Service: Check if label in triggerLabels
alt Label matches
Service->>Service: Extract issue details<br/>(title, body, url)
Service->>Service: Build SalesforceCase<br/>with caseConfig
Service->>Salesforce: create(Case, sObject)
alt Success
Salesforce-->>Service: Case ID
Service-->>Listener: Success
else Error
Salesforce-->>Service: Error response<br/>(401/400/other)
Service->>Service: Log error<br/>with status code
Service-->>Listener: error("Failed to create...")
end
else Label not matched
Service-->>Listener: No action
end
Listener-->>GitHub: Response
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 0/1 reviews remaining, refill in 60 minutes.Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
integrator-default-profile/samples/github-issue-to-salesforce/main.bal (1)
81-84: ⚡ Quick winPrefer direct typed access over unsafe
map<anydata>cast forstatusCode.
err.detail()is assigned tomap<anydata>, anderrorDetail["statusCode"](which returnsanydata, inclusive of()in Ballerina) is then cast with<int>. This cast panics at runtime if the key is absent or the value is not anint. Sinceerr is http:ApplicationResponseErroris already established,err.detail()returns a typed record withstatusCode: int— access it directly.♻️ Proposed refactor
- map<anydata> errorDetail = err.detail(); - int statusCode = <int>errorDetail["statusCode"]; + int statusCode = err.detail().statusCode;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@integrator-default-profile/samples/github-issue-to-salesforce/main.bal` around lines 81 - 84, Replace the unsafe map<anydata> cast and index access by capturing err.detail() into a typed record and read the statusCode field directly: since you already checked err is http:ApplicationResponseError, assign the detail to a record variable (e.g. `var detail = err.detail();` or declare a record type with `statusCode: int` and do `YourDetailType detail = err.detail();`) and then use `detail.statusCode` to get the int instead of `<int>errorDetail["statusCode"]`.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@integrator-default-profile/samples/github-issue-to-salesforce/.choreo/diagram.md`:
- Line 4: The diagram includes a decision node D ("Is repository in
githubRepositories?") but the configuration lacks a githubRepositories field;
either add githubRepositories to githubConfig (update config.bal and
config-schema.json to declare it and its type) and document it in
instructions.md so the diagram's repository filter is configurable, or remove
node D from diagram.md so it matches the current githubConfig (webhookSecret and
triggerLabels) and instructions; update whichever files you change
(githubConfig, config.bal, config-schema.json, instructions.md, diagram.md) to
keep diagram and config in sync.
In `@integrator-default-profile/samples/github-issue-to-salesforce/README.md`:
- Around line 53-69: The README lists flat configuration keys that don't match
the structured Ballerina config record in config.bal; update the README to
either (1) replace flat keys with the structured TOML keys under the
salesforceConfig and caseConfig records (e.g., salesforceConfig.baseUrl,
clientId, clientSecret, refreshToken, refreshUrl and caseConfig.status,
priority, recordType, ownerId) so local Config.toml users can copy/paste correct
keys, or (2) explicitly state that the flat names are only for the Devant UI and
show both representations (Devant flat names and the corresponding config.bal
record/TOML keys) so readers know which to use when testing locally or via the
UI. Ensure you reference the config.bal records salesforceConfig and caseConfig
in the README text.
- Around line 49-51: Add documentation for the required
githubConfig.webhookSecret under the "GitHub Configurations" section: explain
that webhookSecret is a required string used to validate incoming GitHub
webhooks and must match the secret configured in GitHub, show the config key
name webhookSecret (as referenced in config.bal) and note that main.bal uses it
to initialize the GitHub listener; include a short example value placeholder and
a one-line note about keeping it secret.
In `@integrator-default-profile/samples/github-issue-to-salesforce/types.bal`:
- Line 15: The struct/record field named default is a reserved keyword and must
be escaped; update the field declaration in types.bal from boolean default; to
use the quoted identifier ('default) and then update all references to this
field throughout the module to use 'default (e.g., in constructors, accesses,
JSON mapping, or serialization code) so the code compiles; ensure any pattern
matches or JSON keys that relied on unquoted default are adjusted to the quoted
identifier or mapped appropriately.
---
Nitpick comments:
In `@integrator-default-profile/samples/github-issue-to-salesforce/main.bal`:
- Around line 81-84: Replace the unsafe map<anydata> cast and index access by
capturing err.detail() into a typed record and read the statusCode field
directly: since you already checked err is http:ApplicationResponseError, assign
the detail to a record variable (e.g. `var detail = err.detail();` or declare a
record type with `statusCode: int` and do `YourDetailType detail =
err.detail();`) and then use `detail.statusCode` to get the int instead of
`<int>errorDetail["statusCode"]`.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e58682de-4f5f-4c90-b559-e4459f76af2b
📒 Files selected for processing (15)
.github/workflows/projects.jsonintegrator-default-profile/samples/github-issue-to-salesforce/.choreo/component.yamlintegrator-default-profile/samples/github-issue-to-salesforce/.choreo/config-schema.jsonintegrator-default-profile/samples/github-issue-to-salesforce/.choreo/diagram.mdintegrator-default-profile/samples/github-issue-to-salesforce/.choreo/instructions.mdintegrator-default-profile/samples/github-issue-to-salesforce/.gitignoreintegrator-default-profile/samples/github-issue-to-salesforce/Ballerina.tomlintegrator-default-profile/samples/github-issue-to-salesforce/README.mdintegrator-default-profile/samples/github-issue-to-salesforce/agents.balintegrator-default-profile/samples/github-issue-to-salesforce/config.balintegrator-default-profile/samples/github-issue-to-salesforce/connections.balintegrator-default-profile/samples/github-issue-to-salesforce/data_mappings.balintegrator-default-profile/samples/github-issue-to-salesforce/functions.balintegrator-default-profile/samples/github-issue-to-salesforce/main.balintegrator-default-profile/samples/github-issue-to-salesforce/types.bal
| A(["Begin"]):::startNode | ||
| B["Receive GitHub Webhook Event"]:::processNode | ||
| C{"Is label in <br/> triggerLabels?"}:::decisionNode | ||
| D{"Is repository in <br/> githubRepositories?"}:::decisionNode |
There was a problem hiding this comment.
githubRepositories referenced in diagram but missing from configuration.
Decision node D ("Is repository in githubRepositories?") implies a repository-based filter, but githubConfig in config.bal and config-schema.json only defines webhookSecret and triggerLabels — there is no githubRepositories field. The instructions.md likewise omits it as a configurable option.
Either add githubRepositories to githubConfig (and the schema) if this filtering is intended, or remove node D from the diagram.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@integrator-default-profile/samples/github-issue-to-salesforce/.choreo/diagram.md`
at line 4, The diagram includes a decision node D ("Is repository in
githubRepositories?") but the configuration lacks a githubRepositories field;
either add githubRepositories to githubConfig (update config.bal and
config-schema.json to declare it and its type) and document it in
instructions.md so the diagram's repository filter is configurable, or remove
node D from diagram.md so it matches the current githubConfig (webhookSecret and
triggerLabels) and instructions; update whichever files you change
(githubConfig, config.bal, config-schema.json, instructions.md, diagram.md) to
keep diagram and config in sync.
| ### GitHub Configurations | ||
| - `triggerLabels` - List of labels that trigger case creation | ||
| (e.g., `["bug", "support"]`) |
There was a problem hiding this comment.
webhookSecret is missing from the GitHub Configurations section.
githubConfig.webhookSecret (defined in config.bal line 3) is required for the GitHub listener initialization in main.bal line 5, but is not documented. Users will be unable to configure the integration correctly without knowing this value is required.
📝 Suggested addition
### GitHub Configurations
+- `webhookSecret` - Secret token used to validate incoming GitHub webhook payloads
- `triggerLabels` - List of labels that trigger case creation
(e.g., `["bug", "support"]`)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@integrator-default-profile/samples/github-issue-to-salesforce/README.md`
around lines 49 - 51, Add documentation for the required
githubConfig.webhookSecret under the "GitHub Configurations" section: explain
that webhookSecret is a required string used to validate incoming GitHub
webhooks and must match the secret configured in GitHub, show the config key
name webhookSecret (as referenced in config.bal) and note that main.bal uses it
to initialize the GitHub listener; include a short example value placeholder and
a one-line note about keeping it secret.
| ### Salesforce Credentials | ||
| - `salesforceBaseUrl` - Your Salesforce instance URL | ||
| (e.g., `https://your-instance.my.salesforce.com`) | ||
| - `salesforceClientId` - Your Salesforce Connected App/External Client App Client ID | ||
| - `salesforceClientSecret` - Your Salesforce Connected App/External Client App Client Secret | ||
| - `salesforceRefreshToken` - Your Salesforce OAuth refresh token | ||
| - `salesforceRefreshUrl` - Your Salesforce OAuth token endpoint | ||
| (e.g., `https://login.salesforce.com/services/oauth2/token` for production or | ||
| `https://test.salesforce.com/services/oauth2/token` for sandbox) | ||
|
|
||
| ### Salesforce Case Defaults | ||
| - `caseStatus` - Default status for created cases (e.g., `"New"`) | ||
| - `casePriority` - Default priority for created cases | ||
| (e.g., `"Medium"`) | ||
| - `caseRecordType` - Default type for created cases | ||
| (e.g., `"User"`) | ||
| - `caseOwnerId` - Salesforce User ID or Queue ID to assign cases to |
There was a problem hiding this comment.
Configuration key names do not match the actual Ballerina configurable record structure.
The README uses flat aliases (e.g., salesforceBaseUrl, caseStatus, caseOwnerId) that do not correspond to the actual field names in config.bal. For local Config.toml-based configuration, the keys are structured under record sections. For example:
[salesforceConfig]
baseUrl = "..."
clientId = "..."
clientSecret = "..."
refreshToken = "..."
refreshUrl = "..."
[caseConfig]
status = "New"
priority = "Medium"
recordType = "User"
ownerId = "..."If the flat names are intentional for the Devant UI configuration screen, clarify this distinction so developers testing locally know the correct TOML structure.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@integrator-default-profile/samples/github-issue-to-salesforce/README.md`
around lines 53 - 69, The README lists flat configuration keys that don't match
the structured Ballerina config record in config.bal; update the README to
either (1) replace flat keys with the structured TOML keys under the
salesforceConfig and caseConfig records (e.g., salesforceConfig.baseUrl,
clientId, clientSecret, refreshToken, refreshUrl and caseConfig.status,
priority, recordType, ownerId) so local Config.toml users can copy/paste correct
keys, or (2) explicitly state that the flat names are only for the Devant UI and
show both representations (Devant flat names and the corresponding config.bal
record/TOML keys) so readers know which to use when testing locally or via the
UI. Ensure you reference the config.bal records salesforceConfig and caseConfig
in the README text.
| // 6-character hex code, without the leading #, identifying the color | ||
| string color; | ||
| // Whether this label comes by default in a new repository | ||
| boolean default; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify all usages of the `default` field on Label values in the codebase
# to confirm they also need updating to 'default
rg -n "\.default\b" --type bal -A2 -B2Repository: wso2/integration-samples
Length of output: 96
🏁 Script executed:
# First, locate and examine the specific file mentioned in the review
fd -i "types.bal" -x head -20 {}Repository: wso2/integration-samples
Length of output: 14042
🏁 Script executed:
# Search for .default usages in .bal files without using invalid --type argument
fd -e bal -x grep -n "\.default\b" {} + 2>/dev/null || trueRepository: wso2/integration-samples
Length of output: 50
🌐 Web query:
Ballerina programming language reserved keywords escaping single quote
💡 Result:
In Ballerina, single quotes do not “escape” reserved keywords in general strings. Instead, reserved keywords can be used as identifiers (variable/field names) by using a quoted identifier: prefix the keyword with a single quote, e.g. 'resource, 'function, or 'K. For example, if resource is a reserved keyword, field access uses the quoted identifier form: - j2.'resource This is described in the Ballerina language specification under the QuotedIdentifier syntax (single quote preceding a reserved keyword).
Citations:
- 1: https://ballerina.io/spec/lang/master
- 2: https://stackoverflow.com/questions/77177356/how-to-access-reserved-keywords-in-json-attributes
🏁 Script executed:
fd "types.bal" -x wc -l {} \;Repository: wso2/integration-samples
Length of output: 15826
🏁 Script executed:
fd "types.bal" -x cat -n {} \; | grep -A2 -B2 "boolean default"Repository: wso2/integration-samples
Length of output: 210
🏁 Script executed:
# Check if the file path from review exists
find . -path "*integrator-default-profile/samples/github-issue-to-salesforce/types.bal" -type fRepository: wso2/integration-samples
Length of output: 142
Field name default must be quoted with single quote prefix — reserved keyword will cause compilation failure.
The field declaration boolean default; uses a reserved keyword without proper escaping. Per the Ballerina language specification, reserved keywords used as identifiers must be preceded by a single quote (e.g., 'default). This code will fail to compile as written.
Fix
- boolean default;
+ boolean 'default;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| boolean default; | |
| boolean 'default; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@integrator-default-profile/samples/github-issue-to-salesforce/types.bal` at
line 15, The struct/record field named default is a reserved keyword and must be
escaped; update the field declaration in types.bal from boolean default; to use
the quoted identifier ('default) and then update all references to this field
throughout the module to use 'default (e.g., in constructors, accesses, JSON
mapping, or serialization code) so the code compiles; ensure any pattern matches
or JSON keys that relied on unquoted default are adjusted to the quoted
identifier or mapped appropriately.
Purpose