DSCI Report: dsci@007aefe.1789736466
13:01:08 :: [repository] - index updated from http://sparrowhub.io/repo/api/v1/index run stage: main [task run: task.bash - create directory scm] [task stdout] 13:01:09 :: directory path: scm 13:01:09 :: directory owner: <ubuntu> 13:01:09 :: directory group: <ubuntu> 13:01:09 :: directory access rights: drwxr-xr-x scm: http://localhost:8080/pipeline-generator.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/pipeline-generator ...] [task stdout] 13:01:09 :: /home/ubuntu/.dsci/.sparky/.cache/007aefe.1789736466/.sparrowdo/scm [task stderr] 13:01:10 :: Cloning into '.'... [task run: task.bash - bash: git checkout 007aefe] [task stdout] 13:01:10 :: /home/ubuntu/.dsci/.sparky/.cache/007aefe.1789736466/.sparrowdo/scm [task stderr] 13:01:10 :: HEAD is now at 007aefe keep question pipeline mode: localhost run dsci agent container from image: melezhik/dsci-agent-rakupp ai_agent_message set: 4275696c64204453434920706970656c696e6520666f72205048502070726f6a656374207769746820756e697420746573747320616e6420696e7374616c6c696e6720504850206f662073706563696669632076657273696f6e20666f722044656269616e20 >>> 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/jsmyxcoepqngtbhiwvua.4109216 job test ... [OK] ... >>> GET job report, status=200 13:01:18 :: [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/jsmyxcoepqngtbhiwvua.4109216 [task run: task.bash - create directory scm] [task stdout] 13:01:19 :: directory path: scm 13:01:19 :: directory owner: <ubuntu> 13:01:19 :: directory group: <ubuntu> 13:01:19 :: directory access rights: drwxr-xr-x [task run: task.bash - bash: git clone http://localhost:8080/pipeline-generator ...] [task stdout] 13:01:19 :: /home/ubuntu/.dsci/.sparky/.cache/jsmyxcoepqngtbhiwvua.4109216/.sparrowdo/scm [task stderr] 13:01:19 :: Cloning into '.'... [task run: task.bash - bash: git checkout 007aefe] [task stdout] 13:01:20 :: /home/ubuntu/.dsci/.sparky/.cache/jsmyxcoepqngtbhiwvua.4109216/.sparrowdo/scm [task stderr] 13:01:20 :: 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/jsmyxcoepqngtbhiwvua.4109216 [task run: task.bash - .] [task stdout] 13:01:20 :: total 8 13:01:20 :: -rw-r--r-- 1 ubuntu ubuntu 109 Sep 18 13:01 jobs.yaml 13:01:20 :: -rw-r--r-- 1 ubuntu ubuntu 301 Sep 18 13:01 task.bash 13:01:20 :: 4275696c64204453434920706970656c696e6520666f72205048502070726f6a656374207769746820756e697420746573747320616e6420696e7374616c6c696e6720504850206f662073706563696669632076657273696f6e20666f722044656269616e20 13:01:25 :: === 13:01:25 :: Build DSCI pipeline for PHP project with unit tests and installing PHP of specific version for Debian 13:01:25 :: === 13:01:25 :: **File structure** 13:01:25 :: 13:01:25 :: ``` 13:01:25 :: . 13:01:25 :: ├── jobs.yaml 13:01:25 :: ├── job_build/ 13:01:25 :: │ ├── config.yaml 13:01:25 :: │ ├── job.bash 13:01:25 :: │ └── tasks 13:01:25 :: │ ├── install_php 13:01:25 :: │ │ └── task.bash 13:01:25 :: │ ├── composer_install 13:01:25 :: │ │ └── task.bash 13:01:25 :: │ └── run_tests 13:01:25 :: │ └── task.bash 13:01:25 :: ``` 13:01:25 :: 13:01:25 :: --- 13:01:25 :: 13:01:25 :: ## `jobs.yaml` 13:01:25 :: 13:01:25 :: ```yaml 13:01:25 :: # .dsci/jobs.yaml 13:01:25 :: jobs: 13:01:25 :: - 13:01:25 :: id: build 13:01:25 :: path: job_build/ 13:01:25 :: # Optional override of the PHP version (default is defined in config.yaml) 13:01:25 :: # params: 13:01:25 :: # php_version: "8.2" 13:01:25 :: ``` 13:01:25 :: 13:01:25 :: --- 13:01:25 :: 13:01:25 :: ## `job_build/config.yaml` *(default job parameters)* 13:01:25 :: 13:01:25 :: ```yaml 13:01:25 :: php_version: "8.2" 13:01:25 :: ``` 13:01:25 :: 13:01:25 :: --- 13:01:25 :: 13:01:25 :: ## `job_build/job.bash` *(orchestrates the tasks)* 13:01:25 :: 13:01:25 :: ```bash 13:01:25 :: #!/usr/bin/env bash 13:01:25 :: # job_build/job.bash 13:01:25 :: 13:01:25 :: # Run tasks sequentially 13:01:25 :: run_task "install_php" 13:01:25 :: run_task "composer_install" 13:01:25 :: run_task "run_tests" 13:01:25 :: ``` 13:01:25 :: 13:01:25 :: --- 13:01:25 :: 13:01:25 :: ## `job_build/tasks/install_php/task.bash` 13:01:25 :: 13:01:25 :: ```bash 13:01:25 :: #!/usr/bin/env bash 13:01:25 :: # job_build/tasks/install_php/task.bash 13:01:25 :: 13:01:25 :: # ------------------------------------------------------------------ 13:01:25 :: # Install a specific PHP version on Debian (using apt) 13:01:25 :: # ------------------------------------------------------------------ 13:01:25 :: 13:01:25 :: # Retrieve the requested version from job parameters (or default) 13:01:25 :: php_version=$(config php_version) 13:01:25 :: 13:01:25 :: echo "=== Installing PHP ${php_version} on Debian ===" 13:01:25 :: 13:01:25 :: # Update package index 13:01:25 :: apt-get update -y 13:01:25 :: 13:01:25 :: # Add the sury.org repository (commonly used for multiple PHP versions) 13:01:25 :: apt-get install -y lsb-release ca-certificates apt-transport-https software-properties-common wget gnupg2 13:01:25 :: 13:01:25 :: wget -qO /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg 13:01:25 :: echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list 13:01:25 :: 13:01:25 :: apt-get update -y 13:01:25 :: 13:01:25 :: # Install the requested PHP version and common extensions 13:01:25 :: apt-get install -y php${php_version} php${php_version}-cli php${php_version}-common php${php_version}-mbstring php${php_version}-xml php${php_version}-curl php${php_version}-zip 13:01:25 :: 13:01:25 :: # Verify installation 13:01:25 :: php -v 13:01:25 :: 13:01:25 :: # Export the installed version as state for downstream tasks (optional) 13:01:25 :: update_state '{"php_version":"'"$php_version"'"}' 13:01:25 :: ``` 13:01:25 :: 13:01:25 :: --- 13:01:25 :: 13:01:25 :: ## `job_build/tasks/composer_install/task.bash` 13:01:25 :: 13:01:25 :: ```bash 13:01:25 :: #!/usr/bin/env bash 13:01:25 :: # job_build/tasks/composer_install/task.bash 13:01:25 :: 13:01:25 :: # ------------------------------------------------------------------ 13:01:25 :: # Install Composer (if not present) and run `composer install` 13:01:25 :: # ------------------------------------------------------------------ 13:01:25 :: 13:01:25 :: # Ensure PHP is available (state from previous task) 13:01:25 :: php_version=$(config php_version) # just to prove we can read it again 13:01:25 :: 13:01:25 :: # Install Composer globally 13:01:25 :: if ! command -v composer >/dev/null 2>&1; then 13:01:25 :: echo "=== Installing Composer ===" 13:01:25 :: EXPECTED_CHECKSUM="$(php -r 'copy("https://composer.github.io/installer.sig", "php://stdout");')" 13:01:25 :: php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" 13:01:25 :: ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")" 13:01:25 :: 13:01:25 :: if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]; then 13:01:25 :: echo 'ERROR: Invalid Composer installer checksum' 13:01:25 :: exit 1 13:01:25 :: fi 13:01:25 :: 13:01:25 :: php composer-setup.php --install-dir=/usr/local/bin --filename=composer 13:01:25 :: rm composer-setup.php 13:01:25 :: fi 13:01:25 :: 13:01:25 :: composer --version 13:01:25 :: 13:01:25 :: # Install project dependencies 13:01:25 :: if [ -f composer.json ]; then 13:01:25 :: echo "=== Running composer install ===" 13:01:25 :: composer install --no-interaction --prefer-dist --optimize-autoloader 13:01:25 :: else 13:01:25 :: echo "WARNING: composer.json not found – skipping dependency install" 13:01:25 :: fi 13:01:25 :: ``` 13:01:25 :: 13:01:25 :: --- 13:01:25 :: 13:01:25 :: ## `job_build/tasks/run_tests/task.bash` 13:01:25 :: 13:01:25 :: ```bash 13:01:25 :: #!/usr/bin/env bash 13:01:25 :: # job_build/tasks/run_tests/task.bash 13:01:25 :: 13:01:25 :: # ------------------------------------------------------------------ 13:01:25 :: # Run PHP unit tests (phpunit) and store the result as an artifact 13:01:25 :: # ------------------------------------------------------------------ 13:01:25 :: 13:01:25 :: # Ensure phpunit is available – try local vendor binary first 13:01:25 :: if [ -f vendor/bin/phpunit ]; then 13:01:25 :: PHPUNIT_CMD="vendor/bin/phpunit" 13:01:25 :: else 13:01:25 :: # Fallback: install phpunit globally for the requested PHP version 13:01:25 :: echo "phpunit not found locally – installing globally" 13:01:25 :: apt-get install -y php${php_version}-phpunit || true # some Debian versions ship phpunit as a package 13:01:25 :: PHPUNIT_CMD="phpunit" 13:01:25 :: fi 13:01:25 :: 13:01:25 :: # Run the tests 13:01:25 :: echo "=== Executing PHP Unit Tests ===" 13:01:25 :: set -o pipefail 13:01:25 :: TEST_OUTPUT=$($PHPUNIT_CMD 2>&1 | tee /dev/stdout) 13:01:25 :: TEST_EXIT_CODE=${PIPESTATUS[0]} 13:01:25 :: 13:01:25 :: # Save the raw output as an artifact 13:01:25 :: ARTIFACT_DIR="${HOME}/artifacts" 13:01:25 :: mkdir -p "$ARTIFACT_DIR" 13:01:25 :: echo "$TEST_OUTPUT" > "$ARTIFACT_DIR/phpunit_output.txt" 13:01:25 :: 13:01:25 :: # Export test result state (pass/fail) for potential downstream jobs 13:01:25 :: if [ "$TEST_EXIT_CODE" -eq 0 ]; then 13:01:25 :: test_status="passed" 13:01:25 :: else 13:01:25 :: test_status="failed" 13:01:25 :: fi 13:01:25 :: update_state '{"test_status":"'"$test_status"'"}' 13:01:25 :: 13:01:25 :: # Exit with the original phpunit status so the pipeline fails on test failures 13:01:25 :: exit "$TEST_EXIT_CODE" 13:01:25 :: ``` 13:01:25 :: 13:01:25 :: --- 13:01:25 :: 13:01:25 :: ### How the pipeline works 13:01:25 :: 13:01:25 :: 1. **Job `build`** is listed in `jobs.yaml`. 13:01:25 :: 2. The job reads its default parameter `php_version` from `job_build/config.yaml`. 13:01:25 :: 3. **Task `install_php`** installs the requested PHP version on a Debian‑based runner and stores the version in the job state. 13:01:25 :: 4. **Task `composer_install`** ensures Composer is present and installs project dependencies. 13:01:25 :: 5. **Task `run_tests`** runs `phpunit`, writes the full console output to `~/artifacts/phpunit_output.txt` (so any later job could read it) and exports a simple `test_status` state (`passed`/`failed`). 13:01:25 :: 13:01:25 :: All logic lives in standard Bash scripts; the tiny `jobs.yaml` only declares the job and its optional parameters, satisfying the DSCI “99 % less YAML” principle. [task stderr] 13:01:25 :: 13:01:25 :: real 0m4.984s 13:01:25 :: user 0m0.611s 13:01:25 :: sys 0m0.100s saving job artifacts ... >> PUT http://127.0.0.1:8181/file/project/dsci/job/007aefe.1789736466/filename/answer.md >> PUT http://127.0.0.1:8181/file/project/dsci/job/007aefe.1789736466/filename/question.txt >>> POST http://127.0.0.1:8181/stash --- ---