HOS AIHOS AI
Draft

Run the checks in CI

Exit codes, JSON and JUnit output, and a complete GitHub Actions workflow.

On this page

In short

Every hos command ends with an exit code that a CI reads: 0 when everything passes, 1 when a check fails, 2 when the command itself is wrong. Run the checks on every change, keep their reports, and verify your published manifest every day, so that a broken fact or an expiring signature never reaches a hotel.

For
Developers and integrators who automate checks
Time
20 minutes
You need
A project in a Git repository · GitHub Actions, GitLab CI or another CI
Status
Draft

Why this matters

Trigger

A push, a pull request, or every morning.

Install

npm ci, with the exact version of hos.

Consumer

hos conformance run, with a JUnit report.

Producer

hos conformance producer on a recording and a redelivery.

Manifest

hos manifest verify --at 30 days ahead.
On every change, and every morning: the pinned version of hos, the conformance scenarios, the producer check on what the adapter publishes, and the published manifest verified 30 days ahead. Any exit code other than 0 fails the run.

The checks of the other guides catch problems when someone runs them. A CI runs them every time: a change to the adapter that breaks deduplication, or a new field that HOS does not accept, fails the build before it is merged. And a scheduled job warns you weeks before your manifest's signature expires, instead of the day every consumer stops trusting it.

Exit codes

CodeMeaningWhat the CI does
0everything is valid, or every check passedthe step passes
1a file is invalid, a check failed, or a signature does not verifythe step fails
2the command is wrong, or a file or URL could not be readthe step fails: fix the job, not the product

Every command also prints its result as JSON with --json, for a script that needs the details, and hos conformance run writes a JUnit report with --junit, which most CI tools display test by test.

  1. Pin the version of the tools

    In the project, install the command as a development dependency, at an exact version:

    Terminal
    npm install --save-dev --save-exact @hos-ai/cli

    The tools are alphas: messages and checks may change from one version to the next. With an exact version, the CI runs what you tested, and you move to a new version on purpose. Run the command as npx hos in the project: npx uses the project's copy.

  2. Choose the checks

    Keep the checks that match what your system does:

    Your systemCheck
    receives HOS factsnpx hos conformance run --all --level normative --impl "node consumer.mjs" --junit hos-conformance.xml
    publishes HOS factsnpx hos conformance producer --manifest manifest.json --stream recording.jsonl --redelivery redelivery.jsonl
    publishes files you keepnpx hos validate manifest.json
    publishes a signed manifestnpx hos manifest verify https://your-domain.example/.well-known/hos/manifest.json --at <a date ahead>

    For the producer check, have a step of the job produce recording.jsonl and redelivery.jsonl, as the test of Build an adapter does.

  3. Add a GitHub Actions workflow

    Save this as .github/workflows/hos.yml, and adapt the commands and paths to your project:

    YAML
    name: HOS checks
    
    on:
      push:
      pull_request:
      # Every morning, to catch a manifest signature about to expire.
      schedule:
        - cron: "0 6 * * *"
    
    jobs:
      hos:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v7
          - uses: actions/setup-node@v7
            with:
              node-version: 22
              cache: npm
          # Installs the exact version of @hos-ai/cli that package.json pins.
          - run: npm ci
    
          - name: Test the consumer against the conformance scenarios
            run: npx hos conformance run --all --level normative --impl "node consumer.mjs" --junit hos-conformance.xml
    
          - name: Record what the adapter publishes, then again after a restart
            run: |
              node adapter.mjs recording.jsonl
              node adapter.mjs redelivery.jsonl
    
          - name: Check the producer
            run: npx hos conformance producer --manifest manifest.json --stream recording.jsonl --redelivery redelivery.jsonl
    
          - name: Verify the published manifest as of 30 days from now
            run: npx hos manifest verify https://your-domain.example/.well-known/hos/manifest.json --at "$(date -u -d '+30 days' +%Y-%m-%dT%H:%M:%SZ)"
    
          - name: Keep the conformance report
            if: always()
            uses: actions/upload-artifact@v7
            with:
              name: hos-conformance
              path: hos-conformance.xml

    Each step fails on exit code 1 or 2, and the job fails with it. The last step keeps the JUnit report even when a scenario fails, to read in the run's artifacts.

  4. Read the JUnit report

    --junit writes one test suite per scenario and one test case per delivery, named after the fact. A failure carries the difference, as the text report prints it:

    XML
    <?xml version="1.0" encoding="UTF-8"?>
    <testsuites name="hos conformance" tests="3" failures="0">
      <testsuite name="arrival-readiness" tests="13" failures="0" errors="0">
        <testcase classname="arrival-readiness" name="delivery 1 (pms-000312 from urn:hos:pms:demo)"/>
        <testcase classname="arrival-readiness" name="delivery 2 (pms-000421 from urn:hos:pms:demo)"/>

    The report does not replace the text output of the step, which says in one line per scenario what passed.

GitLab CI

The same checks in .gitlab-ci.yml, with the JUnit report shown in merge requests:

YAML
hos:
  image: node:22
  script:
    - npm ci
    - npx hos conformance run --all --level normative --impl "node consumer.mjs" --junit hos-conformance.xml
    - node adapter.mjs recording.jsonl
    - node adapter.mjs redelivery.jsonl
    - npx hos conformance producer --manifest manifest.json --stream recording.jsonl --redelivery redelivery.jsonl
  artifacts:
    when: always
    reports:
      junit: hos-conformance.xml

For the daily check of the manifest, add a scheduled pipeline in the project's CI/CD settings.

Read the JSON output

--json gives the same result as the text, as one JSON document. The top-level valid of validate and conformance producer, and passed of conformance run, say whether everything passed, as the exit code does. With jq, for example:

Terminal
npx hos conformance run --all --level normative --impl "node consumer.mjs" --json | jq '.scenarios[] | {scenario, passed, scores}'

The guides show each command's JSON: validate, replay, conformance producer.

Check it worked

A change that breaks a check fails the workflow, and a scheduled run fails while the manifest's signature has less than 30 days left.

If it fails

  • The step fails with exit code 2: the command is wrong or a file is missing. Read the first line of its output, which starts with hos and says what is missing.
  • npx hos downloads a package instead of using the project's: @hos-ai/cli is not in devDependencies, or npm ci did not run first.
  • The scenarios pass on your computer but not in the CI: the command after --impl starts differently on Linux. Run it on its own in the CI to see.
  • date: invalid option: date -d is GNU date, as on the Ubuntu runners of GitHub. On macOS runners, use date -u -v+30d +%Y-%m-%dT%H:%M:%SZ.

Next steps