[Automated] Sync master after 2201.13.6 release - #6411
[Automated] Sync master after 2201.13.6 release#6411ballerina-cicd-bot wants to merge 177 commits into
Conversation
Update License file
[2201.13.x] Update observei version
[Automated] Sync master after 2201.13.0 release
Update mcp and ai version
Update lang version
Add entries to trivy ignore
[Automated] Sync master after 2201.13.1 release
Include sticky and offline flags for bbe tests
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Bump the lang version for 2201.13.5 release
Bump the http, tcp version for 2201.13.5 release
[2201.13.x] Update the ftp version to 2.20.1
…ion-20260722 Update lang version
Update stdlibEdiVersion and stdlibFtpVersion
[Automated] Sync master after 2201.13.5 release
…ities-2201.13.x Add trivy ignore entries for jackson and netty CVEs
📝 WalkthroughWalkthroughThe release updates synchronize workflow commands, dependency metadata, example build behavior, logging rotation samples, XML conversion examples, MCP APIs, documentation, and integration-test registration. ChangesRelease baseline
Example build and registration
Logging examples
Example API and data conversions
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1⚔️ Resolve merge conflicts 💡
🧪 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. Comment |
|
|
|
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (1)
examples/logger-from-config/logger_from_config.bal (1)
7-14: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winInitialize each configured logger once.
Line 34 and Line 44 call
log:fromConfigfor every processed event. The new file-backed configurations therefore create another registered logger for each call. The log API registers everyfromConfiglogger and auto-generates an ID whenidis omitted. Reuse one logger per configuration after initialization. This prevents registry growth with event volume. (ballerina.io)Also applies to: 21-28
🤖 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 `@examples/logger-from-config/logger_from_config.bal` around lines 7 - 14, Initialize each configured logger once instead of calling log:fromConfig for every event. Update the event-processing flow around the two log:fromConfig call sites to create and retain one logger per configuration, then reuse that logger for subsequent writes while preserving the existing configured destinations and rotation settings.
🤖 Prompt for all review comments with 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.
Inline comments:
In @.github/workflows/publish-release.yml:
- Around line 118-121: Update the setup-node step at
.github/workflows/publish-release.yml:118-121 from actions/setup-node@v2 to a
supported major version, and update the setup-dotnet step at
.github/workflows/publish-release.yml:702-706 from actions/setup-dotnet@v1 to a
supported major version before the release workflow runs.
In @.trivyignore:
- Around line 8-22: Remove the listed Jackson and Netty vulnerability IDs from
the `.trivyignore` suppression entries so Trivy blocks releases until the
dependencies are upgraded. Do not replace them with broad or permanent
exceptions; any temporary workaround must be package-scoped and expiring.
In `@ballerina/build.gradle`:
- Around line 964-966: Update outputVerification to derive additionalBuildParams
from bbe.needCentral and pass the resulting offline options to its bal run
invocation, matching the existing buildBBE behavior. Ensure needCentral: false
uses the same --sticky --offline parameters during output verification.
- Around line 964-966: Update the platform-specific execution flow around
ExecSpec.commandLine so `bal build` and `bal test` run in separate exec calls
rather than overwriting one another. Capture each command’s exit status,
propagate failure when either command fails, and ensure `exitVal` reflects build
or test failure.
In `@ballerina/LICENSE`:
- Around line 167-171: Regenerate the ballerina license inventory from the
dependencies resolved by gradle.properties and build.gradle, replacing stale
FTP, Log, Crypto, and HTTP versions. Ensure the same generation updates the
related compiler and native artifact rows, rather than editing only the
displayed entries manually.
In `@examples/custom-logger/custom_logger.bal`:
- Around line 63-69: Update withContext(...) and the child logger implementation
so child contexts retain a reference to the parent logger instead of copying
parentLevel. Make child getLevel(...) delegate to that parent, and make child
setLevel(...) return the unsupported-operation error, preserving the inherited
parent-level contract.
- Around line 20-29: Update the custom logger’s level handling in setLevel and
the print* methods so emissions below the configured log:Level are suppressed
before calling the standard log API. Ensure setLevel(log:ERROR) prevents
printInfo, printWarn, and printDebug from forwarding while preserving
higher-severity logging.
In `@examples/logger-from-config/logger_from_config.bal`:
- Around line 21-28: Align the metrics destination’s retention metadata with its
rotation settings: update maxBackupFiles in the destinations configuration to 30
for 30-day daily retention, or change the associated retention context value to
match seven backups. Preserve the existing rotation policy and ensure the
resulting configuration accurately describes retention when log writes trigger
rotation.
---
Nitpick comments:
In `@examples/logger-from-config/logger_from_config.bal`:
- Around line 7-14: Initialize each configured logger once instead of calling
log:fromConfig for every event. Update the event-processing flow around the two
log:fromConfig call sites to create and retain one logger per configuration,
then reuse that logger for subsequent writes while preserving the existing
configured destinations and rotation settings.
🪄 Autofix
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 Plus
Run ID: ad21b4e1-8011-4d11-a115-82188c5a959c
⛔ Files ignored due to path filters (8)
examples/log-file-rotation/app_log_rotation.outis excluded by!**/*.outexamples/log-file-rotation/log_file_rotation.outis excluded by!**/*.outexamples/logger-from-config/audit_logs.outis excluded by!**/*.outexamples/logger-from-config/logger_from_config.outis excluded by!**/*.outexamples/logger-from-config/metrics_logs.outis excluded by!**/*.outexamples/xml-from-json-conversion/xml_from_json_conversion.outis excluded by!**/*.outexamples/xml-to-json-conversion/xml_to_json_conversion.outis excluded by!**/*.outexamples/xml-to-record-conversion/xml_to_record_conversion.outis excluded by!**/*.out
📒 Files selected for processing (36)
.github/workflows/publish-release.yml.trivyignoreballerina-test-automation/gradle.propertiesballerina/LICENSEballerina/build.gradlebuild.gradleexamples/azure-functions-cosmosdb-trigger/azure_functions_cosmosdb_trigger.mdexamples/custom-logger/custom_logger.balexamples/http-access-logs/Config.tomlexamples/http-access-logs/http_access_logs.mdexamples/http-trace-logs/Config.tomlexamples/http-trace-logs/http_trace_logs.mdexamples/index.jsonexamples/log-file-rotation/Config.tomlexamples/log-file-rotation/log_file_rotation.balexamples/log-file-rotation/log_file_rotation.mdexamples/log-file-rotation/log_file_rotation.metatagsexamples/logger-from-config/logger_from_config.balexamples/logger-from-config/logger_from_config.mdexamples/logging-configuration/Config.tomlexamples/logging-configuration/logging_configuration.mdexamples/mcp-service-advanced/mcp_service_advanced.balexamples/natural-expressions/natural_expressions.mdexamples/string-templates/string_templates.mdexamples/xml-from-json-conversion/xml_from_json_conversion.balexamples/xml-from-json-conversion/xml_from_json_conversion.mdexamples/xml-from-record-conversion/xml_from_record_conversion.balexamples/xml-from-record-conversion/xml_from_record_conversion.mdexamples/xml-to-json-conversion/xml_to_json_conversion.balexamples/xml-to-json-conversion/xml_to_json_conversion.mdexamples/xml-to-record-conversion/xml_to_record_conversion.balexamples/xml-to-record-conversion/xml_to_record_conversion.mdgradle.propertiesstdlib-integration-tests/index.jsonstdlib-integration-tests/library_package_test/Ballerina.tomlstdlib-integration-tests/library_package_test/main.bal
| - name: Set up Node.js | ||
| uses: actions/setup-node@v2 | ||
| with: | ||
| node-version: '14' | ||
| node-version: "14" |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow occurrences =="
if [ -f .github/workflows/publish-release.yml ]; then
nl -ba .github/workflows/publish-release.yml | sed -n '100,130p;692,710p'
echo "== action action.yml/deprecated mentions =="
rg -n "setup-node@|setup-dotnet@|node-version:|java-version:|dotnet-version:" .github/workflows/publish-release.yml || true
else
echo "workflow file missing"
fi
echo
echo "== GitHub API refs/tags if gh available =="
if command -v gh >/dev/null 2>&1; then
echo "setup-node v2:"
gh api repos/actions/setup-node/git/refs/tags/v2 --jq '{ref:.ref,type:.object.type,target_sha:(if .object.type=="tag" then "delegated" else .object.sha end)}' || true
echo "setup-dotnet v1:"
gh api repos/actions/setup-dotnet/git/refs/tags/v1 --jq '{ref:.ref,type:.object.type,target_sha:(if .object.type=="tag" then "delegated" else .object.sha end)}' || true
else
echo "gh not available"
fi
echo
echo "== workflow YAML parser check =="
python3 - <<'PY'
from pathlib import Path
p=Path(".github/workflows/publish-release.yml")
if not p.exists():
raise SystemExit(0)
text=p.read_text()
for needle in ["actions/setup-node@v2", "actions/setup-dotnet@v1"]:
print(f"{needle}: {text.count(needle)}")
PYRepository: ballerina-platform/ballerina-distribution
Length of output: 246
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow occurrences =="
if [ -f .github/workflows/publish-release.yml ]; then
nl -ba .github/workflows/publish-release.yml | sed -n '100,130p;692,710p'
echo "== action action.yml/deprecated mentions =="
rg -n "setup-node@|setup-dotnet@|node-version:|java-version:|dotnet-version:" .github/workflows/publish-release.yml || true
else
echo "workflow file missing"
fi
echo
echo "== GitHub API refs/tags if gh available =="
if command -v gh >/dev/null 2>&1; then
echo "setup-node v2:"
gh api repos/actions/setup-node/git/refs/tags/v2 --jq '{ref:.ref,type:.object.type,target_sha:(if .object.type=="tag" then "delegated" else .object.sha end)}' || true
echo "setup-dotnet v1:"
gh api repos/actions/setup-dotnet/git/refs/tags/v1 --jq '{ref:.ref,type:.object.type,target_sha:(if .object.type=="tag" then "delegated" else .object.sha en
d)}' || true
else
echo "gh not available"
fi
echo
echo "== workflow YAML parser check =="
python3 - <<'PY'
from pathlib import Path
p=Path(".github/workflows/publish-release.yml")
if not p.exists():
raise SystemExit(0)
text=p.read_text()
for needle in ["actions/setup-node@v2", "actions/setup-dotnet@v1"]:
print(f"{needle}: {text.count(needle)}")
PYRepository: ballerina-platform/ballerina-distribution
Length of output: 246
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== check presence =="
test -f .github/workflows/publish-release.yml && echo "present" || echo "missing"
echo "== search occurrences with grep =="
grep -nE "actions/setup-node|actions/setup-dotnet|node-version:|java-version:|dotnet-version:" .github/workflows/publish-release.yml || true
echo "== line-numbered snippets with awk =="
awk 'NR>=108 && NR<=124 {printf "%6d %s\n", NR, $0}' .github/workflows/publish-release.yml
awk 'NR>=696 && NR<=708 {printf "%6d %s\n", NR, $0}' .github/workflows/publish-release.yml
echo
echo "== repository action occurrences in workflows =="
grep -RnE "actions/(setup-node|setup-dotnet)@" .github/workflows || true
echo
echo "== GitHub API refs/tags if gh available =="
if command -v gh >/dev/null 2>&1; then
echo "setup-node v2:"
gh api repos/actions/setup-node/git/refs/tags/v2 --jq '{ref:.ref,type:.object.type,target_sha:(if .object.type=="tag" then "delegated" else .object.sha end)}' || true
echo "setup-dotnet v1:"
gh api repos/actions/setup-dotnet/git/refs/tags/v1 --jq '{ref:.ref,type:.object.type,target_sha:(if .object.type=="tag" then "delegated" else .object.sha end)}' || true
else
echo "gh not available"
fi
echo
echo "== workflow presence check =="
python3 - <<'PY'
from pathlib import Path
text = Path(".github/workflows/publish-release.yml").read_text()
for needle in ["actions/setup-node@v2", "actions/setup-dotnet@v1"]:
print(f"{needle}: {text.count(needle)}")
PYRepository: ballerina-platform/ballerina-distribution
Length of output: 2876
🌐 Web query:
actions/setup-node v2 legacy runner node runtime deprecated
💡 Result:
The actions/setup-node v2 action is effectively deprecated and highly recommended against for use in GitHub Actions workflows [1][2]. The primary reasons for its deprecation are: 1. Unsupported Node.js Runtime: The v2 version of the action relies on Node 12 as its underlying execution runtime [1][3][4]. Node 12 reached end-of-life (EOL) years ago and is no longer supported or secure [1]. 2. Deprecated Cache Service: The action uses an outdated implementation of the GitHub Actions cache service (@actions/cache), which has been subject to permanent shutdowns and brownout events [2]. This frequently causes workflows to fail during dependency installation [2]. To maintain secure and reliable CI/CD pipelines, you should update your workflows to the latest version of setup-node (currently v4 or later) [1][2][5]. Modern versions of this action use updated Node.js runtimes (such as Node 20 or Node 24) and the current, supported cache service [1][6][7].
Citations:
- 1: outdated actions/setup-node@v2 uses unsupported node12 pnpm/pnpm.io#560
- 2: Errors out on npm cache (no changes, worked fine until now) actions/setup-node#1275
- 3: actions/setup-node@v2...v3.0.0
- 4: Breaking changes from v2 to v3 actions/setup-node#617
- 5: Node 16 deprecation actions/setup-node#850
- 6: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
- 7: https://github.com/actions/setup-node
🌐 Web query:
actions/setup-dotnet v1 legacy runner deprecation unsupported
💡 Result:
The actions/setup-dotnet v1 action is long deprecated and should not be used in modern GitHub Actions workflows [1]. GitHub Actions and their supporting official actions rely on the underlying runner's environment (Node.js version, platform, etc.) to function [2][3]. As actions evolve—such as moving from older Node.js versions (e.g., node12/16/20) to newer ones like node24—the runners must support these newer requirements [2][3]. Key points regarding the deprecation and transition: 1. Version v1 is obsolete: Users encountering issues with v1 (such as warnings about unexpected inputs or failing workflows) are advised to migrate to newer, supported major versions [1]. As of August 2026, the action is on version 5+ [2][3]. 2. Node.js Compatibility: Newer versions of actions/setup-dotnet (e.g., v5.0.0 and above) require updated runners (v2.327.1 or later) to handle upgraded internal requirements like Node.js 24 [2][3]. 3. Why V1 fails: Older actions often contain deprecated dependencies or rely on environment behaviors that have changed significantly since 2019/2021 [4][3]. 4. Recommended Action: You should update your workflow files to use the latest major version (e.g., uses: actions/setup-dotnet@v5 or newer) to ensure compatibility with GitHub's current hosted runner environment [2][5]. If you are seeing "unsupported" or "deprecated" errors, it is a direct consequence of using an outdated version of the action that is no longer tested or maintained against current GitHub runner software [4][3].
Citations:
- 1: Warning: Unexpected input 'dotnet-version' actions/setup-dotnet#90
- 2: https://github.com/actions/setup-dotnet?tab=readme-ov-file
- 3: https://github.com/actions/setup-dotnet/releases/tag/v5.0.0
- 4: https://github.com/actions/setup-dotnet/releases
- 5: https://github.com/actions/setup-dotnet/
Replace the deprecated setup actions.
Both actions/setup-node@v2 and actions/setup-dotnet@v1 are legacy major versions. Update these steps to supported action majors before running the release workflow.
🧰 Tools
🪛 actionlint (1.7.12)
[error] 119-119: the runner of "actions/setup-node@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
📍 Affects 1 file
.github/workflows/publish-release.yml#L118-L121(this comment).github/workflows/publish-release.yml#L702-L706
🤖 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/publish-release.yml around lines 118 - 121, Update the
setup-node step at .github/workflows/publish-release.yml:118-121 from
actions/setup-node@v2 to a supported major version, and update the setup-dotnet
step at .github/workflows/publish-release.yml:702-706 from
actions/setup-dotnet@v1 to a supported major version before the release workflow
runs.
Source: Linters/SAST tools
| CVE-2026-56740 | ||
| CVE-2026-56741 | ||
|
|
||
| # jackson-core / jackson-databind - needs dependency upgrade to 2.18.8+/2.21.4+ | ||
| GHSA-r7wm-3cxj-wff9 | ||
| CVE-2026-54512 | ||
| CVE-2026-54513 | ||
| CVE-2026-54514 | ||
| CVE-2026-54515 | ||
| CVE-2026-59888 | ||
| CVE-2026-59889 | ||
| GHSA-mhm7-754m-9p8w | ||
|
|
||
| # netty-transport-native-epoll / netty-transport-native-kqueue - needs dependency upgrade to 4.1.135.Final/4.2.15.Final+ | ||
| CVE-2026-45536 |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -C 2 'Need to be fixed|CVE-2026-(56740|56741|54512|54513|54514|54515|59888|59889|45536)' .trivyignore
rg -n 'jackson-(core|databind)-2\.18\.0|netty-(transport|handler|codec)-4\.1\.126\.Final' ballerina/LICENSE
rg -n -C 3 'trivy-action|exit-code' .github/workflows/publish-release.ymlRepository: ballerina-platform/ballerina-distribution
Length of output: 1882
🌐 Web query:
Trivy .trivyignore CVE ID suppression YAML ignore-file expiry PURL documentation
💡 Result:
Trivy supports vulnerability suppression using both a legacy plain-text .trivyignore file and an experimental, structured .trivyignore.yaml file [1][2]. YAML Ignore-File (.trivyignore.yaml) This structured format allows for more granular control over ignored findings by categorizing them into vulnerabilities, misconfigurations, secrets, or licenses [1]. Because this feature is currently experimental, you must explicitly specify the path to your YAML ignore file using the --ignorefile flag (e.g., trivy image --ignorefile.trivyignore.yaml...) [1][2]. Key features of.trivyignore.yaml: - CVE ID Suppression: You can list IDs under their respective categories [1]. - PURL Support: You can restrict suppression to specific packages using the purls field, which accepts a list of Package URLs [1][3][4]. This is currently available only for vulnerabilities [1][3]. - Expiry: You can define an expiration date for an ignore entry using the expired_at field (format: yyyy-mm-dd) [1][5]. Once the date passes, the finding will no longer be ignored [5]. - Statement: An optional field to document the reasoning for the suppression (not used for active filtering) [1][5]. Example structure: vulnerabilities: - id: CVE-2023-3817 purls: - "pkg:deb/debian/libssl1.1" expired_at: 2026-12-31 statement: "Waiting for patch upstream" Legacy Plain-Text (.trivyignore) The legacy format supports simple ID-based suppression [1][5]. It also supports expiration dates by appending exp:yyyy-mm-dd to the line [6][7]. Example: CVE-2019-14697 exp:2026-12-31 Important Note: As of April 2026, development is underway to make the id field optional in.trivyignore.yaml, which would allow users to ignore all findings matching specific PURLs or paths without listing individual IDs [8]. Always check your specific version of Trivy documentation for the most accurate feature support [1].
Citations:
- 1: https://trivy.dev/docs/latest/configuration/filtering/
- 2: feat: add support for .trivyignore.yaml aquasecurity/trivy#5070
- 3: aquasecurity/trivy@cd3e4bcac
- 4: Prepare for v0.50.0 aquasecurity/trivy#6306
- 5: https://github.com/aquasecurity/trivy/blob/main/pkg/result/ignore.go
- 6: feat: allow expiration date for .trivyignore entries aquasecurity/trivy#2332
- 7: Ignoring Vulnerabilities for a Period of Time aquasecurity/trivy#2991
- 8: feat(ignore): make id optional in .trivyignore.yaml to ignore all findings for a PURL/path aquasecurity/trivy#10583
Security Misconfiguration (CWE-693)
Reachability: Internal
Do not suppress vulnerabilities that need fixes.
The CVE IDs in .trivyignore are active suppression rules; the section comments do not exempt them. The release workflow runs Trivy with exit-code: "1", so these entries let affected findings pass without blocking the release. Remove these IDs until the Jackson and Netty dependencies are patched. If a temporary exception is needed, use an expiring, package-scoped override only and remove it before the next release.
🤖 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 @.trivyignore around lines 8 - 22, Remove the listed Jackson and Netty
vulnerability IDs from the `.trivyignore` suppression entries so Trivy blocks
releases until the dependencies are upgraded. Do not replace them with broad or
permanent exceptions; any temporary workaround must be package-scoped and
expiring.
| if (!bbe.needCentral) { | ||
| additionalParams += " --sticky --offline" | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Apply offline options during output verification.
outputVerification runs before buildBBE and invokes bal run without --offline. A sample that requires Central can populate the cache during output verification, then pass the later offline build. This makes needCentral: false ineffective for examples with output verification.
Derive additionalBuildParams from bbe.needCentral inside outputVerification and pass the same offline options to bal run.
🤖 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 `@ballerina/build.gradle` around lines 964 - 966, Update outputVerification to
derive additionalBuildParams from bbe.needCentral and pass the resulting offline
options to its bal run invocation, matching the existing buildBBE behavior.
Ensure needCentral: false uses the same --sticky --offline parameters during
output verification.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '960,983p' ballerina/build.gradleRepository: ballerina-platform/ballerina-distribution
Length of output: 1217
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '1,1200p' ballerina/build.gradle | nl -ba | sed -n '930,1005p'Repository: ballerina-platform/ballerina-distribution
Length of output: 219
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== surrounding buildBBE usage =="
rg -n "buildBBE|outputVerification|buildBBE\\(" ballerina/build.gradle
echo "== buildBBE implementation =="
python3 - <<'PY'
from pathlib import Path
p=Path('ballerina/build.gradle')
lines=p.read_text().splitlines()
for i in range(max(0,930-1), min(len(lines),975)):
print(f"{i+1}: {lines[i]}")
PY
echo "== Gradle ExecSpec docs in installed Gradle, if present =="
if command -v gradle >/dev/null 2>&1; then
gradle --version | head -3
else
echo "gradle command not present"
fi
echo "== deterministic parser check of commandLine call semantics in Groovy =="
python3 - <<'PY'
# Gradle Groovy closures are Java-style methods where each call is evaluated;
# the documented ExecSpec.commandLine(String[]) sets the complete command line,
# so a second call replaces the first.
print("If ExecSpec.commandLine sets the whole command line, two sequential calls keep only the second.")
PYRepository: ballerina-platform/ballerina-distribution
Length of output: 2860
🌐 Web query:
Gradle ExecSpec.commandLine sets full command line documentation
💡 Result:
In the Gradle API, the commandLine method in the ExecSpec interface is used to set the full command line for an execution process, including both the executable itself and any associated arguments [1][2]. Key technical details regarding commandLine: Functionality: It replaces any existing executable or arguments previously set on the ExecSpec object with the new sequence provided [1][3]. Inputs: It accepts multiple formats to define the command line, including varargs (Object...), an Iterable, or a List [1][2][3]. Difference from args: While commandLine sets the entire execution string (executable + arguments), the args method is used solely to add additional arguments to an already specified executable [1][4]. Usage Example: In a Gradle task, you might use it as follows: task myExec(type: Exec) { // Sets both the executable and its arguments commandLine 'cmd.exe', '/c', 'my-script.bat' } This will configure the task to execute cmd.exe with the arguments /c and my-script.bat [4][5].
Citations:
- 1: https://docs.gradle.org/current/javadoc/org/gradle/process/ExecSpec.html
- 2: https://docs.gradle.org/current/kotlin-dsl/gradle/org.gradle.process/-exec-spec/index.html
- 3: https://github.com/gradle/gradle/blob/master/subprojects/core-api/src/main/java/org/gradle/process/ExecSpec.java
- 4: https://docs.gradle.org/current/dsl/org.gradle.api.tasks.Exec.html
- 5: https://docs.gradle.org/current/kotlin-dsl/gradle/org.gradle.api.tasks/-exec/index.html
Run build and test in separate exec calls.
ExecSpec.commandLine replaces the full command line, so the second call in each platform branch discards the bal build command. As written, only bal test runs, and exitVal cannot report a build failure. Call them separately and fail the example when either command fails.
🤖 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 `@ballerina/build.gradle` around lines 964 - 966, Update the platform-specific
execution flow around ExecSpec.commandLine so `bal build` and `bal test` run in
separate exec calls rather than overwriting one another. Capture each command’s
exit status, propagate failure when either command fails, and ensure `exitVal`
reflects build or test failure.
| ballerina-time-2.8.0.jar jar apache2 | ||
| ballerina-ftp-2.15.1.jar jar apache2 | ||
| ballerina-ai.intelligence-1.7.0.jar jar apache2 | ||
| ballerina-ai.observe-1.7.0.jar jar apache2 | ||
| ballerina-ai-1.7.0.jar jar apache2 |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Regenerate the release license inventory.
gradle.properties resolves newer FTP, Log, Crypto, and HTTP versions, but this inventory records older versions. The released license notice will not describe the dependency set that build.gradle packages.
Generate this file from the resolved release dependencies. Update the related compiler and native artifact rows in the same generation step.
Also applies to: 219-225, 253-254
🤖 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 `@ballerina/LICENSE` around lines 167 - 171, Regenerate the ballerina license
inventory from the dependencies resolved by gradle.properties and build.gradle,
replacing stale FTP, Log, Crypto, and HTTP versions. Ensure the same generation
updates the related compiler and native artifact rows, rather than editing only
the displayed entries manually.
| public isolated function getLevel() returns log:Level { | ||
| lock { | ||
| return self.level; | ||
| } | ||
| } | ||
|
|
||
| public isolated function setLevel(log:Level level) returns error? { | ||
| lock { | ||
| self.level = level; | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show the repository-declared Ballerina and log-module versions.
fd -a -t f 'Ballerina.toml|Dependencies.toml|gradle.properties' . | sort | while IFS= read -r file; do
echo "===== ${file} ====="
sed -n '1,180p' "$file"
done
# Inspect every ApplicationLogger emission path and level access.
rg -n -C 8 'ApplicationLogger|function (getLevel|setLevel|printDebug|printInfo|printWarn|printError)' \
examples/custom-loggerRepository: ballerina-platform/ballerina-distribution
Length of output: 20304
🌐 Web query:
ballerina log API custom Logger setLevel Level printInfo does not check log:Level
💡 Result:
The statement that the Ballerina log API's print functions do not check the log level is incorrect based on official documentation [1][2][3]. The Ballerina log module is designed to filter log messages based on the effective log level of the logger being used [1][3]. When you call a logging function such as log:printInfo(), the implementation automatically checks the logger's effective log level against the level of the message being sent [1][2]. If the message level is lower than the configured effective log level, the message is suppressed [1][3]. Regarding runtime configuration: - Global and custom loggers (created via log:fromConfig) allow setting and modifying the log level at runtime using the setLevel() method [1][2][4]. - Child loggers (created via withContext) do not support setLevel(); they always inherit the effective log level from their parent logger [2][5]. If you attempt to call setLevel() on a child logger, it will return an error [2][4]. - The log:getLevel() function correctly returns the effective log level, which for child loggers is the level inherited from the parent [2]. If you find that logs are being printed when they should be suppressed, ensure that the log level is configured correctly (e.g., in Config.toml using [ballerina.log] level = "...") [1][6] and that you are using the appropriate logger instance for your context [1][3]. Outdated configurations or incorrect module-level settings are common causes for unexpected logging behavior [6].
Citations:
- 1: https://central.ballerina.io/ballerina/log/latest
- 2: https://ballerina.io/spec/log/
- 3: https://github.com/ballerina-platform/module-ballerina-log
- 4: https://context7.com/ballerina-platform/ballerina-dev-website/llms.txt
- 5: Add native support for modifying the log level programmatically at runtime ballerina-library#6213
- 6: https://stackoverflow.com/questions/75090819/configured-log-level-is-not-working-as-expected
🌐 Web query:
ballerina spec log Logger interfaces getLevel setLevel printInfo Level
💡 Result:
In Ballerina, the log module provides the Logger interface to manage application logging [1][2]. The primary logging functions available on a Logger instance include printDebug, printInfo, printWarn, and printError [1][3]. Regarding the specific methods for log level management: - getLevel: This method returns the effective Level of the logger instance [2][3]. For root and custom loggers created via configuration, it returns the explicitly set level, while for child loggers, it returns the level inherited from the parent logger [2]. - setLevel(Level level): This method updates the log level of a logger at runtime [2][3]. It is supported for root loggers and custom loggers (e.g., those created via log:fromConfig) [4][5]. It typically returns an error if the operation is unsupported, such as when attempting to set the level on a child logger, which is designed to inherit its level from its parent [2][4]. The supported log levels, in descending order of priority, are ERROR, WARN, INFO, and DEBUG [1][5][6]. By default, the system logs at the INFO level and above [5][6]. Runtime log level modification allows for updating loggers registered in the logger registry without restarting the application [5].
Citations:
- 1: https://github.com/ballerina-platform/module-ballerina-log
- 2: https://ballerina.io/spec/log/
- 3: [Proposal][Discussion] Native support for modifying the log level programmatically at runtime via ICP ballerina-spec#1424
- 4: Add native support for modifying the log level programmatically at runtime ballerina-library#6213
- 5: https://central.ballerina.io/ballerina/log/latest
- 6: https://learn-ballerina.github.io/best_practices/logging.html
🌐 Web query:
site:ballerina.io/spec/log printInfo custom logger setLevel level
💡 Result:
In the context of the Ballerina programming language logging library, the setLevel(Level level) function is used to update the log level of a root or custom logger at runtime [1]. Key behavioral details for setLevel include: - Functionality: It updates the log level for the specific logger instance [1]. - Return Value: It returns an error? type, which may indicate an unsupported operation if called incorrectly [1]. - Limitations on Child Loggers: The setLevel function cannot be called directly on child loggers, as they inherit their log level from their parent [1]. Attempting to call setLevel on a child logger will result in an error [1]. To modify the effective log level of a child logger, you must instead call setLevel on its parent logger [1]. While the term printInfo appears as a specific logging method (e.g., printInfo(string|PrintableRawTemplate msg,...)) within the Ballerina log library for logging informational messages, it is distinct from the configuration methods like setLevel used to manage logger behavior [1].
Citations:
🌐 Web query:
ballerina log printInfo checks Logger getSetLevel before emitting
💡 Result:
Yes, the Ballerina log:printInfo function (and other similar logging functions like printDebug, printWarn, and printError) implicitly checks the logger's effective log level before emitting a log message [1][2]. When you call a logging function, the underlying implementation verifies whether the configured log level of the logger is sufficient to permit the message based on its severity (e.g., INFO level logs will not be emitted if the logger is set to WARN or ERROR) [2][3]. To optimize performance and avoid unnecessary computation for logs that will not be emitted—such as constructing complex strings or executing heavy functions—it is a best practice to use lazy evaluation techniques [3]. Specifically, you can pass functions (function pointers) as key-value pairs [3]. If the current effective log level is lower than the severity of the log call, the log module will skip the execution of those function pointers [3]. For example, if you have a printDebug call that includes a heavy computation, passing it as a function ensures the computation only occurs if the DEBUG level is actually enabled: log:printDebug("Checking the duration", duration = isolated function returns float { return heavyComputation; }); In this example, if the logger's level is set to INFO or higher, the function inside the key-value pair will not be executed [3].
Citations:
- 1: https://ballerina.io/spec/log/
- 2: https://github.com/ballerina-platform/module-ballerina-log
- 3: https://learn-ballerina.github.io/best_practices/logging.html
🌐 Web query:
"ballerina" "Logger interface" "printDebug" "LogLevel" "setLevel"
💡 Result:
In Ballerina, the log module provides a Logger object type that defines the interface for logging messages, including the printDebug method and runtime level management via setLevel [1][2]. The Logger interface provides the following primary methods for logging and managing log levels: Logging Methods You can log messages at the DEBUG level using the printDebug method [1][2]: public isolated function printDebug(string|PrintableRawTemplate msg, error? 'error =, error:StackFrame[]? stackTrace =, *KeyValues keyValues); Similar methods exist for other levels, such as printInfo, printWarn, and printError [1][3]. Runtime Log Level Management The Logger interface includes methods to retrieve and modify the log level at runtime [1]: - getLevel: Returns the effective LogLevel of the logger [1]. - setLevel(Level level): Sets the log level for the logger at runtime [1]. Runtime Modification via Logger Registry For loggers created via log:fromConfig, you can discover and update their log levels at runtime using the logger registry, without restarting the application [4][5]: 1. Access the registry: log:LoggerRegistry registry = log:getLoggerRegistry; [4] 2. Lookup the logger by its ID: log:Logger? logger = registry.getById("your-logger-id"); [4] 3. Update the level: check logger.setLevel(log:DEBUG); [4] Note that log levels for child loggers (created via withContext) are inherited from their parent and cannot be changed independently, and per-module log levels configured via Config.toml are static [4][5].
Citations:
- 1: https://ballerina.io/spec/log/
- 2: Contextual logging proposal discussion ballerina-spec#1322
- 3: [Proposal][Discussion] Native support for modifying the log level programmatically at runtime via ICP ballerina-spec#1424
- 4: https://central.ballerina.io/ballerina/log/latest
- 5: https://central.ballerina.io/ballerina/log/2.17.0
🌐 Web query:
"Ballina" "setLevel" "log" "printInfo" "check"
💡 Result:
In the Ballerina programming language, the log module provides logging functionality with configurable log levels [1][2]. The relevant functions and methods you mentioned are part of this library's API [1][3]. Core Logging Functions The Ballerina log module includes four primary functions to log messages at specific levels [1][2]: * log:printDebug * log:printInfo * log:printWarn * log:printError Runtime Log Level Management You can manage log levels at runtime for specific loggers [1][2]. If you have a log:Logger instance, you can use the following methods [1][2]: * setLevel(Level level): Sets the log level for that logger at runtime [1][2]. It returns an error if the operation is not supported (e.g., on child loggers) [1][2]. * getLevel: Returns the currently effective log level for the logger [1][2]. Configuration * Default Behavior: By default, the system logs messages at the INFO level and above [2][3]. * Static Configuration: You can configure log levels globally or per module using a Config.toml file [2][4]. Note that log levels defined in Config.toml are static and apply at startup [2]. * Runtime Configuration: Loggers created via log:fromConfig can be registered and updated at runtime using setLevel() [2]. Child loggers (created via withContext) inherit their level from the parent and cannot have their level changed independently [1][2]. For further details, consult the official Ballerina log module documentation [1][2].
Citations:
- 1: https://ballerina.io/spec/log/
- 2: https://central.ballerina.io/ballerina/log/latest
- 3: https://github.com/ballerina-platform/module-ballerina-log
- 4: https://learn-ballerina.github.io/best_practices/logging.html
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate any local/log repository sources or docs under the checkout.
printf '%s\n' "===== candidate log documentation/source files ====="
git ls-files | rg 'log($|/)|module-ballerina-log|Ballerina\.toml|ModuleDescription\.toml' | head -200
printf '\n===== file-level indicators about log implementation/spec =====\n'
rg -n 'printDebug|printInfo|printWarn|printError|LogLevel|enum Logger|class Logger|interface Logger|setLevel|getLevel' -g '*.bal' -g '*.md' -g '*.toml' . | head -300Repository: ballerina-platform/ballerina-distribution
Length of output: 37469
Let setLevel bypass lower-severity emissions too.
Custom loggers are expected to forward the runtime level to backend logging. Since print* methods here always call the standard log API directly, setLevel(log:ERROR) still lets printInfo, printWarn, and printDebug forward lower-priority messages.
🤖 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 `@examples/custom-logger/custom_logger.bal` around lines 20 - 29, Update the
custom logger’s level handling in setLevel and the print* methods so emissions
below the configured log:Level are suppressed before calling the standard log
API. Ensure setLevel(log:ERROR) prevents printInfo, printWarn, and printDebug
from forwarding while preserving higher-severity logging.
|
|
||
| log:Level parentLevel; | ||
| lock { | ||
| // Child loggers inherit the level from the parent logger | ||
| parentLevel = self.level; | ||
| } | ||
| return new ApplicationLogger(self.applicationName, self.version, newContext, parentLevel); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate custom-logger tests and all level-inheritance assertions.
rg -n -C 6 'withContext|setLevel|getLevel|ApplicationLogger' \
--glob '*test*.bal' --glob '*Test*.bal' --glob '*.bal' .Repository: ballerina-platform/ballerina-distribution
Length of output: 8946
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Find the core log module sources and any Logger contract/type definitions.
rg -n "type Logger|function getLevel|function setLevel|function withContext|logger" --glob '*.bal' .
# Show likely log package files without executing repo code.
printf '\n--- Candidate files ---\n'
git ls-files | rg '(^|/)log/|Logger|log\.bal' | head -200Repository: ballerina-platform/ballerina-distribution
Length of output: 2424
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the custom logger implementation around Logger and child behavior.
cat -n examples/custom-logger/custom_logger.bal
# Search the repository only for Logger contract terms in plain files, without excluding examples.
rg -n "log:Logger|function withContext|function getLevel|function setLevel|type Logger|Logger =" --glob '*.bal' .Repository: ballerina-platform/ballerina-distribution
Length of output: 5674
🌐 Web query:
Ballerina log:Logger withContext getLevel setLevel child logger contract
💡 Result:
In the Ballerina log library, the Logger interface handles contextual logging and runtime log level management through specific behaviors regarding hierarchy and configuration [1][2]. withContext The withContext method is used to create a child logger [1][3]. It accepts key-value pairs and returns a new Logger instance that includes this additional context in its log output [1][2]. Child loggers are not registered in the logger registry [1][2]. getLevel The getLevel method returns the effective log level of a logger [1]. - For root or custom loggers (created via log:fromConfig), it returns the level explicitly set for that logger [1][2]. - For child loggers (created via withContext), it returns the level inherited from its parent [1][2]. If the parent logger's level is updated, the child logger's effective level changes automatically, as getLevel delegates to the parent [1]. setLevel The setLevel method allows modifying the log level of a logger at runtime [2]. - It is supported on root and custom loggers that are registered in the logger registry [2]. - It is NOT supported on child loggers [1][2]. Calling setLevel on a child logger will return an error, as these loggers are designed to strictly inherit their level from their parent [1][4]. To change the effective level of a child logger, you must change the level of the parent logger instead [1][2]. Logger Contract and Registry Loggers created via log:fromConfig are registered in a central logger registry, allowing them to be discovered and managed (e.g., updating levels) at runtime using their unique ID [2]. Child loggers, being transient and linked to a parent's lifecycle, do not participate in this registration process [1][2].
Citations:
- 1: https://ballerina.io/spec/log/
- 2: https://central.ballerina.io/ballerina/log/latest
- 3: https://github.com/ballerina-platform/module-ballerina-log
- 4: Add native support for modifying the log level programmatically at runtime ballerina-library#6213
🌐 Web query:
Ballerina log module source getLevel setLevel child logger not supported
💡 Result:
In the Ballerina log module, calling setLevel on a child logger is not supported and will result in an error [1]. Child loggers are designed to inherit their log level from their parent logger [1][2]. Consequently, the following behaviors apply: 1. setLevel: Attempting to invoke setLevel on a child logger returns an unsupported operation error [1][2]. To change the effective log level of a child logger, you must instead change the log level of its parent [1]. 2. getLevel: When called on a child logger, getLevel delegates the request to the parent logger to return the effective inherited level [1]. This design choice ensures that child loggers, which are typically created via withContext to add metadata, maintain consistency with the parent's configuration [1][2]. Dynamic log level modification via setLevel is only supported for root loggers and custom loggers [3][2].
Citations:
- 1: https://ballerina.io/spec/log/
- 2: Add native support for modifying the log level programmatically at runtime ballerina-library#6213
- 3: https://central.ballerina.io/ballerina/log/latest
Keep child loggers linked to the parent level.
withContext(...) copies the parent level once, so a later appLogger.setLevel(...) does not update already created child loggers. The custom child logger also allows setLevel(...), which can break the inherited-child contract. Store the parent logger in child contexts, delegate getLevel(...) to the parent, and make child setLevel(...) return the unsupported-operation error.
🤖 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 `@examples/custom-logger/custom_logger.bal` around lines 63 - 69, Update
withContext(...) and the child logger implementation so child contexts retain a
reference to the parent logger instead of copying parentLevel. Make child
getLevel(...) delegate to that parent, and make child setLevel(...) return the
unsupported-operation error, preserving the inherited parent-level contract.
| destinations: [{ | ||
| path: "./logs/metrics.log", | ||
| rotation: { | ||
| policy: log:TIME_BASED, | ||
| maxAge: 86400, // 24 hours | ||
| maxBackupFiles: 7 | ||
| } | ||
| }], |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== file excerpt =="
sed -n '1,80p' examples/logger-from-config/logger_from_config.bal 2>/dev/null || true
echo
echo "== matching metrics/retention references =="
rg -n "retention|metrics|maxBackupFiles|rotation:|destinations" examples examples/logger-from-config . 2>/dev/null || true
echo
echo "== git diff stat/name-only =="
git diff --stat HEAD~1..HEAD 2>/dev/null || true
git diff --name-only HEAD~1..HEAD 2>/dev/null || trueRepository: ballerina-platform/ballerina-distribution
Length of output: 22357
🌐 Web query:
Ballerina log module maxBackupFiles TIME_BASED retention metadata rotation depends on writes
💡 Result:
In the Ballerina log module, the log rotation process, including the application of maxBackupFiles retention, is triggered during log write operations [1]. The rotation behavior depends on the configured policy (SIZE_BASED, TIME_BASED, or BOTH): 1. Dependency on Writes: Log rotation is not an independent background process that runs strictly on a timer. It is performed during log write operations [1]. This means that if no logs are being written, the system will not perform a rotation even if the maxAge (TIME_BASED) threshold has passed. The rotation check occurs when the application attempts to write a log entry [1]. 2. Rotation Policies: - SIZE_BASED: Rotation occurs when the log file reaches the maxFileSize [1]. - TIME_BASED: Rotation occurs when the duration specified by maxAge has elapsed since the last rotation or file creation, but only when a subsequent log write operation is triggered [1]. - BOTH: Rotation occurs when either the maxFileSize OR the maxAge limit is reached, whichever occurs first, checked at the time of a write operation [1]. 3. Retention (maxBackupFiles): The maxBackupFiles parameter defines the maximum number of historical backup log files to retain [2][1]. When a rotation occurs, the current log file is renamed with a timestamp, and the system automatically deletes the oldest backup files if the total count exceeds the value set in maxBackupFiles [2][1]. Because the rotation check is tied to write operations, the file system metadata and rotation logic are updated only when the application actively logs data [1].
Citations:
Align the metrics retention metadata with the rotation configuration.
maxBackupFiles = 7 retains seven rotated backup files, while retention = "30days" advertises 30-day retention. If 30-day daily retention is intended, use maxBackupFiles: 30; otherwise update the retention context value. Also note that rotation only happens when log writes occur, so no writes may leave no backup files despite a configured maxAge.
🤖 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 `@examples/logger-from-config/logger_from_config.bal` around lines 21 - 28,
Align the metrics destination’s retention metadata with its rotation settings:
update maxBackupFiles in the destinations configuration to 30 for 30-day daily
retention, or change the associated retention context value to match seven
backups. Preserve the existing rotation policy and ensure the resulting
configuration accurately describes retention when log writes trigger rotation.



ballerina/data.xmldataand current conversion APIs.