This directory contains utility scripts for managing the java-profiler project.
Triggers the Validated Release workflow using GitHub CLI to create a new release.
Prerequisites:
- GitHub CLI installed and authenticated
- jq installed
- Git repository is up to date
- The authenticated user has write, maintain, or admin repository access
- You are on the correct branch for the release type
Usage:
./utils/release.sh <release_type> [options]Arguments:
release_type: Type of release (major,minor, orpatch)
Options:
--no-dry-run: Actually perform the release (default is dry-run)--skip-tests: Skip pre-release tests (emergency releases only)--branch <name>: Specify branch to release from (default: current branch)--commit <sha>: Specify commit SHA to release (default: interactive selection)--help: Show help message
Branch rules:
- Major/Minor releases: must be run from
main - Patch releases: must be run from a
release/X.Y._branch
Release flow:
- Validates inputs and branch rules
- Fetches and verifies the selected branch is up to date with
origin(a checked-out local branch that's behind or ahead of origin fails fast with pull instructions) - For patch releases, asks whether to pick PRs from
mainto backport onto the release branch first; if you accept, you select which PRs, a combined backport PR is opened, and the script exits so you can merge it and re-run - Interactive commit selection (or use
--commit) - Triggers GitHub Actions "Validated Release" workflow
- Workflow runs pre-release tests, then creates the annotated tag on the selected commit (and a release branch for minor/major releases)
- Tag push triggers GitLab, which publishes the Maven artifacts, and the GitHub release workflows attach the release assets
No file modifications or version-bump PRs are needed — the version is
computed from git tags at build time. The next build from main (or the
release branch) automatically sees the new tag and computes the next
snapshot version.
Interactive pickers (branch and commit selection) support ↑/↓/Enter, and
can be cancelled at any time with q or Ctrl-C.
A dry run never creates a tag, pushes a branch, or triggers GitLab.
If workflow monitoring loses its API connection, the script checks the run's
status and reconnects to the same run, making up to three monitoring attempts
per monitoring window. All attempts share a one-hour deadline. When the deadline
is reached, the script allows up to ten seconds for a final status query, including
when it must retry a query interrupted by the shared deadline. If the result remains
unconfirmed, an interactive session asks whether to watch the same run for another
hour. Answering y or yes renews the deadline and monitoring attempts. Answering
n, pressing Enter, or reaching EOF stops monitoring with
WORKFLOW STATUS UNKNOWN and a nonzero exit. Unattended sessions stop without
prompting. The remote workflow keeps running when local monitoring stops.
RELEASE_MONITOR_TIMEOUT_SECONDS overrides the default 3600-second deadline.
Check the existing run before starting another release.
Recognized completed outcomes retain GitHub's exact conclusion in the output.
Only a confirmed success exits zero; other recognized conclusions exit nonzero.
Only failure and startup_failure are labelled as workflow failures.
.github/scripts/tests/test_release_automation.sh is a single hermetic shell
test. It validates release tag/branch creation, version computation,
trivial-PR authorization, and recovery from workflow monitoring errors using
temporary local Git repositories and a GitHub CLI fixture. It does not load
credentials or contact GitHub, so it cannot publish, tag, push, or merge
anything remotely.
The terminal interaction tests require Python 3.
.github/scripts/tests/test_release_automation.shCherry-picks a merged PR onto a release branch, pushes the backport branch, and opens a PR.
Prerequisites:
- GitHub CLI installed and authenticated
- jq installed
- Clean working tree
Usage:
./utils/backport-pr.sh [--dry-run] [<release-name>] <pr-number-or-url>Arguments:
<release-name>: Target release branch suffix, e.g.1.9._(maps torelease/1.9._). If omitted, an interactive picker is shown.<pr-number-or-url>: PR number (420) or full GitHub URL.--dry-run: Preview without making changes.
Examples:
./utils/backport-pr.sh 1.9._ 420
./utils/backport-pr.sh 420 # interactive branch selection
./utils/backport-pr.sh --dry-run 1.9._ 420Finds PRs merged to main since a release branch diverged, lets you
multi-select which ones to backport, cherry-picks them onto a single new
branch off the release branch, runs ./gradlew buildDebug to catch a
combination that doesn't build before pushing, and opens one combined PR.
Also invoked interactively from release.sh when preparing a patch release.
Prerequisites:
- GitHub CLI installed and authenticated
- jq installed
- Clean working tree
Usage:
./utils/prepare-patch.sh [--branch release/X.Y._] [--no-dry-run]Options:
--branch <name>: Release branch to prepare. If omitted, an interactive picker is shown.--no-dry-run: Actually cherry-pick, push, and open the PR (default is dry-run).
Examples:
./utils/prepare-patch.sh --branch release/1.9._ # dry-run, preview only
./utils/prepare-patch.sh # interactive branch selection, dry-run
./utils/prepare-patch.sh --no-dry-run --branch release/1.9._Test candidate discovery with local Git repositories and a GitHub CLI fixture:
bash utils/tests/test_prepare_patch.shRuns tests in containers across various OS/libc/JDK combinations, mirroring the CI matrix locally. Defaults to Podman; on macOS use Docker via colima (--container=docker) — podman's credential-helper lookup for the Datadog registries (ddtool) fails outside the CI network and aborts container commands.
Usage:
./utils/run-containers-tests.sh [options]
--libc=glibc|musl|all[,..] (default: glibc)
--jdk=8|11|17|21|25|8-j9|...|regular|j9|graal|all[,..]
(default: 21)
--arch=x64|aarch64|all[,..] (default: auto-detect)
--config=debug|release|asan|tsan|all[,..] (default: debug)
--container=podman|docker (default: podman)
--tests="TestPattern" (optional)
--gtest (enable C++ gtests)
--gtest-task=Task (run one C++ gtest task)
--shell (drop to shell instead of running tests)
--mount (mount local repo instead of cloning)
--rebuild (force rebuild of container images)
--matrix (preview a full matrix)
--run (execute an inferred matrix without prompting)
--fail-fast (stop matrix execution on first failure)Examples:
# Run a single C++ gtest binary in ASan mode
./utils/run-containers-tests.sh --config=asan --gtest-task=elfparser_ut
# Use Docker via colima (recommended on macOS)
./utils/run-containers-tests.sh --container=docker --libc=glibc --jdk=21
# Preview selected JDKs across every supported libc/architecture pair
./utils/run-containers-tests.sh --libc=all --jdk=8,17,21 --arch=all
# Run all supported musl cells without an interactive prompt
./utils/run-containers-tests.sh --matrix --libc=musl --run
# Run all OpenJ9 cells
./utils/run-containers-tests.sh --matrix --jdk=j9 --runSingle-value commands run one container test configuration immediately. When any dimension expands to multiple cells, the script prints a compact status table first; interactive terminals ask for confirmation, while non-interactive runs require --run to execute. Matrix execution prints the status table again after all cells finish and writes summaries to build/reports/container-matrix/summary.md and build/reports/container-matrix/summary.json. Matrix gtest runs require a short --gtest-task name so the task follows each cell's configuration. Cells not run because of --fail-fast are reported as cancelled separately from unsupported cells that are skipped.
Static async-signal-safety check. Builds a call graph from the relocations of the debug object files (objdump -dr) and reports every function reachable from a signal handler or malloc hook that calls an unsafe symbol (heap allocation, locks, stdio, dynamic-loader calls, dynamic TLS, logging). The entry points, unsafe symbols and known findings are data lists at the top of the script. ELF objects only (Linux x64/aarch64); needs GNU objdump and c++filt.
Usage:
./utils/check-signal-reachability.py --obj-dir ddprof-lib/build/obj/main/debug [--allowlist <file>]
./utils/check-signal-reachability.py --self-test # planted violations in utils/tests/signal-reachability-fixture.cpp
./gradlew :ddprof-lib:checkSignalReachability # opt-in; SKIPPED when the debug objects are not ELFExit codes: 0 no findings outside the allowlist (or self-test passed), 1 new findings (one <object>:<caller> -> <unsafe symbol> (via <path>) line each), 2 usage/environment error. --allowlist replaces the built-in known findings; one entry per line: <caller>[|<caller>...] -> <unsafe symbol> # <JIRA-KEY>.
Standalone, stdlib-only checks over the git-tracked files. Each prints one <path>[:<line>]: <problem> line per violation and exits 0 clean, 1 violations, 2 environment error; --root selects the checkout (default: the one containing the script).
| Script | Checks |
|---|---|
check-jvm-boundary-includes.py |
Shared code in ddprof-lib/src/main/cpp does not #include "hotspot/", "j9/" or "zing/" headers (quoted or angle-bracket form), except the boundary files and the known exceptions (mirrors doc/architecture/JvmSupportLayer.md#known-boundary-exceptions). |
check-doc-index.py |
Every doc/**/*.md is linked from doc/README.md and has a PascalCase file name. |
check-sigsetjmp-shape.py |
Every sigsetjmp() has a JmpCtxScope in effect, savemask 1, and a landing pad that starts with SIGNAL_HANDLER_UNWIND_AFTER_LONGJMP(); then <scope>.restore(); (the guards.h pattern). The glibc cancellation buffer in libraryPatcher_linux.cpp is the one exception. |
check-tracked-artifacts.py |
No tracked path under docs/sphinx/ or .sphinx/, and no *.scratch* path. |
Usage:
./utils/check-doc-index.py # any one check
./gradlew :ddprof-lib:qualityChecks # signal-reachability check (+ --self-test on Linux) plus all four; run by CI (ci.yml source-invariant-checks job)Patches a dd-java-agent.jar with a locally-built ddprof library for quick local testing without a full dd-trace-java rebuild.
Usage:
DD_AGENT_JAR=path/to/dd-java-agent.jar DDPROF_JAR=path/to/ddprof.jar \
./utils/patch-dd-java-agent.shSee README_UPSTREAM_TRACKER.md for full documentation.
Wrapper to compare local files against a given upstream async-profiler commit and produce a change report.
Core change detection and report generation logic.
Identifies which local files should be tracked against upstream (based on async-profiler copyright headers).
Identifies divergences from upstream async-profiler that could be contributed back.
Core diff analysis and report generation for contribution candidate detection.
Updates the Sonatype (Maven Central) OSSRH credentials stored in AWS SSM, used by the CI publish pipeline.
Prerequisites:
- AWS CLI authenticated with
ssm:PutParameterpermission
Usage:
./utils/update-sonatype-credentials.sh <username> <token>