Skip to content
Merged
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
23 changes: 23 additions & 0 deletions .changeset/anarci-with-docker-entrypoint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
'@platforma-open/milaboratories.import-vdj.workflow': patch
'@platforma-open/milaboratories.import-vdj': patch
---

Move to software-anarci 1.0.1, which records its docker entrypoint

Region annotation failed on k8s deployments with `sh: 1: ANARCI: not found`
(exit 127). The conda image puts its environment on PATH solely through
`ENTRYPOINT ["micromamba", "run", "--prefix", "/conda-env"]`, and a k8s pod spec
overrides the image entrypoint — so the runner has to re-apply it from the
software descriptor. Every software-anarci up to 1.0.0 records
`docker.entrypoint: []`, because the package-builder that published them did not
read the built image's entrypoint back. Nothing re-applied the wrapper, ANARCI
was never on PATH, and the step died before it started.

1.0.1 was rebuilt with a package-builder that reads `.Config.Entrypoint` from the
image, so its descriptor carries the micromamba wrapper and the k8s runner
reconstructs the right command. `^0.0.3` is exact for a 0.0.x range, so the pin
could never pick the fix up on its own.

No ANARCI behaviour changes between these versions — 1.0.0 was a plain release
and 1.0.1 was "update build deps".
21 changes: 21 additions & 0 deletions .changeset/separator-name-not-character.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
'@platforma-open/milaboratories.import-vdj.workflow': patch
'@platforma-open/milaboratories.import-vdj.column-profile': patch
'@platforma-open/milaboratories.import-vdj': patch
---

Pass the column-profile separator by name, not as a tab character

Loading a TSV failed on server deployments with `TypeError: "delimiter" must be a 1-character
string`, while the same file loaded on a desktop backend. The block was passing a real tab as an
argv element. Desktop runners exec argv directly, so the tab arrived intact; the k8s and
google-batch runners serialise the command with Go's `%q` and re-run it through `sh -c`, where
the tab has already become the two characters `\` and `t` and stays that way. `csv.reader`
rejects a two-character delimiter.

Prerun now sends `tab` or `comma` and `main.py` maps the name back to the character, so only
plain words cross the runner boundary. A separator that still arrives malformed now fails with a
message naming the accepted values rather than a `TypeError`.

The underlying quoting is a backend issue and is unfixed: `toShellCmd` in `util/k8s/template.go`
uses Go quoting where POSIX shell quoting is needed.
23 changes: 23 additions & 0 deletions .changeset/software-build-via-block-tools.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
'@platforma-open/milaboratories.import-vdj.column-profile': patch
'@platforma-open/milaboratories.import-vdj.region-annotation': patch
'@platforma-open/milaboratories.import-vdj.xlsx-to-csv': patch
'@platforma-open/milaboratories.import-vdj': patch
---

Build software through block-tools so dev builds produce docker images

The three software packages called `pl-pkg build` directly, which ignores
`PL_BUILD_CHANNEL` / `PL_BUILD_VARIANT` / `PL_BUILD_LOCATION` and defaults docker
image builds to CI-only. A local `build:dev-remote` therefore emitted binary-only
descriptors, and a block built that way cannot run on a k8s deployment at all —
that runner launches containers exclusively and rejects a command with no image
as "docker is not set".

They now use `block-tools software build`, which honours those variables: variant
`all` builds the images and location `remote` pushes them, the same way
tcr-disco and the other 23 already-migrated software packages work. `PL_PKG_DEV`
drops out of the root scripts and `turbo.json`, since `PL_BUILD_LOCATION` carries
what it used to say.

No change to what the software does — only to how it is built.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"index.js"
],
"scripts": {
"test": "env PL_PKG_DEV=local PL_BUILD_CHANNEL=dev PL_BUILD_VARIANT=binary PL_BUILD_LOCATION=local turbo run test --concurrency 1",
"test": "env PL_BUILD_CHANNEL=dev PL_BUILD_VARIANT=binary PL_BUILD_LOCATION=local turbo run test --concurrency 1",
"test:dry-run": "env PL_BUILD_CHANNEL=dev PL_BUILD_VARIANT=binary PL_BUILD_LOCATION=local turbo run test --dry-run=json",
"mark-stable": "turbo run mark-stable",
"watch": "turbo watch build",
Expand All @@ -15,7 +15,7 @@
"check": "turbo run check",
"do-pack": "turbo run do-pack",
"upgrade-sdk": "block-tools structure refresh --update-deps-only && pnpm i && block-tools structure refresh && pnpm i && pnpm fmt",
"build:dev-local": "env PL_PKG_DEV=local PL_BUILD_CHANNEL=dev PL_BUILD_VARIANT=all PL_BUILD_LOCATION=local turbo run build",
"build:dev-local": "env PL_BUILD_CHANNEL=dev PL_BUILD_VARIANT=all PL_BUILD_LOCATION=local turbo run build",
"build:dev-remote": "env PL_BUILD_CHANNEL=dev PL_BUILD_VARIANT=all PL_BUILD_LOCATION=remote turbo run build",
"build:dev-no-software": "env PL_BUILD_CHANNEL=dev PL_BUILD_VARIANT=none turbo run build",
"build:dev-binary-existing": "env PL_BUILD_CHANNEL=dev PL_BUILD_USE_PUBLISHED=true turbo run build",
Expand Down
41 changes: 12 additions & 29 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ catalog:
# than introduced here, per the spec's requirement that the instrument already exist
# in the workspace. Versions follow blocks/redefine-clonotypes, its other consumer.
"@platforma-open/milaboratories.runenv-python-3": ^1.1.16
"@platforma-open/milaboratories.software-anarci": ^0.0.3
"@platforma-open/milaboratories.software-anarci": ^1.0.1

"vue": 3.5.24

Expand Down
10 changes: 5 additions & 5 deletions software/column-profile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"name": "@platforma-open/milaboratories.import-vdj.column-profile",
"version": "1.1.0",
"description": "Profile a csv/tsv's columns: value type and whether they hold amino-acid variable domains",
"type": "module",
"scripts": {
"build": "pl-pkg build",
"prepublishOnly": "pl-pkg prepublish",
"do-pack": "rm -f *.tgz && pl-pkg build && pnpm pack && mv platforma-open*.tgz package.tgz",
"build": "block-tools software build",
"do-pack": "shx rm -f *.tgz && block-tools software build && pnpm pack && shx mv platforma-open*.tgz package.tgz",
"changeset": "changeset",
"version-packages": "changeset version"
},
Expand All @@ -14,8 +14,8 @@
],
"dependencies": {},
"devDependencies": {
"@platforma-sdk/package-builder": "catalog:",
"@platforma-open/milaboratories.runenv-python-3": "catalog:"
"@platforma-open/milaboratories.runenv-python-3": "catalog:",
"@platforma-sdk/block-tools": "catalog:"
},
"block-software": {
"entrypoints": {
Expand Down
25 changes: 23 additions & 2 deletions software/column-profile/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,23 @@ def value_type(value: str) -> int:
return T_DOUBLE


# The workflow passes a name rather than the character. On the k8s and google-batch runners the
# backend serialises argv with Go's %q and re-runs it through `sh -c`: a real tab arrives here as
# the two characters \ and t, which csv.reader rejects outright. A plain word survives that
# round-trip, so the name is what crosses the boundary and the character is chosen here.
SEPARATOR_NAMES = {"tab": "\t", "comma": ",", "semicolon": ";"}


def resolve_separator(separator: str) -> str:
resolved = SEPARATOR_NAMES.get(separator, separator)
if len(resolved) != 1:
raise SystemExit(
f"--separator must be one of {sorted(SEPARATOR_NAMES)} or a single character,"
f" got {separator!r}"
)
return resolved


def profile(path: str, separator: str) -> dict:
with open(path, newline="", encoding="utf-8-sig") as f:
reader = csv.reader(f, delimiter=separator)
Expand Down Expand Up @@ -97,11 +114,15 @@ def profile(path: str, separator: str) -> dict:
def main() -> None:
p = argparse.ArgumentParser(description="Profile a csv/tsv's columns")
p.add_argument("--input", required=True, help="Input csv or tsv")
p.add_argument("--separator", required=True, help="Field separator")
p.add_argument(
"--separator",
required=True,
help='Field separator: a name ("tab", "comma", "semicolon") or the character itself',
)
p.add_argument("--output", required=True, help="Output JSON")
args = p.parse_args()

result = profile(args.input, args.separator)
result = profile(args.input, resolve_separator(args.separator))
with open(args.output, "w") as f:
json.dump(result, f, sort_keys=True)

Expand Down
10 changes: 5 additions & 5 deletions software/region-annotation/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"name": "@platforma-open/milaboratories.import-vdj.region-annotation",
"version": "1.1.0",
"description": "Locate FR/CDR region boundaries in amino-acid antibody variable domains from ANARCI numbering",
"type": "module",
"scripts": {
"build": "pl-pkg build",
"prepublishOnly": "pl-pkg prepublish",
"do-pack": "rm -f *.tgz && pl-pkg build && pnpm pack && mv platforma-open*.tgz package.tgz",
"build": "block-tools software build",
"do-pack": "shx rm -f *.tgz && block-tools software build && pnpm pack && shx mv platforma-open*.tgz package.tgz",
"changeset": "changeset",
"version-packages": "changeset version"
},
Expand All @@ -14,8 +14,8 @@
],
"dependencies": {},
"devDependencies": {
"@platforma-sdk/package-builder": "catalog:",
"@platforma-open/milaboratories.runenv-python-3": "catalog:"
"@platforma-open/milaboratories.runenv-python-3": "catalog:",
"@platforma-sdk/block-tools": "catalog:"
},
"block-software": {
"entrypoints": {
Expand Down
10 changes: 5 additions & 5 deletions software/xlsx-to-csv/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"name": "@platforma-open/milaboratories.import-vdj.xlsx-to-csv",
"version": "1.1.0",
"description": "Convert the first worksheet of a workbook to CSV so the pipeline only ever sees csv/tsv",
"type": "module",
"scripts": {
"build": "pl-pkg build",
"prepublishOnly": "pl-pkg prepublish",
"do-pack": "rm -f *.tgz && pl-pkg build && pnpm pack && mv platforma-open*.tgz package.tgz",
"build": "block-tools software build",
"do-pack": "shx rm -f *.tgz && block-tools software build && pnpm pack && shx mv platforma-open*.tgz package.tgz",
"changeset": "changeset",
"version-packages": "changeset version"
},
Expand All @@ -14,8 +14,8 @@
],
"dependencies": {},
"devDependencies": {
"@platforma-sdk/package-builder": "catalog:",
"@platforma-open/milaboratories.runenv-python-3": "catalog:"
"@platforma-open/milaboratories.runenv-python-3": "catalog:",
"@platforma-sdk/block-tools": "catalog:"
},
"block-software": {
"entrypoints": {
Expand Down
1 change: 0 additions & 1 deletion turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
"inputs": ["$TURBO_DEFAULT$"],
"env": [
"PL_DOCKER_REGISTRY_PUSH_TO",
"PL_PKG_DEV",
"PL_BUILD_CHANNEL",
"PL_BUILD_VARIANT",
"PL_BUILD_LOCATION",
Expand Down
7 changes: 6 additions & 1 deletion workflow/src/prerun.tpl.tengo
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ wf.body(func(args) {
// The mapping dropdowns need the file's headers, and on this door nothing upstream
// supplies them. The separator comes from what the UI read out of the file's own first
// line rather than from the filename, which may not match the content.
separator := readable.extension == "csv" ? "," : "\t"
//
// A name, not the character itself: on the k8s and google-batch runners the backend
// serialises argv with Go's %q and re-runs it through `sh -c`, which turns a real tab
// into the two characters \t and leaves them that way. Only plain words survive that
// round-trip intact. profile-columns maps the name back.
separator := readable.extension == "csv" ? "comma" : "tab"
// The whole file, not a head: the panel needs each column's value type and whether it
// holds amino-acid domains, and both are wrong if taken from a sample. See
// profile-columns.
Expand Down
2 changes: 2 additions & 0 deletions workflow/src/profile-columns.tpl.tengo
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ self.defineOutputs("profile")

self.body(func(inputs) {
ll.assert(inputs.file != undefined, "profile-columns: file is required")
// A name — "tab" or "comma" — not the character. See prerun: a real tab does not survive
// the `sh -c` round-trip the k8s runner puts argv through. main.py maps the name back.
ll.assert(inputs.separator != undefined, "profile-columns: separator is required")

cmd := exec.builder().
Expand Down
Loading