Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 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
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
4 changes: 2 additions & 2 deletions .github/workflows/build-and-snapshot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,9 @@ 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
# on Windows amd64
cf install-plugin https://github.com/SAP/cf-cli-java-plugin/releases/download/snapshot/cf-cli-java-plugin-windows-amd64
# on Linux x86
# on Linux amd64
cf install-plugin https://github.com/SAP/cf-cli-java-plugin/releases/download/snapshot/cf-cli-java-plugin-linux-amd64
```

Expand Down
51 changes: 48 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,46 @@
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)

rc = subprocess.call(f"go build -o dist/cf-cli-java-plugin-{os_name}-{arch}", shell=True)
sys.exit(rc)
105 changes: 56 additions & 49 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,54 @@ 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]

- name: Build plugin
run: |
echo "🔨 Building plugin..."
if ! python3 .github/workflows/build.py; then
echo "❌ Build failed."
exit 1
fi
echo "✅ Build successful!"
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: Validation Summary
- name: Download JStall minimal JAR for go:embed
shell: bash
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)"
fi
echo "✅ Plugin build"
echo ""
echo "🚀 Ready for merge!"
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: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: cf-cli-java-plugin-${{ matrix.os }}
path: |
dist/*
!dist/jstall-minimal.jar
!dist/hprof-redact-*
54 changes: 50 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ _testmain.go
# Tools
counterfeiter

# Built binaries
# Build output directories
build/
pkg/

Expand All @@ -49,8 +49,54 @@ 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/

# 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