Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
db13421
Generate PR to sync with the main branch
ChinthakaJ98 May 26, 2026
868263d
Merge pull request #544 from ChinthakaJ98/stable/mi
ChinthakaJ98 May 29, 2026
a3149e5
Support the startOnLoad attribute for tasks in MI 4.1.0
ChinthakaJ98 May 29, 2026
594ea94
Merge pull request #545 from ChinthakaJ98/task-startOnLoad
ChinthakaJ98 May 29, 2026
4d87824
Added mcp server section to the directory tree builder
Dulavinya May 4, 2026
bc0bc66
Preserve mcpServers in directory tree format conversion
Dulavinya May 9, 2026
b5f7617
Update golden test files
Dulavinya May 9, 2026
e4f83a2
Refactor Mcp Classification
Dulavinya May 9, 2026
9597c4e
Replace suffix-based MCP identification with content-based parsing
Dulavinya May 9, 2026
b0e8389
Restore MCP local entries without matching endpoints to local entries…
Dulavinya May 9, 2026
47feedd
Improve MCP server inbound implementation
arunans23 Jun 5, 2026
9094568
Fix issues in the MI Extension
ChinthakaJ98 Jun 5, 2026
1af0786
Merge pull request #547 from ChinthakaJ98/fix-issues-07
ChinthakaJ98 Jun 8, 2026
a0d15b2
Refactor code to avoid duplicate dom parsing for mcp inbound
arunans23 Jun 9, 2026
f5d63b4
Merge remote-tracking branch 'origin/stable/mi' into feature/mi-mcp-s…
arunans23 Jun 9, 2026
2e439a7
Merge pull request #546 from arunans23/feature/mi-mcp-server
arunans23 Jun 9, 2026
efbec66
Fix mcp tool response parsing issue
ChinthakaJ98 Jun 10, 2026
d5ca9ff
Merge pull request #548 from ChinthakaJ98/mcp-parsing
ChinthakaJ98 Jun 10, 2026
78b3ea5
Update LS version
ChinthakaJ98 Jun 10, 2026
0d5c7b3
Merge pull request #549 from ChinthakaJ98/stable/mi
ChinthakaJ98 Jun 10, 2026
699d638
Fix issues in the MI Extension
ChinthakaJ98 Jun 22, 2026
a927a5c
Merge pull request #551 from ChinthakaJ98/fix-issues-09
ChinthakaJ98 Jun 22, 2026
afc745e
Flag operator-precedence pitfalls and undefined vars in element text
IsuruMaduranga Jun 19, 2026
3515374
Report expression diagnostics on the synapse/codeDiagnostic path
IsuruMaduranga Jun 19, 2026
27ecb31
Flag unclosed ${ expression delimiters
IsuruMaduranga Jun 19, 2026
d9d2415
Add skipCrossFileValidation opt-out and refresh stale cross-file index
IsuruMaduranga Jun 23, 2026
976d299
Merge pull request #552 from IsuruMaduranga/fix/expression-precedence…
IsuruMaduranga Jun 24, 2026
8c411d2
Normalize path separators in artifact file-change cache invalidation
IsuruMaduranga Jun 25, 2026
05a7114
Add support to the binds-to attribute in APIs
ChinthakaJ98 Jun 25, 2026
8c4a64b
Merge pull request #553 from ChinthakaJ98/binding-inbound
ChinthakaJ98 Jun 26, 2026
c6bda6e
Merge pull request #554 from IsuruMaduranga/fix/windows-path-separato…
IsuruMaduranga Jun 26, 2026
fe9c36b
Update LS version
ChinthakaJ98 Jun 29, 2026
a4b8daf
Merge pull request #555 from ChinthakaJ98/stable/mi
ChinthakaJ98 Jun 29, 2026
3370e9e
Add Solace inbound-endpoint configuration
ChinthakaJ98 Jun 29, 2026
3663400
Change custom inbound-endpoints directory
ChinthakaJ98 Jul 3, 2026
7eab8b8
Fix solace description retrieving issue
ChinthakaJ98 Jul 3, 2026
a01b529
Merge pull request #557 from ChinthakaJ98/inbound-dir-change
ChinthakaJ98 Jul 3, 2026
1e2016b
Merge pull request #558 from ChinthakaJ98/fix-issues-10
ChinthakaJ98 Jul 3, 2026
84b6c7b
Update LS version
ChinthakaJ98 Jul 3, 2026
bbb48dd
Merge pull request #559 from ChinthakaJ98/stable/mi
ChinthakaJ98 Jul 3, 2026
f21ad7b
Handle inbound-endpoints with same ID
ChinthakaJ98 Jul 3, 2026
3c2aee9
Merge pull request #560 from ChinthakaJ98/fix-issues-11
ChinthakaJ98 Jul 3, 2026
fcb77e7
Update connector gen tool version
ChinthakaJ98 Jul 10, 2026
b1ddb2a
Merge pull request #562 from ChinthakaJ98/update-con-gen-tool
ChinthakaJ98 Jul 10, 2026
4d954ed
Add ASB inbound-endpoint
ChinthakaJ98 Jul 15, 2026
dd8ff8d
Update LS version
ChinthakaJ98 Jul 15, 2026
9f9efcf
Merge pull request #563 from ChinthakaJ98/add-asb-inbound
ChinthakaJ98 Jul 15, 2026
13d0567
Add inbound connector input variable suggestion support
thuva9872 Jul 20, 2026
d84648b
Fix coderabbit comments
thuva9872 Jul 20, 2026
e0b30a5
Replace string null checks with StringUtils
thuva9872 Jul 21, 2026
c59ffe6
Merge pull request #564 from thuva9872/inbound-variable
thuva9872 Jul 21, 2026
9c75568
Update OpenAPI spec generation process
ChinthakaJ98 Jul 21, 2026
ebe10b1
Merge pull request #565 from ChinthakaJ98/api-qparam
ChinthakaJ98 Jul 22, 2026
429d4ae
Update LS version
ChinthakaJ98 Jul 28, 2026
ef67879
Merge pull request #566 from ChinthakaJ98/stable/mi
ChinthakaJ98 Jul 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 39 additions & 7 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,43 @@ jobs:
name: ${{ steps.ls.outputs.fileName }}.zip
- name: Create a release in repo
run: |
createResponse=`curl -X POST -H "Accept: application/vnd.github.v3+json" \
-H "Authorization:token ${{ secrets.GIT_BOT_TOKEN }}" -d '{"tag_name":"v${{ steps.ls.outputs.version }}", \
"draft":false, "name": "Release v${{ steps.ls.outputs.version }}", "prerelease":true}' \
https://api.github.com/repos/${{ github.repository }}/releases` \
&& id=`echo "$createResponse" | sed -n -e 's/"id":\ \([0-9]\+\),/\1/p' | head -n 1 | sed 's/[[:blank:]]//g'` && \
uploadResponse=`curl -X POST -H "Authorization:token ${{ secrets.GIT_BOT_TOKEN }}" -H "Content-Type:application/octet-stream" \
set -euo pipefail
createResponse=$(curl --fail-with-body -X POST \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization:token ${{ secrets.GIT_BOT_TOKEN }}" \
-d '{"tag_name":"v${{ steps.ls.outputs.version }}", "draft":false, "name": "Release v${{ steps.ls.outputs.version }}", "prerelease":true}' \
https://api.github.com/repos/${{ github.repository }}/releases)
id=$(echo "$createResponse" | jq -r '.id // empty')
if [ -z "$id" ]; then
echo "Failed to parse release id from response:"
echo "$createResponse"
exit 1
fi
curl --fail-with-body -X POST \
-H "Authorization:token ${{ secrets.GIT_BOT_TOKEN }}" \
-H "Content-Type:application/octet-stream" \
--data-binary @${{ steps.ls.outputs.fileName }}.zip \
Comment on lines +54 to 65

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Pass workflow outputs through environment variables before shell use.

Use env vars and jq payload construction instead of expanding step outputs directly inside shell commands.

Proposed adjustment
     - name: Create a release in repo
+      env:
+        GIT_BOT_TOKEN: ${{ secrets.GIT_BOT_TOKEN }}
+        LS_VERSION: ${{ steps.ls.outputs.version }}
+        LS_FILE_NAME: ${{ steps.ls.outputs.fileName }}
       run: |
         set -euo pipefail
+        releasePayload=$(jq -n \
+          --arg tag "v${LS_VERSION}" \
+          --arg name "Release v${LS_VERSION}" \
+          '{tag_name: $tag, draft: false, name: $name, prerelease: true}')
         createResponse=$(curl --fail-with-body -X POST \
           -H "Accept: application/vnd.github.v3+json" \
-          -H "Authorization:token ${{ secrets.GIT_BOT_TOKEN }}" \
-          -d '{"tag_name":"v${{ steps.ls.outputs.version }}", "draft":false, "name": "Release v${{ steps.ls.outputs.version }}", "prerelease":true}' \
+          -H "Authorization:token ${GIT_BOT_TOKEN}" \
+          -d "$releasePayload" \
           https://api.github.com/repos/${{ github.repository }}/releases)
 ...
         curl --fail-with-body -X POST \
-          -H "Authorization:token ${{ secrets.GIT_BOT_TOKEN }}" \
+          -H "Authorization:token ${GIT_BOT_TOKEN}" \
           -H "Content-Type:application/octet-stream" \
-          --data-binary @${{ steps.ls.outputs.fileName }}.zip \
-          "https://uploads.github.com/repos/${{ github.repository }}/releases/$id/assets?name=${{ steps.ls.outputs.fileName }}.zip"
+          --data-binary @"${LS_FILE_NAME}.zip" \
+          "https://uploads.github.com/repos/${{ github.repository }}/releases/$id/assets?name=${LS_FILE_NAME}.zip"
     - name: Create sync PR from stable/mi to main
       if: github.ref == 'refs/heads/stable/mi'
       env:
         GH_TOKEN: ${{ secrets.GIT_BOT_TOKEN }}
+        LS_VERSION: ${{ steps.ls.outputs.version }}
 ...
-          --title "Sync stable/mi to main after release v${{ steps.ls.outputs.version }}" \
-          --body "Automated PR to sync \`stable/mi\` into \`main\` following the successful release of v${{ steps.ls.outputs.version }}."
+          --title "Sync stable/mi to main after release v${LS_VERSION}" \
+          --body "Automated PR to sync \`stable/mi\` into \`main\` following the successful release of v${LS_VERSION}."

As per path instructions, provide concise, actionable feedback focused on correctness and best practices.

Also applies to: 88-89

🧰 Tools
🪛 zizmor (1.26.1)

[info] 54-54: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)


[info] 54-54: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)


[info] 65-65: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)


[info] 65-65: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 54 - 65, The release workflow is
expanding step outputs directly inside shell commands instead of passing them
through environment variables first. Update the release job around the release
creation/upload logic to read values from env vars (for example the version and
file name from steps.ls.outputs) and build the JSON payload with jq rather than
inline string interpolation. Keep the curl and jq flow in the same release
creation/upload block so the shell only uses sanitized env-backed values.

Sources: Path instructions, Linters/SAST tools

https://uploads.github.com/repos/${{ github.repository }}/releases/$id/assets?name=${{ steps.ls.outputs.fileName }}.zip`
"https://uploads.github.com/repos/${{ github.repository }}/releases/$id/assets?name=${{ steps.ls.outputs.fileName }}.zip"

- name: Create sync PR from stable/mi to main
if: github.ref == 'refs/heads/stable/mi'
env:
GH_TOKEN: ${{ secrets.GIT_BOT_TOKEN }}
run: |
git fetch --unshallow origin main stable/mi 2>/dev/null || git fetch origin main stable/mi
commits=$(git rev-list --count origin/main..origin/stable/mi)
if [ "$commits" -eq 0 ]; then
echo "No new commits on stable/mi compared to main — skipping PR creation."
exit 0
fi
existing=$(gh pr list --repo ${{ github.repository }} --base main --head stable/mi --state open --json number --jq '.[0].number // empty')
if [ -n "$existing" ]; then
echo "An open PR from stable/mi to main already exists: #$existing"
exit 0
fi
gh pr create \
--repo ${{ github.repository }} \
--base main \
--head stable/mi \
--title "Sync stable/mi to main after release v${{ steps.ls.outputs.version }}" \
--body "Automated PR to sync \`stable/mi\` into \`main\` following the successful release of v${{ steps.ls.outputs.version }}."
4 changes: 2 additions & 2 deletions org.eclipse.lemminx/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<parent>
<groupId>org.wso2.language.server</groupId>
<artifactId>mi-language-server-parent</artifactId>
<version>0.24.0-wso2v90</version>
<version>0.24.0-wso2v95</version>
<relativePath>../pom.xml</relativePath>
</parent>
<name>MI Language Server</name>
Expand All @@ -15,7 +15,7 @@
<dev.build.timestamp>${maven.build.timestamp}</dev.build.timestamp>
<cbi.jarsigner.skip>true</cbi.jarsigner.skip>
<native.maven.plugin.version>0.9.16</native.maven.plugin.version>
<mi.connector.generator.version>0.9.10</mi.connector.generator.version>
<mi.connector.generator.version>0.9.11</mi.connector.generator.version>
<graalvm.static />
</properties>
<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@
import org.eclipse.lemminx.customservice.synapse.idp.PdfToImagesRequest;
import org.eclipse.lemminx.dom.DOMDocument;
import org.eclipse.lemminx.extensions.contentmodel.settings.XMLValidationSettings;
import org.eclipse.lemminx.extensions.synapse.SynapseDiagnosticsParticipant;
import org.eclipse.lemminx.services.extensions.completion.ICompletionResponse;
import org.eclipse.lemminx.settings.SharedSettings;
import org.eclipse.lemminx.uriresolver.URIResolverExtensionManager;
Expand Down Expand Up @@ -346,8 +347,21 @@ private PublishDiagnosticsParams doDiagnostics(DOMDocument xmlDocument, CancelCh
public CompletableFuture<PublishDiagnosticsParams> codeDiagnostic(CodeDiagnosticRequest param) {

return CompletableFuture.supplyAsync(() -> {
DOMDocument xmlDocument = Utils.getDOMDocument(param.getCode(), uriResolverExtensionManager);
return doDiagnostics(xmlDocument, NULL_CANCEL_CHECKER);
// Use the real file path (when supplied) as the document URI. Several diagnostics are
// gated on the document path — e.g. SynapseExpressionValidator only runs for files under
// src/main/wso2mi/artifacts — so the literal "temp" fallback would silently drop them.
// Treat a blank fileName as missing, otherwise an unusable URI would skip those checks.
String uri = StringUtils.isBlank(param.getFileName()) ? "temp" : param.getFileName();
// Opt-out (default off) for cross-file reference checks: the agent validates a file
// before its referenced siblings are written, so those checks would fire spuriously.
// Set/clear around doDiagnostics on this thread; the editor never sets it.
try {
SynapseDiagnosticsParticipant.setSkipCrossFileValidation(param.isSkipCrossFileValidation());
DOMDocument xmlDocument = Utils.getDOMDocument(param.getCode(), uri, uriResolverExtensionManager);
return doDiagnostics(xmlDocument, NULL_CANCEL_CHECKER);
} finally {
SynapseDiagnosticsParticipant.clearSkipCrossFileValidation();
}
});
}

Expand Down Expand Up @@ -1044,7 +1058,10 @@ public CompletableFuture<ConnectorGeneratorResponse> generateConnector(Connector
connectorGenReq.connectorProjectPath, projectServerVersion, projectUri);
}
} catch (Exception e) {
log.log(Level.SEVERE, "Error occurred while generating the connector", e);
String errorMsg = "Error occurred while generating the connector: " + e.getMessage();
log.log(Level.SEVERE, errorMsg, e);
ConnectorGeneratorResponse errorResponse = new ConnectorGeneratorResponse(false, null, errorMsg);
return CompletableFuture.supplyAsync(() -> errorResponse);
}
ConnectorGeneratorResponse response = new ConnectorGeneratorResponse(filePath != null, filePath);
return CompletableFuture.supplyAsync(() -> response);
Expand Down Expand Up @@ -1202,6 +1219,12 @@ public CompletableFuture<Either<ConnectorInfoResponse, String>> resolveConnector
});
}

@Override
public CompletableFuture<String> fetchInboundConnectors() {

return CompletableFuture.supplyAsync(() -> inboundConnectorHolder.getCustomInboundConnectors());
}

public String getProjectUri() {
return projectUri;
}
Expand Down Expand Up @@ -1233,7 +1256,8 @@ public void dispose() {

private void packHttpConnector() {

if (Utils.compareVersions(projectServerVersion, Constant.MI_440_VERSION) >= 0) {
if (Utils.compareVersions(projectServerVersion, Constant.MI_440_VERSION) >= 0
&& Utils.hasDependency(projectUri, Constant.HTTP_CONNECTOR_ARTIFACT_ID)) {
String projectId = new File(projectUri).getName() + "_" + Utils.getHash(projectUri);
String connectorDownloadPath = Path.of(System.getProperty(Constant.USER_HOME), Constant.WSO2_MI,
Constant.CONNECTORS, projectId, Constant.DOWNLOADED).toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.eclipse.lemminx.dom.DOMDocument;
import org.eclipse.lemminx.dom.DOMParser;
import org.eclipse.lemminx.extensions.contentmodel.settings.XMLValidationRootSettings;
import org.eclipse.lemminx.extensions.synapse.SynapseDiagnosticsParticipant;
import org.eclipse.lemminx.services.DocumentSymbolsResult;
import org.eclipse.lemminx.services.SymbolInformationResult;
import org.eclipse.lemminx.services.XMLLanguageService;
Expand Down Expand Up @@ -599,7 +600,14 @@ public CompletableFuture<List<ColorPresentation>> colorPresentation(ColorPresent
public void didSave(DidSaveTextDocumentParams params) {
computeAsync((monitor) -> {
// A document was saved, collect documents to revalidate
SaveContext context = new SaveContext(params.getTextDocument().getUri());
String savedUri = params.getTextDocument().getUri();
// LSP document URIs use '/', but normalize defensively so a backslash path also matches on Windows.
if (savedUri != null && savedUri.replace('\\', '/').contains("src/main/wso2mi")) {
// An artifact/resource file was saved — drop the cached cross-file index so the
// revalidation below (and sibling files) sees the updated set instead of stale data.
SynapseDiagnosticsParticipant.invalidateArtifactIndexCache();
}
SaveContext context = new SaveContext(savedUri);
doSave(context);

// Manage didSave document lifecycle participants
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import org.eclipse.lemminx.commons.WorkspaceFolders;
import org.eclipse.lemminx.customservice.synapse.utils.Constant;
import org.eclipse.lemminx.extensions.synapse.SynapseDiagnosticsParticipant;
import org.eclipse.lemminx.services.extensions.commands.IXMLCommandService;
import org.eclipse.lsp4j.DidChangeConfigurationParams;
import org.eclipse.lsp4j.DidChangeWatchedFilesParams;
Expand Down Expand Up @@ -94,11 +95,19 @@ public void didChangeWatchedFiles(DidChangeWatchedFilesParams params) {
.getTextDocumentService();
List<FileEvent> changes = params.getChanges();
for (FileEvent change : changes) {
if (change.getUri().contains(Constant.INBOUND_CONNECTORS_DIR) && change.getUri().contains(".zip")) {
if ((change.getUri().contains(Constant.INBOUND_ENDPOINTS)
|| change.getUri().contains(Constant.INBOUND_CONNECTORS_DIR)) && change.getUri().contains(".zip")) {
((SynapseLanguageService) xmlLanguageServer.getSynapseLanguageService()).updateInboundConnectors();
} else if (change.getUri().contains(Constant.CONNECTORS) && change.getUri().contains(".zip")) {
((SynapseLanguageService) xmlLanguageServer.getSynapseLanguageService()).updateConnectors();
} else {
// LSP URIs use '/', but normalize defensively so a backslash path also matches on Windows.
if (change.getUri().replace('\\', '/').contains("src/main/wso2mi")) {
// An artifact/resource file changed on disk — drop the cached cross-file index so
// the next diagnostics run rebuilds it (otherwise a just-written sibling stays
// "unresolved" for up to the cache TTL).
SynapseDiagnosticsParticipant.invalidateArtifactIndexCache();
}
if (!xmlTextDocumentService.documentIsOpen(change.getUri())) {
xmlTextDocumentService.doSave(change.getUri());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -359,4 +359,7 @@ CompletableFuture<DriverMavenCoordinatesResponse> getDriverMavenCoordinates(

@JsonRequest
CompletableFuture<Either<InboundEndpointInfo, String>> getInboundInfo(InboundInfoRequest request);

@JsonRequest
CompletableFuture<String> fetchInboundConnectors();
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
public class CodeDiagnosticRequest {

private String code;
private String fileName;
private boolean skipCrossFileValidation;

public String getCode() {

Expand All @@ -27,4 +29,30 @@ public void setCode(String code) {

this.code = code;
}

public String getFileName() {

return fileName;
}

public void setFileName(String fileName) {

this.fileName = fileName;
}

/**
* When true, cross-file reference checks (which depend on other artifact files existing) are
* skipped for this request. Defaults to false, so the editor and the explicit "validate all"
* path are unaffected. The MI Copilot agent sets it for per-file auto-validation after a write,
* where a referenced sibling artifact may not exist on disk yet.
*/
public boolean isSkipCrossFileValidation() {

return skipCrossFileValidation;
}

public void setSkipCrossFileValidation(boolean skipCrossFileValidation) {

this.skipCrossFileValidation = skipCrossFileValidation;
}
}
Loading
Loading