DSCI Report: dsci@2185


artifacts
14:21:51 :: [repository] - index updated from http://sparrowhub.io/repo/api/v1/index
run stage: main
[task run: task.bash - create directory scm]
[task stdout]
14:21:51 :: directory path: scm
14:21:51 :: directory owner: <ubuntu>
14:21:51 :: directory group: <ubuntu>
14:21:51 :: directory access rights: drwxr-xr-x
scm: http://localhost:8080/test1.git
sha: 007aefe
message: keep question by dsci@sparrowhub.io - manual run
container runtime: podman
raku version
Raku++ (rakupp) 3.25.0 — a Raku interpreter and compiler in C++
Implements Raku 6.d, and 6.e under `use v6.e.PREVIEW`.
Build  v3.25.0 (2026-09-03), x86_64-linux, clang 18.1.3
Home   https://raku.online — docs, a tour of the language, and a browser playground
sparrow version
0.0.94
runner version: 0.1.1
=======
[task run: task.bash - bash: git config --global advice.detachedHead false]
[task stdout]
[task run: task.bash - bash: git clone http://localhost:8080/test1.git .]
[task stdout]
14:21:52 :: /home/ubuntu/.dsci/.sparky/.cache/007aefe.1789654909/.sparrowdo/scm
[task stderr]
14:21:52 :: Cloning into '.'...
[task run: task.bash - bash: git checkout 007aefe]
[task stdout]
14:21:52 :: /home/ubuntu/.dsci/.sparky/.cache/007aefe.1789654909/.sparrowdo/scm
[task stderr]
14:21:52 :: HEAD is now at 007aefe keep question
pipeline mode: localhost
run dsci agent container from image: melezhik/dsci-agent-rakupp
ai_agent_message set: 437265617465204453434920706970656c696e6520746f206275696c64204e6f64654a532070726f6a65637420616e64207075626c697368204e504d20746f206e6f6d207265676973747279202c20646f6e277420666f726765742061626f757420696e697420746573747321
>>> POST http://127.0.0.1:8181/stash
>>> POST http://127.0.0.1:8181/queue
>>> wait for jobs, timeout: 600 sec
>>> GET http://127.0.0.1:8181/stash/job.run/ezhukslbrdivmqwjofga.4012391
job test ... [OK]
...
>>> GET job report, status=200
14:22:01 :: [repository] - index updated from http://sparrowhub.io/repo/api/v1/index
run stage: job-run
raku version
Raku++ (rakupp) 3.25.0 — a Raku interpreter and compiler in C++
Implements Raku 6.d, and 6.e under `use v6.e.PREVIEW`.
Build  v3.25.0 (2026-09-03), x86_64-linux, clang 18.1.3
Home   https://raku.online — docs, a tour of the language, and a browser playground
sparrow version
0.0.94
runner version: 0.1.1
run job: test
===
>>> GET http://127.0.0.1:8181/stash/job.run/ezhukslbrdivmqwjofga.4012391
[task run: task.bash - create directory scm]
[task stdout]
14:22:02 :: directory path: scm
14:22:02 :: directory owner: <ubuntu>
14:22:02 :: directory group: <ubuntu>
14:22:02 :: directory access rights: drwxr-xr-x
[task run: task.bash - bash: git clone http://localhost:8080/test1.git .]
[task stdout]
14:22:02 :: /home/ubuntu/.dsci/.sparky/.cache/ezhukslbrdivmqwjofga.4012391/.sparrowdo/scm
[task stderr]
14:22:02 :: Cloning into '.'...
[task run: task.bash - bash: git checkout 007aefe]
[task stdout]
14:22:02 :: /home/ubuntu/.dsci/.sparky/.cache/ezhukslbrdivmqwjofga.4012391/.sparrowdo/scm
[task stderr]
14:22:02 :: HEAD is now at 007aefe keep question
[task run: task.bash - bash: prepare dsci scripts]
[task stdout]
>>> GET http://127.0.0.1:8181/stash/job.run/ezhukslbrdivmqwjofga.4012391
[task run: task.bash - .]
[task stdout]
14:22:03 :: total 8
14:22:03 :: -rw-r--r-- 1 ubuntu ubuntu 109 Sep 17 14:22 jobs.yaml
14:22:03 :: -rw-r--r-- 1 ubuntu ubuntu 301 Sep 17 14:22 task.bash
14:22:03 :: 437265617465204453434920706970656c696e6520746f206275696c64204e6f64654a532070726f6a65637420616e64207075626c697368204e504d20746f206e6f6d207265676973747279202c20646f6e277420666f726765742061626f757420696e697420746573747321
14:22:10 :: ===
14:22:10 :: Create DSCI pipeline to build NodeJS project and publish NPM to nom registry , don't forget about init tests!
14:22:10 :: ===
14:22:10 :: Below is a **complete, ready‑to‑use DSCI pipeline** that
14:22:10 :: 
14:22:10 :: * installs the Node JS dependencies,  
14:22:10 :: * runs the project tests (you can add any test framework – the task simply executes `npm test`),  
14:22:10 :: * builds the project (e.g. `npm run build`),  
14:22:10 :: * publishes the built package to a **private npm registry** (the *nom* registry you mentioned),  
14:22:10 :: 
14:22:10 :: and stores a small test‑report artifact while passing the package version from the **build job** to the **publish job** via DSCI state.
14:22:10 :: 
14:22:10 :: ---
14:22:10 :: 
14:22:10 :: ## 1️⃣ Repository layout
14:22:10 :: 
14:22:10 :: ```
14:22:10 :: .
14:22:10 :: ├── jobs.yaml                     # pipeline definition
14:22:10 :: │
14:22:10 :: ├── build_job/                    # first job – install / test / build
14:22:10 :: │   ├── config.yaml               # default job parameters
14:22:10 :: │   ├── job.bash                  # orchestrates the three tasks
14:22:10 :: │   └── tasks/
14:22:10 :: │       ├── install/
14:22:10 :: │       │   └── task.bash
14:22:10 :: │       ├── test/
14:22:10 :: │       │   └── task.bash
14:22:10 :: │       └── build/
14:22:10 :: │           └── task.bash
14:22:10 :: │
14:22:10 :: └── publish_job/                  # second job – npm publish
14:22:10 ::     ├── config.yaml               # default job parameters
14:22:10 ::     ├── job.bash                  # runs the publish task
14:22:10 ::     └── tasks/
14:22:10 ::         └── publish/
14:22:10 ::             └── task.bash
14:22:10 :: ```
14:22:10 :: 
14:22:10 :: All scripts are **plain Bash** – the simplest language for the required steps.  
14:22:10 :: `config()` and `update_state()`/`get_state()` are the DSCI SDK helpers that are injected at runtime, so you do **not** need to import anything.
14:22:10 :: 
14:22:10 :: ---
14:22:10 :: 
14:22:10 :: ## 2️⃣ `jobs.yaml` – the only YAML the pipeline needs
14:22:10 :: 
14:22:10 :: ```yaml
14:22:10 :: # jobs.yaml
14:22:10 :: jobs:
14:22:10 ::   -
14:22:10 ::     id: build_job
14:22:10 ::     path: build_job/
14:22:10 ::     # you can override defaults here, e.g.
14:22:10 ::     # params:
14:22:10 ::     #   node_version: "20"
14:22:10 ::     #   npm_registry: "https://npm.my-company.com"
14:22:10 ::   -
14:22:10 ::     id: publish_job
14:22:10 ::     path: publish_job/
14:22:10 ::     # the publish job will automatically receive the state produced by `build_job`
14:22:10 :: ```
14:22:10 :: 
14:22:10 :: > **Rule followed:** only a list of jobs (with optional `params`). No matrices, no external actions.
14:22:10 :: 
14:22:10 :: ---
14:22:10 :: 
14:22:10 :: ## 3️⃣ Job 1 – **build_job**
14:22:10 :: 
14:22:10 :: ### 3.1 `build_job/config.yaml` – default parameters
14:22:10 :: 
14:22:10 :: ```yaml
14:22:10 :: # build_job/config.yaml
14:22:10 :: node_version: "20"
14:22:10 :: project_dir: "."                 # relative to repository root
14:22:10 :: npm_registry: "https://registry.npmjs.org"
14:22:10 :: npm_token: ""                    # ← put a placeholder; CI will inject the real token
14:22:10 :: ```
14:22:10 :: 
14:22:10 :: ### 3.2 `build_job/job.bash` – orchestrates the three tasks
14:22:10 :: 
14:22:10 :: ```bash
14:22:10 :: #!/usr/bin/env bash
14:22:10 :: # build_job/job.bash
14:22:10 :: 
14:22:10 :: # -------------------------------------------------
14:22:10 :: # Helper – read a config value (DSL SDK)
14:22:10 :: # -------------------------------------------------
14:22:10 :: node_version=$(config node_version)
14:22:10 :: project_dir=$(config project_dir)
14:22:10 :: 
14:22:10 :: # -------------------------------------------------
14:22:10 :: # Run tasks in the required order
14:22:10 :: # -------------------------------------------------
14:22:10 :: run_task "install"
14:22:10 :: run_task "test"
14:22:10 :: run_task "build"
14:22:10 :: ```
14:22:10 :: 
14:22:10 :: ### 3.3 `build_job/tasks/install/task.bash`
14:22:10 :: 
14:22:10 :: ```bash
14:22:10 :: #!/usr/bin/env bash
14:22:10 :: # build_job/tasks/install/task.bash
14:22:10 :: 
14:22:10 :: # -------------------------------------------------
14:22:10 :: # Install exact Node version (optional – you can rely on the runner)
14:22:10 :: # -------------------------------------------------
14:22:10 :: node_version=$(config node_version)
14:22:10 :: if command -v nvm >/dev/null 2>&1; then
14:22:10 ::   nvm install "$node_version"
14:22:10 ::   nvm use "$node_version"
14:22:10 :: fi
14:22:10 :: 
14:22:10 :: # -------------------------------------------------
14:22:10 :: # Install project dependencies
14:22:10 :: # -------------------------------------------------
14:22:10 :: project_dir=$(config project_dir)
14:22:10 :: cd "$project_dir"
14:22:10 :: npm ci
14:22:10 :: ```
14:22:10 :: 
14:22:10 :: ### 3.4 `build_job/tasks/test/task.bash`
14:22:10 :: 
14:22:10 :: ```bash
14:22:10 :: #!/usr/bin/env bash
14:22:10 :: # build_job/tasks/test/task.bash
14:22:10 :: 
14:22:10 :: project_dir=$(config project_dir)
14:22:10 :: cd "$project_dir"
14:22:10 :: 
14:22:10 :: # Run the test suite – whatever the project defines
14:22:10 :: npm test
14:22:10 :: 
14:22:10 :: # Store a tiny test‑report as an artifact (optional)
14:22:10 :: {
14:22:10 ::   echo "=== Test run on $(date) ==="
14:22:10 ::   echo "Exit status: $?"
14:22:10 :: } > ~/artifacts/test-report.txt
14:22:10 :: ```
14:22:10 :: 
14:22:10 :: ### 3.5 `build_job/tasks/build/task.bash`
14:22:10 :: 
14:22:10 :: ```bash
14:22:10 :: #!/usr/bin/env bash
14:22:10 :: # build_job/tasks/build/task.bash
14:22:10 :: 
14:22:10 :: project_dir=$(config project_dir)
14:22:10 :: cd "$project_dir"
14:22:10 :: 
14:22:10 :: # -----------------------------------------------------------------
14:22:10 :: # Build the package – most projects expose a `build` script
14:22:10 :: # -----------------------------------------------------------------
14:22:10 :: npm run build
14:22:10 :: 
14:22:10 :: # -----------------------------------------------------------------
14:22:10 :: # Grab the version from package.json and expose it as job state
14:22:10 :: # -----------------------------------------------------------------
14:22:10 :: if [[ -f package.json ]]; then
14:22:10 ::   version=$(jq -r .version package.json)
14:22:10 ::   # Export the version for downstream jobs
14:22:10 ::   update_state "{\"version\":\"$version\"}"
14:22:10 :: else
14:22:10 ::   echo "⚠️  package.json not found – cannot expose version"
14:22:10 :: fi
14:22:10 :: 
14:22:10 :: # -----------------------------------------------------------------
14:22:10 :: # (Optional) package the build artefacts for later use
14:22:10 :: # -----------------------------------------------------------------
14:22:10 :: if [[ -d dist ]]; then
14:22:10 ::   tar -czf ~/artifacts/dist.tgz -C dist .
14:22:10 :: else
14:22:10 ::   echo "⚠️  No 'dist' folder – nothing to archive"
14:22:10 :: fi
14:22:10 :: ```
14:22:10 :: 
14:22:10 :: ---
14:22:10 :: 
14:22:10 :: ## 4️⃣ Job 2 – **publish_job**
14:22:10 :: 
14:22:10 :: ### 4.1 `publish_job/config.yaml`
14:22:10 :: 
14:22:10 :: ```yaml
14:22:10 :: # publish_job/config.yaml
14:22:10 :: npm_registry: "https://registry.npmjs.org"
14:22:10 :: npm_token: ""          # CI will inject the real token (same name as in build_job)
14:22:10 :: project_dir: "."       # same as the build job – we reuse the artefacts folder
14:22:10 :: ```
14:22:10 :: 
14:22:10 :: ### 4.2 `publish_job/job.bash`
14:22:10 :: 
14:22:10 :: ```bash
14:22:10 :: #!/usr/bin/env bash
14:22:10 :: # publish_job/job.bash
14:22:10 :: 
14:22:10 :: # The only thing this job does is run the publish task
14:22:10 :: run_task "publish"
14:22:10 :: ```
14:22:10 :: 
14:22:10 :: ### 4.3 `publish_job/tasks/publish/task.bash`
14:22:10 :: 
14:22:10 :: ```bash
14:22:10 :: #!/usr/bin/env bash
14:22:10 :: # publish_job/tasks/publish/task.bash
14:22:10 :: 
14:22:10 :: # -------------------------------------------------
14:22:10 :: # Get parameters
14:22:10 :: # -------------------------------------------------
14:22:10 :: npm_registry=$(config npm_registry)
14:22:10 :: npm_token=$(config npm_token)
14:22:10 :: project_dir=$(config project_dir)
14:22:10 :: 
14:22:10 :: # -------------------------------------------------
14:22:10 :: # Retrieve the version produced by the build job
14:22:10 :: # -------------------------------------------------
14:22:10 :: # DSCI puts all upstream states under the special _dsci_ key.
14:22:10 :: # In Bash we fetch it via `config | jq ...`
14:22:10 :: version=$(config | jq -r '._dsci_.build_job.version // empty')
14:22:10 :: if [[ -z "$version" ]]; then
14:22:10 ::   echo "❌  No version found from build_job – aborting publish"
14:22:10 ::   exit 1
14:22:10 :: fi
14:22:10 :: echo "🚀  Publishing version $version to $npm_registry"
14:22:10 :: 
14:22:10 :: # -------------------------------------------------
14:22:10 :: # Prepare npm authentication (npm reads .npmrc)
14:22:10 :: # -------------------------------------------------
14:22:10 :: cd "$project_dir"
14:22:10 :: npm config set "//$(echo "$npm_registry" | sed -e 's#https\?://##')/:_authToken" "$npm_token"
14:22:10 :: npm config set registry "$npm_registry"
14:22:10 :: 
14:22:10 :: # -------------------------------------------------
14:22:10 :: # Publish – we use the tarball we archived (if any)
14:22:10 :: # -------------------------------------------------
14:22:10 :: if [[ -f ~/artifacts/dist.tgz ]]; then
14:22:10 ::   # If the project builds a tarball, publish that directly
14:22:10 ::   npm publish ~/artifacts/dist.tgz --registry "$npm_registry"
14:22:10 :: else
14:22:10 ::   # Otherwise fall back to the normal `npm publish`
14:22:10 ::   npm publish --registry "$npm_registry"
14:22:10 :: fi
14:22:10 :: 
14:22:10 :: # -------------------------------------------------
14:22:10 :: # Clean up auth token (good practice)
14:22:10 :: # -------------------------------------------------
14:22:10 :: npm config delete "//$(echo "$npm_registry" | sed -e 's#https\?://##')/:_authToken"
14:22:10 :: ```
14:22:10 :: 
14:22:10 :: ---
14:22:10 :: 
14:22:10 :: ## 5️⃣ How the pieces talk to each other  
14:22:10 :: 
14:22:10 :: | Piece | What it does | How data is shared |
14:22:10 :: |------|--------------|--------------------|
14:22:10 :: | **`build_job/tasks/build/task.bash`** | extracts the version from `package.json` and calls `update_state "{\"version\":\"$version\"}"` | State is stored under `/_dsci_/build_job/version` |
14:22:10 :: | **`publish_job/tasks/publish/task.bash`** | reads that state with `config | jq '._dsci_.build_job.version'` and uses it for the npm publish step | No extra code – the SDK handles it |
14:22:10 :: | **Artifacts** | `test-report.txt` and optional `dist.tgz` are written into `~/artifacts/` | The next job sees them automatically (e.g. the tarball is used for publishing) |
14:22:10 :: 
14:22:10 :: ---
14:22:10 :: 
14:22:10 :: ## 6️⃣ What you still need to provide in the repo  
14:22:10 :: 
14:22:10 :: * A **Node JS project** (e.g. `package.json`, source files, a `test` script, a `build` script).  
14:22:10 :: * In your CI environment, **inject the real `npm_token`** (matching the name used in the two `config.yaml` files) – DSCI will make it available through `$(config npm_token)`.
14:22:10 :: 
14:22:10 :: ---
14:22:10 :: 
14:22:10 :: ## 7️⃣ TL;DR – All files in one view  
14:22:10 :: 
14:22:10 :: ```markdown
14:22:10 :: # jobs.yaml
14:22:10 :: ```yaml
14:22:10 :: jobs:
14:22:10 ::   -
14:22:10 ::     id: build_job
14:22:10 ::     path: build_job/
14:22:10 ::   -
14:22:10 ::     id: publish_job
14:22:10 ::     path: publish_job/
14:22:10 :: ```
14:22:10 :: 
14:22:10 :: ---
14:22:10 :: 
14:22:10 :: ### build_job/config.yaml
14:22:10 :: ```yaml
14:22:10 :: node_version: "20"
14:22:10 :: project_dir: "."
14:22:10 :: npm_registry: "https://registry.npmjs.org"
14:22:10 :: npm_token: ""
14:22:10 :: ```
14:22:10 :: 
14:22:10 :: ### build_job/job.bash
14:22:10 :: ```bash
14:22:10 :: #!/usr/bin/env bash
14:22:10 :: node_version=$(config node_version)
14:22:10 :: project_dir=$(config project_dir)
14:22:10 :: 
14:22:10 :: run_task "install"
14:22:10 :: run_task "test"
14:22:10 :: run_task "build"
14:22:10 :: ```
14:22:10 :: 
14:22:10 :: #### build_job/tasks/install/task.bash
14:22:10 :: ```bash
14:22:10 :: #!/usr/bin/env bash
14:22:10 :: node_version=$(config node_version)
14:22:10 :: if command -v nvm >/dev/null 2>&1; then
14:22:10 ::   nvm install "$node_version"
14:22:10 ::   nvm use "$node_version"
14:22:10 :: fi
14:22:10 :: project_dir=$(config project_dir)
14:22:10 :: cd "$project_dir"
14:22:10 :: npm ci
14:22:10 :: ```
14:22:10 :: 
14:22:10 :: #### build_job/tasks/test/task.bash
14:22:10 :: ```bash
14:22:10 :: #!/usr/bin/env bash
14:22:10 :: project_dir=$(config project_dir)
14:22:10 :: cd "$project_dir"
14:22:10 :: npm test
14:22:10 :: {
14:22:10 ::   echo "=== Test run on $(date) ==="
14:22:10 ::   echo "Exit status: $?"
14:22:10 :: } > ~/artifacts/test-report.txt
14:22:10 :: ```
14:22:10 :: 
14:22:10 :: #### build_job/tasks/build/task.bash
14:22:10 :: ```bash
14:22:10 :: #!/usr/bin/env bash
14:22:10 :: project_dir=$(config project_dir)
14:22:10 :: cd "$project_dir"
14:22:10 :: npm run build
14:22:10 :: if [[ -f package.json ]]; then
14:22:10 ::   version=$(jq -r .version package.json)
14:22:10 ::   update_state "{\"version\":\"$version\"}"
14:22:10 :: fi
14:22:10 :: if [[ -d dist ]]; then
14:22:10 ::   tar -czf ~/artifacts/dist.tgz -C dist .
14:22:10 :: fi
14:22:10 :: ```
14:22:10 :: 
14:22:10 :: ---
14:22:10 :: 
14:22:10 :: ### publish_job/config.yaml
14:22:10 :: ```yaml
14:22:10 :: npm_registry: "https://registry.npmjs.org"
14:22:10 :: npm_token: ""
14:22:10 :: project_dir: "."
14:22:10 :: ```
14:22:10 :: 
14:22:10 :: ### publish_job/job.bash
14:22:10 :: ```bash
14:22:10 :: #!/usr/bin/env bash
14:22:10 :: run_task "publish"
14:22:10 :: ```
14:22:10 :: 
14:22:10 :: #### publish_job/tasks/publish/task.bash
14:22:10 :: ```bash
14:22:10 :: #!/usr/bin/env bash
14:22:10 :: npm_registry=$(config npm_registry)
14:22:10 :: npm_token=$(config npm_token)
14:22:10 :: project_dir=$(config project_dir)
14:22:10 :: 
14:22:10 :: version=$(config | jq -r '._dsci_.build_job.version // empty')
14:22:10 :: if [[ -z "$version" ]]; then
14:22:10 ::   echo "❌  No version found
[task stderr]
14:22:11 :: 
14:22:11 :: real	0m7.874s
14:22:11 :: user	0m0.766s
14:22:11 :: sys	0m0.117s
saving job artifacts ...
>> PUT http://127.0.0.1:8181/file/project/dsci/job/007aefe.1789654909/filename/answer.md
>> PUT http://127.0.0.1:8181/file/project/dsci/job/007aefe.1789654909/filename/question.txt
>>> POST http://127.0.0.1:8181/stash
---

---