Summary
codeql-bundle crashes with ValueError: Invalid NPM block in '${workspace}': '${workspace}' when any qlpack.yml in the workspace uses the documented ${workspace} / ~${workspace} / ^${workspace} version-range placeholders.
These placeholders are an officially supported feature of CodeQL workspaces and are commonly used for sibling-pack dependencies (e.g. a test/qlpack.yml depending on the matching src/qlpack.yml). They appear in advanced-security/codeql-development-template's per-language qlpack.yml files, so any custom bundle built from a workspace derived from that template fails immediately.
Repro
# qlpack.yml
name: my-org/my-test
version: 0.0.2
dependencies:
my-org/my-src: ${workspace}
$ codeql-bundle --bundle <bundle-path> --workspace . ...
Traceback
File ".../codeql_bundle/helpers/codeql.py", line 110, in load
qlpack_config = CodeQLPackConfig.from_dict(qlpack_yml_as_dict)
File ".../codeql_bundle/helpers/codeql.py", line 37, in from_dict
filtered_dict = {k: _convert_value(k, v) for k, v in dict_.items() if k in fieldset}
File ".../codeql_bundle/helpers/codeql.py", line 33, in _convert_value
return {k: NpmSpec(v) for k, v in v.items()}
File ".../semantic_version/base.py", line 1294, in parse
raise ValueError("Invalid NPM block in %r: %r" % (expression, block))
ValueError: Invalid NPM block in '${workspace}': '${workspace}'
Full failing run for reference: https://github.com/ql-mcp-playground/codeql-copilot-control/actions/runs/25194864966/job/73875255677
Root cause
codeql_bundle/helpers/codeql.py calls NpmSpec(v) unconditionally on every dependency value:
def _convert_value(k: str, v: Any) -> Any:
if k == "version":
return Version(v)
elif k == "dependencies":
return {k: NpmSpec(v) for k, v in v.items()}
else:
return v
NpmSpec does not understand the ${workspace} family.
Suggested fix
Detect and either resolve or pass through workspace placeholders. Since codeql-bundle already discovers the local pack set via codeql pack ls, the resolved version of the workspace pack is known and could substitute for the placeholder, mirroring what codeql pack publish does. Minimal sketch:
WORKSPACE_PLACEHOLDERS = ("${workspace}", "~${workspace}", "^${workspace}")
def _convert_dep(name: str, spec: str, workspace_versions: Dict[str, Version]) -> NpmSpec:
if spec in WORKSPACE_PLACEHOLDERS:
v = workspace_versions.get(name)
if v is None:
return NpmSpec("*") # source-resolved; any version
prefix = spec[: spec.index("$")] # "", "~", "^"
return NpmSpec(f"{prefix}{v}")
return NpmSpec(spec)
* is also acceptable for source-resolved deps per the GitHub docs ("Using \"*\" for source dependencies makes it explicit that the version is inherited from the workspace").
Impact
Blocks codeql-bundle-action and any direct codeql-bundle invocation against workspaces that use the documented ${workspace} placeholder. Cross-ref: filing a companion issue against advanced-security/codeql-bundle-action.
Environment
codeql-bundle 0.4.1 (as bundled in advanced-security/codeql-bundle-action@v2.2.0)
- Python 3.11.15
semantic-version 2.10.x
Summary
codeql-bundlecrashes withValueError: Invalid NPM block in '${workspace}': '${workspace}'when anyqlpack.ymlin the workspace uses the documented${workspace}/~${workspace}/^${workspace}version-range placeholders.These placeholders are an officially supported feature of CodeQL workspaces and are commonly used for sibling-pack dependencies (e.g. a
test/qlpack.ymldepending on the matchingsrc/qlpack.yml). They appear inadvanced-security/codeql-development-template's per-languageqlpack.ymlfiles, so any custom bundle built from a workspace derived from that template fails immediately.Repro
Traceback
Full failing run for reference: https://github.com/ql-mcp-playground/codeql-copilot-control/actions/runs/25194864966/job/73875255677
Root cause
codeql_bundle/helpers/codeql.pycallsNpmSpec(v)unconditionally on every dependency value:NpmSpecdoes not understand the${workspace}family.Suggested fix
Detect and either resolve or pass through workspace placeholders. Since
codeql-bundlealready discovers the local pack set viacodeql pack ls, the resolved version of the workspace pack is known and could substitute for the placeholder, mirroring whatcodeql pack publishdoes. Minimal sketch:*is also acceptable for source-resolved deps per the GitHub docs ("Using\"*\"for source dependencies makes it explicit that the version is inherited from the workspace").Impact
Blocks
codeql-bundle-actionand any directcodeql-bundleinvocation against workspaces that use the documented${workspace}placeholder. Cross-ref: filing a companion issue againstadvanced-security/codeql-bundle-action.Environment
codeql-bundle0.4.1 (as bundled inadvanced-security/codeql-bundle-action@v2.2.0)semantic-version2.10.x