Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
38 changes: 37 additions & 1 deletion .github/workflows/opencode-review-dispatch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1430,6 +1430,38 @@ jobs:

writable_npm_cache_dir=""
writable_pnpm_store_dir=""
npm_lock_project_dir() {
local candidate_dir="$PWD"

case "$candidate_dir" in
"$COVERAGE_SOURCE_WORKDIR"|"$COVERAGE_SOURCE_WORKDIR"/*) ;;
*)
echo "::error::npm package directory escaped the validated coverage worktree." >&2
Comment thread
seonghobae marked this conversation as resolved.
return 1
;;
esac

while true; do
if [ -f "$candidate_dir/npm-shrinkwrap.json" ] \
&& [ ! -L "$candidate_dir/npm-shrinkwrap.json" ]; then
printf '%s\n' "$candidate_dir"
return 0
fi
if [ -f "$candidate_dir/package-lock.json" ] \
&& [ ! -L "$candidate_dir/package-lock.json" ]; then
printf '%s\n' "$candidate_dir"
return 0
fi
if [ "$candidate_dir" = "$COVERAGE_SOURCE_WORKDIR" ]; then
break
fi
candidate_dir="$(dirname "$candidate_dir")"
done

echo "::error::No regular non-symlink npm lock was found at the package or validated workspace root." >&2
return 1
}

trusted_npm_lock_is_materialized() {
local relative_dir
local lock_name
Expand Down Expand Up @@ -1639,16 +1671,19 @@ jobs:

install_package_dependencies() {
local package_runner="$1"
local npm_project_dir
case "$package_runner" in
npm)
if [ -f package-lock.json ] || [ -f npm-shrinkwrap.json ]; then
if npm_project_dir="$(npm_lock_project_dir)"; then
pushd "$npm_project_dir" >/dev/null
if ! trusted_npm_lock_is_materialized || ! prepare_writable_npm_cache; then
Comment thread
seonghobae marked this conversation as resolved.
append "### JavaScript/TypeScript dependencies (npm)"
append ""
append "- Result: FAIL"
append "- Reason: the current npm lock is not hash-bounded to the validated base or HEAD, or the trusted npm cache is unavailable."
append ""
failures=$((failures + 1))
popd >/dev/null
return 0
fi
run_and_capture "JavaScript/TypeScript dependencies (npm offline ci, lifecycle hooks disabled)" \
Expand All @@ -1658,6 +1693,7 @@ jobs:
--cache "$writable_npm_cache_dir" \
--no-audit \
--no-fund
popd >/dev/null
Comment thread
seonghobae marked this conversation as resolved.
Comment thread
seonghobae marked this conversation as resolved.
else
append "### JavaScript/TypeScript dependencies (npm)"
append ""
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ this file. The format follows Keep a Changelog, and versioned releases follow
Semantic Versioning where the repository publishes a release.

## [Unreleased]
- Run npm workspace coverage installs from the nearest validated ancestor lock
while keeping tests scoped to the changed package; regular non-symlink lock
files remain hash-bounded by the existing materialization manifest.
- **Pin `opencode-review-dispatch.yml` off the starved floating `ubuntu-latest` image.**
The 2026-09-01 floating-image fix (see that entry below) pinned `strix.yml`,
`opencode-review.yml`, and `noema-review.yml` -- the three required-check
Expand Down
2 changes: 1 addition & 1 deletion scripts/ci/test_strix_quick_gate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ required_workflow_bootstrap_has_if() {
local bootstrap_file="$1"

awk '/^ required-workflow-bootstrap:$/{p=1; print; next} p && /^ [A-Za-z0-9_-]+:/{exit} p' "$bootstrap_file" |
grep '^[[:space:]]*if:' >/dev/null
grep '^ if:' >/dev/null
Comment thread
seonghobae marked this conversation as resolved.
}

seal_opencode_test_artifacts() {
Expand Down
61 changes: 61 additions & 0 deletions tests/test_opencode_agent_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,9 @@ def test_opencode_target_coverage_materializes_only_after_authorized_dispatch():
assert "corepack pnpm fetch" in measure_step
assert "--store-dir /opt/pnpm-store" in measure_step
assert "chmod -R a+rX /opt/corepack /opt/npm-cache /opt/pnpm-store" in measure_step
assert "npm_lock_project_dir() {" in measure_step
assert 'pushd "$npm_project_dir" >/dev/null' in measure_step
assert "No regular non-symlink npm lock was found at the package or validated workspace root." in measure_step
assert "trusted_npm_lock_is_materialized()" in measure_step
assert (
'head_blob="$(trusted_git rev-parse "${PR_HEAD_SHA}:${relative_lock}"'
Expand Down Expand Up @@ -1581,6 +1584,64 @@ def test_opencode_coverage_discovers_changed_nested_javascript_package(tmp_path)
assert result.stdout.splitlines() == ["ADFS 연동 라이브러리/Node.JS/Node App"]


def test_opencode_coverage_resolves_ancestor_npm_lock_for_workspace_package(tmp_path):
"""Workspace coverage installs from the root lock while testing the nested package."""
bash = shutil.which("bash")
if bash is None:
pytest.skip("bash is required for the extracted workflow function regression test")

workflow = Path(".github/workflows/opencode-review-dispatch.yml").read_text(
encoding="utf-8"
)
measure_start = workflow.index(
" - name: Measure test and docstring evidence\n"
)
measure_end = workflow.index("\n - name:", measure_start + 1)
measure_step = workflow[measure_start:measure_end]
helper_start = measure_step.index(" npm_lock_project_dir() {\n")
helper_end = measure_step.index(
"\n\n trusted_npm_lock_is_materialized()", helper_start
)
shell = "\n".join(
(
"set -euo pipefail",
textwrap.dedent(measure_step[helper_start:helper_end]),
"npm_lock_project_dir",
)
)

repo = tmp_path / "repo"
package = repo / "apps" / "desktop"
package.mkdir(parents=True)
(repo / "package-lock.json").write_text("{}\n", encoding="utf-8")
env = os.environ.copy()
env["COVERAGE_SOURCE_WORKDIR"] = str(repo)
result = subprocess.run(
[bash, "-c", shell],
cwd=package,
env=env,
capture_output=True,
text=True,
timeout=10,
)

assert result.returncode == 0, result.stderr
assert result.stdout.splitlines() == [str(repo)]

outside = tmp_path / "outside"
outside.mkdir()
escaped = subprocess.run(
[bash, "-c", shell],
cwd=outside,
env=env,
capture_output=True,
text=True,
timeout=10,
)
assert escaped.returncode != 0
assert "escaped the validated coverage worktree" in escaped.stderr
Comment thread
seonghobae marked this conversation as resolved.


def test_opencode_runtime_pin_supports_reasoning_options():
"""Keep OpenCode runtime new enough to apply model-level reasoning settings."""
review_workflow = Path(".github/workflows/opencode-review-dispatch.yml").read_text(
Expand Down
2 changes: 1 addition & 1 deletion tests/test_pr_review_autofix_nvidia_nim_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
DOCTORING_RECORD = Path("docs/doctoring/hourly-nvidia-nim-autofix.md")
CHANGELOG = Path("CHANGELOG.md")
REVIEW_DISPATCH_WORKFLOW = Path(".github/workflows/opencode-review-dispatch.yml")
REVIEW_DISPATCH_BLOB_SHA = "d86497b3f43bebbabbb4f504eb5132cdf3b7b293"
REVIEW_DISPATCH_BLOB_SHA = "a9b57d284def1ff8f4f82880612583039ea8d52e"


def _workflow_text(path: Path) -> str:
Expand Down
Loading