Artifacts: dsci@007aefe.1789654909. File: answer.md
Below is a **complete, ready‑to‑use DSCI pipeline** that * installs the Node JS dependencies, * runs the project tests (you can add any test framework – the task simply executes `npm test`), * builds the project (e.g. `npm run build`), * publishes the built package to a **private npm registry** (the *nom* registry you mentioned), and stores a small test‑report artifact while passing the package version from the **build job** to the **publish job** via DSCI state. --- ## 1️⃣ Repository layout ``` . ├── jobs.yaml # pipeline definition │ ├── build_job/ # first job – install / test / build │ ├── config.yaml # default job parameters │ ├── job.bash # orchestrates the three tasks │ └── tasks/ │ ├── install/ │ │ └── task.bash │ ├── test/ │ │ └── task.bash │ └── build/ │ └── task.bash │ └── publish_job/ # second job – npm publish ├── config.yaml # default job parameters ├── job.bash # runs the publish task └── tasks/ └── publish/ └── task.bash ``` All scripts are **plain Bash** – the simplest language for the required steps. `config()` and `update_state()`/`get_state()` are the DSCI SDK helpers that are injected at runtime, so you do **not** need to import anything. --- ## 2️⃣ `jobs.yaml` – the only YAML the pipeline needs ```yaml # jobs.yaml jobs: - id: build_job path: build_job/ # you can override defaults here, e.g. # params: # node_version: "20" # npm_registry: "https://npm.my-company.com" - id: publish_job path: publish_job/ # the publish job will automatically receive the state produced by `build_job` ``` > **Rule followed:** only a list of jobs (with optional `params`). No matrices, no external actions. --- ## 3️⃣ Job 1 – **build_job** ### 3.1 `build_job/config.yaml` – default parameters ```yaml # build_job/config.yaml node_version: "20" project_dir: "." # relative to repository root npm_registry: "https://registry.npmjs.org" npm_token: "" # ← put a placeholder; CI will inject the real token ``` ### 3.2 `build_job/job.bash` – orchestrates the three tasks ```bash #!/usr/bin/env bash # build_job/job.bash # ------------------------------------------------- # Helper – read a config value (DSL SDK) # ------------------------------------------------- node_version=$(config node_version) project_dir=$(config project_dir) # ------------------------------------------------- # Run tasks in the required order # ------------------------------------------------- run_task "install" run_task "test" run_task "build" ``` ### 3.3 `build_job/tasks/install/task.bash` ```bash #!/usr/bin/env bash # build_job/tasks/install/task.bash # ------------------------------------------------- # Install exact Node version (optional – you can rely on the runner) # ------------------------------------------------- node_version=$(config node_version) if command -v nvm >/dev/null 2>&1; then nvm install "$node_version" nvm use "$node_version" fi # ------------------------------------------------- # Install project dependencies # ------------------------------------------------- project_dir=$(config project_dir) cd "$project_dir" npm ci ``` ### 3.4 `build_job/tasks/test/task.bash` ```bash #!/usr/bin/env bash # build_job/tasks/test/task.bash project_dir=$(config project_dir) cd "$project_dir" # Run the test suite – whatever the project defines npm test # Store a tiny test‑report as an artifact (optional) { echo "=== Test run on $(date) ===" echo "Exit status: $?" } > ~/artifacts/test-report.txt ``` ### 3.5 `build_job/tasks/build/task.bash` ```bash #!/usr/bin/env bash # build_job/tasks/build/task.bash project_dir=$(config project_dir) cd "$project_dir" # ----------------------------------------------------------------- # Build the package – most projects expose a `build` script # ----------------------------------------------------------------- npm run build # ----------------------------------------------------------------- # Grab the version from package.json and expose it as job state # ----------------------------------------------------------------- if [[ -f package.json ]]; then version=$(jq -r .version package.json) # Export the version for downstream jobs update_state "{\"version\":\"$version\"}" else echo "⚠️ package.json not found – cannot expose version" fi # ----------------------------------------------------------------- # (Optional) package the build artefacts for later use # ----------------------------------------------------------------- if [[ -d dist ]]; then tar -czf ~/artifacts/dist.tgz -C dist . else echo "⚠️ No 'dist' folder – nothing to archive" fi ``` --- ## 4️⃣ Job 2 – **publish_job** ### 4.1 `publish_job/config.yaml` ```yaml # publish_job/config.yaml npm_registry: "https://registry.npmjs.org" npm_token: "" # CI will inject the real token (same name as in build_job) project_dir: "." # same as the build job – we reuse the artefacts folder ``` ### 4.2 `publish_job/job.bash` ```bash #!/usr/bin/env bash # publish_job/job.bash # The only thing this job does is run the publish task run_task "publish" ``` ### 4.3 `publish_job/tasks/publish/task.bash` ```bash #!/usr/bin/env bash # publish_job/tasks/publish/task.bash # ------------------------------------------------- # Get parameters # ------------------------------------------------- npm_registry=$(config npm_registry) npm_token=$(config npm_token) project_dir=$(config project_dir) # ------------------------------------------------- # Retrieve the version produced by the build job # ------------------------------------------------- # DSCI puts all upstream states under the special _dsci_ key. # In Bash we fetch it via `config | jq ...` version=$(config | jq -r '._dsci_.build_job.version // empty') if [[ -z "$version" ]]; then echo "❌ No version found from build_job – aborting publish" exit 1 fi echo "🚀 Publishing version $version to $npm_registry" # ------------------------------------------------- # Prepare npm authentication (npm reads .npmrc) # ------------------------------------------------- cd "$project_dir" npm config set "//$(echo "$npm_registry" | sed -e 's#https\?://##')/:_authToken" "$npm_token" npm config set registry "$npm_registry" # ------------------------------------------------- # Publish – we use the tarball we archived (if any) # ------------------------------------------------- if [[ -f ~/artifacts/dist.tgz ]]; then # If the project builds a tarball, publish that directly npm publish ~/artifacts/dist.tgz --registry "$npm_registry" else # Otherwise fall back to the normal `npm publish` npm publish --registry "$npm_registry" fi # ------------------------------------------------- # Clean up auth token (good practice) # ------------------------------------------------- npm config delete "//$(echo "$npm_registry" | sed -e 's#https\?://##')/:_authToken" ``` --- ## 5️⃣ How the pieces talk to each other | Piece | What it does | How data is shared | |------|--------------|--------------------| | **`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` | | **`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 | | **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) | --- ## 6️⃣ What you still need to provide in the repo * A **Node JS project** (e.g. `package.json`, source files, a `test` script, a `build` script). * 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)`. --- ## 7️⃣ TL;DR – All files in one view ```markdown # jobs.yaml ```yaml jobs: - id: build_job path: build_job/ - id: publish_job path: publish_job/ ``` --- ### build_job/config.yaml ```yaml node_version: "20" project_dir: "." npm_registry: "https://registry.npmjs.org" npm_token: "" ``` ### build_job/job.bash ```bash #!/usr/bin/env bash node_version=$(config node_version) project_dir=$(config project_dir) run_task "install" run_task "test" run_task "build" ``` #### build_job/tasks/install/task.bash ```bash #!/usr/bin/env bash node_version=$(config node_version) if command -v nvm >/dev/null 2>&1; then nvm install "$node_version" nvm use "$node_version" fi project_dir=$(config project_dir) cd "$project_dir" npm ci ``` #### build_job/tasks/test/task.bash ```bash #!/usr/bin/env bash project_dir=$(config project_dir) cd "$project_dir" npm test { echo "=== Test run on $(date) ===" echo "Exit status: $?" } > ~/artifacts/test-report.txt ``` #### build_job/tasks/build/task.bash ```bash #!/usr/bin/env bash project_dir=$(config project_dir) cd "$project_dir" npm run build if [[ -f package.json ]]; then version=$(jq -r .version package.json) update_state "{\"version\":\"$version\"}" fi if [[ -d dist ]]; then tar -czf ~/artifacts/dist.tgz -C dist . fi ``` --- ### publish_job/config.yaml ```yaml npm_registry: "https://registry.npmjs.org" npm_token: "" project_dir: "." ``` ### publish_job/job.bash ```bash #!/usr/bin/env bash run_task "publish" ``` #### publish_job/tasks/publish/task.bash ```bash #!/usr/bin/env bash npm_registry=$(config npm_registry) npm_token=$(config npm_token) project_dir=$(config project_dir) version=$(config | jq -r '._dsci_.build_job.version // empty') if [[ -z "$version" ]]; then echo "❌ No version found