Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
18f0987
feat(heap-dump): add --redact, --redact-complete, --compress flags
parttimenerd Sep 9, 2026
00672a0
feat: Windows ARM support + default gz compression for heap-dump
parttimenerd Sep 9, 2026
08c93c1
fix: dry-run bypass CheckRequiredTools + appInstanceIndex detection
parttimenerd Sep 9, 2026
a1ada44
docs: document --redact, --redact-complete, --compress flags for heap…
parttimenerd Sep 9, 2026
1020396
docs: design spec for --open flag on heap-dump
parttimenerd Sep 17, 2026
a40dc1c
docs: implementation plan for --open heap-dump flag
parttimenerd Sep 17, 2026
8c3b131
feat: add serveFileOnce and openBrowser helpers for --open
parttimenerd Sep 17, 2026
19ea354
fix: address code quality issues in open.go
parttimenerd Sep 17, 2026
82d626d
feat: add --open and --open-url flags to Options and flagDefinitions
parttimenerd Sep 17, 2026
101d658
feat: invoke serveFileOnce+openBrowser after heap-dump download for -…
parttimenerd Sep 17, 2026
964e2ea
fix: stream file directly via io.Copy to prevent http.ServeFile path …
parttimenerd Sep 17, 2026
a79a3da
fix: use random token URL path in serveFileOnce to prevent filename l…
parttimenerd Sep 17, 2026
43d2260
fix: print Would-open line before dry-run SSH command output for --op…
parttimenerd Sep 17, 2026
22fc173
fix: handle CORS OPTIONS preflight without triggering server shutdown…
parttimenerd Sep 17, 2026
91d8a55
docs: document --open and --open-url flags in README and CHANGELOG
parttimenerd Sep 17, 2026
b46bb1f
docs: document macOS firewall permission dialog for --open flag
parttimenerd Sep 17, 2026
0791be0
docs: add .tool.yaml with --open, --redact, --compress how-to entries
parttimenerd Sep 17, 2026
812fe9b
chore: exclude docs/superpowers planning artifacts from repo
parttimenerd Sep 17, 2026
7f9847b
docs: fix supported platforms list for --redact in CHANGELOG
parttimenerd Sep 17, 2026
c8202bf
Merge branch 'master' into heap-dump-compress-redact
parttimenerd Sep 17, 2026
160e510
docs: clarify that gzip transfer is always used on JDK 17+, --compres…
parttimenerd Sep 17, 2026
189fe24
ci: download hprof-redact binaries before golangci-lint in PR validation
parttimenerd Sep 17, 2026
c6e7ea7
ci: fix hprof-redact download by extracting from archives via build.py
parttimenerd Sep 17, 2026
fa8c71c
style: add trailing newline to .gitignore
parttimenerd Sep 17, 2026
332018e
style: fix markdownlint MD013/MD060 violations in README
parttimenerd Sep 17, 2026
b99e31e
style: fix MD060 aligned table style in README redact section
parttimenerd Sep 17, 2026
6dcbc21
style: fix MD060 table column alignment accounting for multi-byte chars
parttimenerd Sep 17, 2026
06de3c9
fix: address PR review comments on heap-dump redact/open features
parttimenerd Sep 18, 2026
c95cdd4
feat: make heap-dump open/redact more robust
parttimenerd Sep 18, 2026
fbe08ec
Stream heap dumps through hprof-redact
parttimenerd Sep 21, 2026
b92623b
Fix changelog heading duplication
parttimenerd Sep 21, 2026
f166766
Improve heap-dump stream error handling
parttimenerd Sep 21, 2026
08f904e
fix: prevent double-call to cat.Wait() in StreamOverCat
parttimenerd Sep 21, 2026
2d4ddda
fix: bump vulnerable deps and extend PR validation CI
parttimenerd Sep 21, 2026
51ff39c
fix: make redact tests Windows-compatible; close file handle before R…
parttimenerd Sep 21, 2026
f1e68ab
fix: use PowerShell binary copy on Windows instead of `more` to avoid…
parttimenerd Sep 21, 2026
b93362b
fix: replace --ssh-prefix with --cf/--ssh; update jstall to v0.7.1
parttimenerd Sep 22, 2026
4376ff2
fix: use --ssh instead of --cf for jstall; fix help text alignment
parttimenerd Sep 22, 2026
171bb8a
ci: trigger CI to pick up jstall v0.7.2 and latest hprof-redact nightly
parttimenerd Sep 22, 2026
27c24bc
fix: use --cf for jstall; remove shellQuote (fixes Windows flag parsi…
parttimenerd Sep 22, 2026
97e0d28
ci: pick up jstall v0.7.3 with Windows .cmd/.bat wrapper fix
parttimenerd Sep 25, 2026
33cb28e
ci: add Windows smoke-test for cf java status (verifies jstall reache…
parttimenerd Sep 25, 2026
c1781f5
ci: fix Windows smoke-test (install CF CLI only on Windows, simplify …
parttimenerd Sep 25, 2026
e1365af
ci: tighten Windows smoke-test to assert CF auth error (not just abse…
parttimenerd Sep 25, 2026
1d19893
fix: add .exe extension to Windows plugin binary; assert it in CI
parttimenerd Sep 28, 2026
d2bbb72
chore: bump go to 1.26.8 to fix stdlib vulns (GO-2026-5856/5972/5039/…
parttimenerd Sep 28, 2026
4bcd681
ci: bump upload-artifact to v7, download-artifact to v8 (drop Node 20)
parttimenerd Sep 28, 2026
6a1a9c3
fix: suggest corrected order when app and command are swapped
parttimenerd Sep 28, 2026
165803d
docs: update CHANGELOG with Windows fixes, swap detection, Go bump
parttimenerd Sep 28, 2026
ce7a122
chore: fix .gitignore — add cf-cli-java-plugin binary, bin/, venv/
parttimenerd Sep 28, 2026
628938c
feat: add WorkloadApp source and pre-built JAR
parttimenerd Oct 7, 2026
bd59f81
feat: add SapMachine 11/17/21/25 app manifests
parttimenerd Oct 7, 2026
266be6e
feat: add OpenJDK 11/17/21/25 app manifests, remove jre21
parttimenerd Oct 7, 2026
8add9a2
feat: add sample-apps.sh deploy/undeploy/busy/calm script
parttimenerd Oct 7, 2026
d4356fc
test: fix jdk21/jdk25 crash + add run-on-all.sh
parttimenerd Oct 7, 2026
c7e425b
fix: treat jstall exit code 10 as warning; add JSTALL_LOCAL build option
parttimenerd Oct 7, 2026
dc6ce7f
fix(sapmachine11): fix OOM crash and Java 17 agent incompatibility on…
parttimenerd Oct 7, 2026
6c03a22
fix: bump jdk11/jdk17 to 512M + cap ReservedCodeCacheSize; fix run-on…
parttimenerd Oct 7, 2026
3a720c1
feat: JRE-only fallback via nc for thread-dump/vm-info/vm-version; bu…
parttimenerd Oct 7, 2026
c9e32e0
feat: JRE-only fallback via nc for heap-dump and jcmd commands
parttimenerd Oct 7, 2026
76d16d1
fix: correct attach-protocol framing — full cmdline in one NUL field
parttimenerd Oct 7, 2026
c06f330
docs: update CHANGELOG with JRE-only nc fallback and reorganize Added…
parttimenerd Oct 7, 2026
2ee9039
docs: update README prerequisites for JRE-only nc fallback
parttimenerd Oct 7, 2026
3f9e8fe
docs: improve CHANGELOG — add jstall version, key subcommands, JRE-on…
parttimenerd Oct 7, 2026
ba35431
fix: address PR review findings
parttimenerd Oct 7, 2026
2494c11
style: fix MD013 line-length violations in CLAUDE.md and README.md
parttimenerd Oct 7, 2026
73062db
fix: clean up jvmmon helper script and remove TOCTOU pre-write check
parttimenerd Oct 7, 2026
7fbc0ad
style: fix MD060 table separator spacing in CLAUDE.md and README.md
parttimenerd Oct 7, 2026
b460e02
fix: suppress spurious --open-url warning — OpenURL always has a defa…
parttimenerd Oct 7, 2026
fa7ce62
fix(test): use 16 MB file in disconnect test to reliably exceed TCP b…
parttimenerd Oct 7, 2026
8610cf9
chore: bump jstall to v0.8.2; add vm-vitals swap-detection tests
parttimenerd Oct 8, 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
7 changes: 3 additions & 4 deletions .github/workflows/build-and-snapshot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -231,14 +231,13 @@ jobs:
```sh
# on Mac arm64
cf install-plugin https://github.com/SAP/cf-cli-java-plugin/releases/download/snapshot/cf-cli-java-plugin-macos-arm64
# on Windows x86
cf install-plugin https://github.com/SAP/cf-cli-java-plugin/releases/download/snapshot/cf-cli-java-plugin-windows-amd64
# on Linux x86
# on Windows amd64
cf install-plugin https://github.com/SAP/cf-cli-java-plugin/releases/download/snapshot/cf-cli-java-plugin-windows-amd64.exe
# on Linux amd64
cf install-plugin https://github.com/SAP/cf-cli-java-plugin/releases/download/snapshot/cf-cli-java-plugin-linux-amd64
```

**Note:** On Linux and macOS, if you get a permission error, run `chmod +x [cf-cli-java-plugin]` on the plugin binary.
On Windows, the plugin will refuse to install unless the binary has the `.exe` file extension.

You can verify that the plugin is successfully installed by looking for `java` in the output of `cf plugins`.

Expand Down
52 changes: 49 additions & 3 deletions .github/workflows/build.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import os
import platform
import subprocess
import sys
import tarfile
import urllib.request
import zipfile

os.makedirs('dist', exist_ok=True)

Expand All @@ -19,6 +24,47 @@
arch = arch_map[platform.machine().lower()]
print(f"Building for {os_name} {arch}")

import sys
rc = os.system(f"go build -o dist/cf-cli-java-plugin-{os_name}-{arch}")
sys.exit(rc >> 8 if os.name != 'nt' else rc)
HPROF_BASE = "https://github.com/parttimenerd/hprof-analyzer/releases/download/nightly"

# All platform binaries must exist before go build (go:embed requires them all).
hprof_targets = [
("hprof-analyzer-x86_64-unknown-linux-musl.tar.gz", "hprof-analyzer-x86_64-unknown-linux-musl/hprof-redact", "dist/hprof-redact-linux-amd64", False),
("hprof-analyzer-aarch64-unknown-linux-musl.tar.gz", "hprof-analyzer-aarch64-unknown-linux-musl/hprof-redact", "dist/hprof-redact-linux-arm64", False),
("hprof-analyzer-aarch64-apple-darwin.tar.gz", "hprof-analyzer-aarch64-apple-darwin/hprof-redact", "dist/hprof-redact-darwin-arm64", False),
("hprof-analyzer-x86_64-pc-windows-msvc.zip", "hprof-analyzer-x86_64-pc-windows-msvc/hprof-redact.exe", "dist/hprof-redact-windows-amd64.exe", True),
("hprof-analyzer-aarch64-pc-windows-msvc.zip", "hprof-analyzer-aarch64-pc-windows-msvc/hprof-redact.exe", "dist/hprof-redact-windows-arm64.exe", True),
]

for archive_name, member, dest, is_zip in hprof_targets:
if os.path.exists(dest) and os.path.getsize(dest) > 0:
print(f" {dest} already present, skipping")
continue
url = f"{HPROF_BASE}/{archive_name}"
print(f" Downloading {archive_name} -> {dest}")
tmp = dest + ".tmp"
try:
urllib.request.urlretrieve(url, tmp)
if is_zip:
with zipfile.ZipFile(tmp) as zf:
data = zf.read(member)
else:
with tarfile.open(tmp, "r:gz") as tf:
data = tf.extractfile(member).read()
with open(dest, "wb") as f:
f.write(data)
os.chmod(dest, 0o755)
except Exception as e:
# windows-arm64 may not always have a release; create an empty placeholder
# so go:embed compiles (the plugin will report "not available" at runtime).
print(f" Warning: could not download {archive_name}: {e}; creating empty placeholder")
open(dest, "wb").close()
finally:
if os.path.exists(tmp):
os.remove(tmp)

if "--deps-only" in sys.argv:
sys.exit(0)

exe = ".exe" if os_name == "windows" else ""
rc = subprocess.call(f"go build -o dist/cf-cli-java-plugin-{os_name}-{arch}{exe}", shell=True)
sys.exit(rc)
129 changes: 84 additions & 45 deletions .github/workflows/pr-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ permissions:
contents: read

jobs:
validate-pr:
name: Validate Pull Request
validate:
name: Lint & Test
runs-on: ubuntu-latest

steps:
Expand All @@ -38,6 +38,9 @@ jobs:
mkdir -p dist
curl -fsSL -o dist/jstall-minimal.jar https://github.com/parttimenerd/jstall/releases/latest/download/jstall-minimal.jar

- name: Download hprof-redact binaries for go:embed
run: python3 .github/workflows/build.py --deps-only

- name: Install Go dependencies
run: go mod tidy -e || true

Expand All @@ -49,9 +52,6 @@ jobs:
- name: Run govulncheck
run: |
go install golang.org/x/vuln/cmd/govulncheck@latest
# Run in JSON mode and emit GitHub Actions warning annotations for each finding.
# govulncheck outputs multi-line JSON objects (not line-delimited), so we use
# raw_decode to parse successive top-level objects from the output stream.
govulncheck -json . 2>/dev/null | python3 -c "
import sys, json
decoder = json.JSONDecoder()
Expand Down Expand Up @@ -87,15 +87,16 @@ jobs:
- name: Lint Go code
run: ./scripts/lint-go.sh ci

- name: Run Go tests
run: go test -v -race ./...

- name: Check Python test suite
id: check-python
run: |
if [ -f "test/requirements.txt" ] && [ -f "test/setup.sh" ]; then
echo "python_tests_exist=true" >> $GITHUB_OUTPUT
echo "✅ Python test suite found"
else
echo "python_tests_exist=false" >> $GITHUB_OUTPUT
echo "⚠️ Python test suite not found - skipping Python validation"
fi

- name: Setup Python environment
Expand All @@ -114,48 +115,86 @@ jobs:
- name: Lint Markdown files
run: ./scripts/lint-markdown.sh ci

# TODO: Re-enable Python tests when ready
# - name: Run Python tests
# if: steps.check-python.outputs.python_tests_exist == 'true'
# run: |
# cd test
# source venv/bin/activate
# echo "🧪 Running Python tests..."
# if ! pytest -v --tb=short; then
# echo "❌ Python tests failed."
# exit 1
# fi
# echo "✅ Python tests passed!"
# env:
# CF_API: ${{ secrets.CF_API }}
# CF_USERNAME: ${{ secrets.CF_USERNAME }}
# CF_PASSWORD: ${{ secrets.CF_PASSWORD }}
# CF_ORG: ${{ secrets.CF_ORG }}
# CF_SPACE: ${{ secrets.CF_SPACE }}
build:
name: Build (${{ matrix.os }})
needs: validate
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]

steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: ">=1.23.5"

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.11"

- name: Download JStall minimal JAR for go:embed
shell: bash
run: |
mkdir -p dist
curl -fsSL -o dist/jstall-minimal.jar https://github.com/parttimenerd/jstall/releases/latest/download/jstall-minimal.jar

- name: Download hprof-redact binaries for go:embed
shell: bash
run: python3 .github/workflows/build.py --deps-only

- name: Install Go dependencies
run: go mod tidy -e || true

- name: Run Go tests
shell: bash
run: go test -race ./...

- name: Build plugin
shell: bash
run: python3 .github/workflows/build.py

- name: Install CF CLI (Windows only)
if: runner.os == 'Windows'
shell: bash
run: |
echo "🔨 Building plugin..."
if ! python3 .github/workflows/build.py; then
echo "❌ Build failed."
choco install cloudfoundry-cli -y --no-progress
cf version

- name: Smoke-test jstall on Windows
if: runner.os == 'Windows'
shell: bash
run: |
plugin_bin=$(ls dist/cf-cli-java-plugin-windows-* | head -1)
# The binary must have a .exe extension; cf install-plugin rejects files without it.
if [[ "$plugin_bin" != *.exe ]]; then
echo "FAIL: Windows plugin binary missing .exe extension: $plugin_bin"
exit 1
fi
echo "✅ Build successful!"
cf install-plugin "$plugin_bin" -f

- name: Validation Summary
run: |
echo ""
echo "🎉 Pull Request Validation Summary"
echo "=================================="
echo "✅ Go code formatting and linting"
echo "✅ Go tests"
echo "✅ Markdown formatting and linting"
if [ "${{ steps.check-python.outputs.python_tests_exist }}" == "true" ]; then
echo "✅ Python code quality checks"
echo "✅ Python tests"
else
echo "⚠️ Python tests skipped (not found)"
# Run cf java status — not logged in so CF will respond with an auth
# error. That means jstall successfully invoked cf.exe via ProcessBuilder.
# Any Windows invocation bug (sh not found, unknown flag, etc.) would
# produce a different error and fail this check.
output=$(cf java status fake-app 2>&1 || true)
echo "Output: $output"

if ! echo "$output" | grep -qiE "not logged in|login|token|authenticate"; then
echo "FAIL: expected CF auth error, got: $output"
exit 1
fi
echo "✅ Plugin build"
echo ""
echo "🚀 Ready for merge!"
echo "OK: jstall reached CF as expected"

- name: Upload artifacts
uses: actions/upload-artifact@v7
with:
name: cf-cli-java-plugin-${{ matrix.os }}
path: |
dist/*
!dist/jstall-minimal.jar
!dist/hprof-redact-*
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:
run: python3 .github/workflows/build.py

- name: Upload build artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: binaries-${{ matrix.os }}
path: dist/
Expand Down Expand Up @@ -130,7 +130,7 @@ jobs:
git push origin "$VERSION"

- name: Download all build artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
path: artifacts/

Expand Down
58 changes: 54 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,16 @@ _testmain.go
# Tools
counterfeiter

# Built binaries
# Build output directories
build/
pkg/

# built project binary (go build)
cf-java-plugin
cf-cli-java-plugin

# Local tool binaries (downloaded during development, e.g. gofumpt, gopls)
bin/
# Testing directory - sensitive config and test results
test/test_config.yml
test/*.hprof
Expand All @@ -49,8 +52,55 @@ test/snapshots/
# Heap dump files
*.hprof

# Build artifacts
# Embedded/downloaded build artifacts
dist

# go
pkg
# Local project binaries
requires

# OS/editor/local tooling
.DS_Store
.claude/
.playwright-mcp/
.test_success_cache.json
*.log
*.tmp
*.bak
*~

# Python local caches / coverage
.coverage
htmlcov/
.mypy_cache/
.ruff_cache/
venv/

# Local investigation / scratch artifacts
BUG*.md
FIX*.md
*_REPORT.md
*analysis*.py
append_*.py
discover*.py
investigate*.py
*_test_output.txt
*_results.txt
*.out
out.zip

# Local runtime artifacts
sapmachine21-status/
sapmachine21-status.zip
sapmachine21-heapdump-*.hprof.gz
sapmachine21-heapdump-*-redacted.hprof.gz

# Local ad-hoc test helpers/artifacts
test/doc_bugs_finder.py
test/sapmachine21-status.zip
test/test_bugs.py
test_bugs.sh
test_edge_cases.py
test_fixes.py

# Internal planning docs (superpowers skill artifacts)
docs/superpowers/
Loading
Loading