Compare commits

...

9 Commits

Author SHA1 Message Date
2a53979069 Update the bundled pipeline to Narratio v2.1.2 2026-09-21 13:50:39 +00:00
19b1dcabcf Squashed 'roles/pipeline/' changes from 51566af..f48008a
f48008a Upgrade the pipeline to Narratio v2.1.2

git-subtree-dir: roles/pipeline
git-subtree-split: f48008aa38e1c50adde18aa455d12a8ad77023c2
2026-09-21 13:50:39 +00:00
4691344676 Import D&D storage and publishing 2026-09-21 03:37:02 +00:00
77f67adbc0 Squashed 'roles/pipeline/' changes from c13f726..51566af
51566af Enable D&D storage and publishing

git-subtree-dir: roles/pipeline
git-subtree-split: 51566afcf69083cdbb5b5718f2544c86b079001c
2026-09-21 03:37:02 +00:00
cf3de016ee Prepare collection storage credentials 2026-09-21 03:36:30 +00:00
d292297b6a Squashed 'roles/pipeline/' changes from 78afffe..c13f726
c13f726 Add optional pipeline operator enrollment

git-subtree-dir: roles/pipeline
git-subtree-split: c13f726a0a846180a1aa95d110b8bbc801edaae5
2026-09-18 12:57:00 +00:00
c0b0ebd13e Import pipeline operator enrollment 2026-09-18 12:57:00 +00:00
f62445ad1e Squashed 'roles/pipeline/' changes from 7c2bad8..78afffe
78afffe Clarify the pipeline snapshot workflow

git-subtree-dir: roles/pipeline
git-subtree-split: 78afffe8e5fdedbd274e256dfa0e0721cfbf9a5c
2026-09-17 23:51:51 +00:00
5e695f38d0 Import pipeline documentation correction 2026-09-17 23:51:51 +00:00
7 changed files with 249 additions and 24 deletions

View File

@@ -49,8 +49,9 @@ The collection source exposes a reviewed snapshot of this role as
Collection consumers should follow the unified bootstrap instructions in the Collection consumers should follow the unified bootstrap instructions in the
[`rakestraw.dnd` collection repository](https://gitea.maximumdirect.net/eric/ansible-collection-dnd). [`rakestraw.dnd` collection repository](https://gitea.maximumdirect.net/eric/ansible-collection-dnd).
This standalone repository remains authoritative for role changes; collection This standalone repository remains authoritative for role changes; collection
maintainers import a reviewed release as a snapshot. Collection releases are maintainers import a reviewed, pushed commit or immutable tag as a snapshot.
published independently and are listed in the collection repository. Collection releases are published independently and are listed in the
collection repository.
## Variables ## Variables
@@ -60,7 +61,7 @@ The compatible application versions are selected through these variables:
| Variable | Default | | Variable | Default |
| --- | --- | | --- | --- |
| `dnd_pipeline_audita_version` | `v0.9.1` | | `dnd_pipeline_audita_version` | `v0.9.1` |
| `dnd_pipeline_narratio_version` | `v2.1.0` | | `dnd_pipeline_narratio_version` | `v2.1.2` |
| `dnd_pipeline_notarius_version` | `v0.7.0` | | `dnd_pipeline_notarius_version` | `v0.7.0` |
| `dnd_pipeline_seriatim_version` | `v1.5.0` | | `dnd_pipeline_seriatim_version` | `v1.5.0` |
| `dnd_pipeline_scriptorium_version` | `v0.13.0` | | `dnd_pipeline_scriptorium_version` | `v0.13.0` |
@@ -89,6 +90,7 @@ group before the remaining configuration-bearing dependencies run.
| --- | --- | | --- | --- |
| `dnd_pipeline_runtime_user` | `narratio` | | `dnd_pipeline_runtime_user` | `narratio` |
| `dnd_pipeline_runtime_group` | `narratio` | | `dnd_pipeline_runtime_group` | `narratio` |
| `dnd_pipeline_operator_users` | `[]` |
| `dnd_pipeline_config_directory_mode` | `0755` | | `dnd_pipeline_config_directory_mode` | `0755` |
| `dnd_pipeline_config_file_mode` | `0644` | | `dnd_pipeline_config_file_mode` | `0644` |
@@ -150,6 +152,40 @@ it is the shared cross-application boundary. Other Narratio-local controls,
including reports, timeouts, debug rendering, presentation, and bounds prompt including reports, timeouts, debug rendering, presentation, and bounds prompt
profile selection, remain Narratio defaults. profile selection, remain Narratio defaults.
### Storage and publication policy
The suite selects Narratio's S3 backend and the established Backblaze-compatible
archive. These are ordinary inventory variables, so deployments may replace
the selected policy through the role's public interface.
| Variable | Default policy |
| --- | --- |
| `dnd_pipeline_narratio_workspace_cleanup_after_publish` | `true` |
| `dnd_pipeline_narratio_storage_backend` | `s3` |
| `dnd_pipeline_narratio_storage_s3_bucket` | `rakestraw-assets` |
| `dnd_pipeline_narratio_storage_s3_root_prefix` | `dnd` |
| `dnd_pipeline_narratio_storage_s3_region` | `us-east-1` |
| `dnd_pipeline_narratio_storage_s3_endpoint` | `https://s3.us-east-005.backblazeb2.com` |
| `dnd_pipeline_narratio_storage_s3_force_path_style` | `true` |
| `dnd_pipeline_narratio_storage_s3_access_key_id` | `OBJECT_STORAGE_KEY_ID` |
| `dnd_pipeline_narratio_storage_s3_secret_access_key` | `OBJECT_STORAGE_KEY` |
| `dnd_pipeline_narratio_cache_s3_audio` | `true` |
| `dnd_pipeline_narratio_publish_enabled` | `true` |
| `dnd_pipeline_narratio_publish_upload_run` | `true` |
`dnd_pipeline_narratio_publish_outputs` is a complete native list, not a list
merged with the suite default. It publishes final and trimmed JSON, final and
trimmed Markdown, session recap, hostile rumors, and optional deranged rumors.
Every rule omits `dest`: Narratio derives transcript destinations from its
built-in sources and artifact destinations from the configured artifact output
paths.
S3 session audio uses the maximum available native cache beneath
`/var/cache/narratio`. After successful run publication, Narratio cleans the
published workspace target while preserving that cache. The suite deliberately
does not set `narratio_spool_delete_audio_after_publish`; spool-audio retention
continues to use Narratio's application default.
### Artifacts and profiles ### Artifacts and profiles
The role owns these complete native mapping variables. Replacing one mapping The role owns these complete native mapping variables. Replacing one mapping
@@ -225,6 +261,9 @@ that input. The accepted sources are
`narratio.extraction.item_registry`, `npc_registry`, `location_registry`, `narratio.extraction.item_registry`, `npc_registry`, `location_registry`,
`scene_descriptions`, `item_occurrences`, `spells`, `combat_turns`, `scene_descriptions`, `item_occurrences`, `spells`, `combat_turns`,
`npc_occurrences`, `location_occurrences`, and `enemy_events`. `npc_occurrences`, `location_occurrences`, and `enemy_events`.
They remain available as `narratio.extraction.<output_key>` inputs for future
analyze artifacts whether or not a source has a stable publication rule;
accepted extraction and published output selection are independent interfaces.
Narratio forwards the typed `OPENROUTER_API_KEY` reference to the selected Narratio forwards the typed `OPENROUTER_API_KEY` reference to the selected
Notarius profile and ordinary extraction requests checkpoint reuse with Notarius profile and ordinary extraction requests checkpoint reuse with
@@ -258,8 +297,15 @@ inspection shows enabled sources, inferred dependencies, and generated family
members; the diff shows the overlay's profile selections without modifying members; the diff shows the overlay's profile selections without modifying
managed files. managed files.
Storage and publishing, operator selection and group-membership management, With valid object-storage credentials, the selected policy enables Narratio's
scheduling, and end-to-end external execution remain deferred. native [S3 session-audio](https://gitea.maximumdirect.net/eric/narratio/src/tag/v2.1.1/docs/config.md#session),
[publication](https://gitea.maximumdirect.net/eric/narratio/src/tag/v2.1.1/docs/operations.md#publish-workflow),
[restore](https://gitea.maximumdirect.net/eric/narratio/src/tag/v2.1.1/docs/operations.md#restore-workflow),
[publication locks](https://gitea.maximumdirect.net/eric/narratio/src/tag/v2.1.1/docs/operations.md#publish-locks),
[session status](https://gitea.maximumdirect.net/eric/narratio/src/tag/v2.1.1/docs/operations.md#standard-session-workflow),
and [cleanup](https://gitea.maximumdirect.net/eric/narratio/src/tag/v2.1.1/docs/operations.md#cleanup)
workflows. These remain application commands and lifecycle rules; scheduling
and real end-to-end execution remain deployment concerns.
### Shared execution filesystem ### Shared execution filesystem
@@ -268,27 +314,30 @@ scheduling, and end-to-end external execution remain deferred.
`narratio:narratio` mode `2775` **setgid** directories. Their access and `narratio:narratio` mode `2775` **setgid** directories. Their access and
default ACLs retain owner and group write access plus world read/traverse access default ACLs retain owner and group write access plus world read/traverse access
for newly created content. The pipeline may run as `narratio` or as a human for newly created content. The pipeline may run as `narratio` or as a human
account already in the selected runtime group; the production role neither account in the selected runtime group. Consumers can enroll selected existing
selects people nor manages their group membership. For example, a consumer human accounts through the role interface:
play can manage its selected operator separately:
```yaml ```yaml
- name: Add the selected operator to the pipeline group dnd_pipeline_operator_users:
become: true - eric
ansible.builtin.user: - alice
name: "{{ pipeline_operator }}"
groups:
- "{{ dnd_pipeline_runtime_group }}"
append: true
``` ```
Every selected account must already exist; the role does not create human
accounts or manage their identity and login policy. Enrollment adds the
selected runtime group without replacing other supplementary groups. Removing
or omitting a name later does not revoke membership. A newly enrolled operator
must begin a new login session before the operating system exposes the added
supplementary group to that session.
Configuration, transcripts, caches, generated artifacts, campaign data, Configuration, transcripts, caches, generated artifacts, campaign data,
prompts, and logs are non-secret D&D content. Credentials use the restricted prompts, and logs are non-secret D&D content. Credentials use the restricted
`/usr/local/etc/narratio/secrets` subtree, owned by the selected runtime user `/usr/local/etc/narratio/secrets` subtree, owned by the selected runtime user
and group with mode `0750`; managed files use mode `0640`. Runtime-group and group with mode `0750`; managed files use mode `0640`. Runtime-group
membership authorizes use of these shared credentials, while the subtree grants membership, including enrollment through `dnd_pipeline_operator_users`,
no world access. Ordinary configuration remains world-readable and contains authorizes use of these shared credentials, while the subtree grants no world
only reference names. access. Ordinary configuration remains world-readable and contains only
reference names.
### Managed credentials ### Managed credentials
@@ -306,8 +355,17 @@ consumer workflow, not role functionality:
dnd_pipeline_secrets: dnd_pipeline_secrets:
AUDITA_LLM_API_KEY: "{{ vault_dnd_audita_llm_api_key }}" AUDITA_LLM_API_KEY: "{{ vault_dnd_audita_llm_api_key }}"
OPENROUTER_API_KEY: "{{ vault_dnd_openrouter_api_key }}" OPENROUTER_API_KEY: "{{ vault_dnd_openrouter_api_key }}"
OBJECT_STORAGE_KEY_ID: "{{ vault_dnd_object_storage_key_id }}"
OBJECT_STORAGE_KEY: "{{ vault_dnd_object_storage_key }}"
``` ```
Only the reference names enter ordinary Narratio configuration; credential
values remain in encrypted inventory and the restricted managed secrets
directory. A deployment using Narratio's ambient AWS SDK provider chain can
set both `dnd_pipeline_narratio_storage_s3_access_key_id` and
`dnd_pipeline_narratio_storage_s3_secret_access_key` to `null`. The pair must
be omitted together.
Scriptorium profiles continue to own their `api_key_env` selection. To supply Scriptorium profiles continue to own their `api_key_env` selection. To supply
that credential through the suite, add a `dnd_pipeline_secrets` entry whose that credential through the suite, add a `dnd_pipeline_secrets` entry whose
name matches the selected profile's `api_key_env`. Narratio's secrets bootstrap name matches the selected profile's `api_key_env`. Narratio's secrets bootstrap

View File

@@ -1,6 +1,6 @@
--- ---
dnd_pipeline_audita_version: v0.9.1 dnd_pipeline_audita_version: v0.9.1
dnd_pipeline_narratio_version: v2.1.0 dnd_pipeline_narratio_version: v2.1.2
dnd_pipeline_notarius_version: v0.7.0 dnd_pipeline_notarius_version: v0.7.0
dnd_pipeline_seriatim_version: v1.5.0 dnd_pipeline_seriatim_version: v1.5.0
dnd_pipeline_scriptorium_version: v0.13.0 dnd_pipeline_scriptorium_version: v0.13.0
@@ -9,6 +9,7 @@ dnd_pipeline_go_snap_channel: 1.26/stable
dnd_pipeline_go_binary: /snap/bin/go dnd_pipeline_go_binary: /snap/bin/go
dnd_pipeline_runtime_user: narratio dnd_pipeline_runtime_user: narratio
dnd_pipeline_runtime_group: narratio dnd_pipeline_runtime_group: narratio
dnd_pipeline_operator_users: []
dnd_pipeline_secrets: {} dnd_pipeline_secrets: {}
dnd_pipeline_config_directory_mode: "0755" dnd_pipeline_config_directory_mode: "0755"
dnd_pipeline_config_file_mode: "0644" dnd_pipeline_config_file_mode: "0644"
@@ -206,6 +207,33 @@ dnd_pipeline_notarius_pipelines:
dnd_pipeline_notarius_cache_root: /var/cache/notarius dnd_pipeline_notarius_cache_root: /var/cache/notarius
dnd_pipeline_notarius_cache_chunk_plans_mode: auto dnd_pipeline_notarius_cache_chunk_plans_mode: auto
dnd_pipeline_notarius_cache_checkpoints_enabled: true dnd_pipeline_notarius_cache_checkpoints_enabled: true
dnd_pipeline_narratio_workspace_cleanup_after_publish: true
dnd_pipeline_narratio_storage_backend: s3
dnd_pipeline_narratio_storage_s3_bucket: rakestraw-assets
dnd_pipeline_narratio_storage_s3_root_prefix: dnd
dnd_pipeline_narratio_storage_s3_region: us-east-1
dnd_pipeline_narratio_storage_s3_endpoint: https://s3.us-east-005.backblazeb2.com
dnd_pipeline_narratio_storage_s3_force_path_style: true
dnd_pipeline_narratio_storage_s3_access_key_id: OBJECT_STORAGE_KEY_ID
dnd_pipeline_narratio_storage_s3_secret_access_key: OBJECT_STORAGE_KEY
dnd_pipeline_narratio_cache_s3_audio: true
dnd_pipeline_narratio_publish_enabled: true
dnd_pipeline_narratio_publish_upload_run: true
dnd_pipeline_narratio_publish_outputs:
- source: narratio.transcript.final
required: true
- source: narratio.transcript.final_trimmed
required: true
- source: narratio.transcript.final_markdown
required: true
- source: narratio.transcript.final_trimmed_markdown
required: true
- source: narratio.artifact.session_recap
required: true
- source: narratio.artifact.hostile_rumors
required: true
- source: narratio.artifact.deranged_rumors
required: false
dnd_pipeline_narratio_seriatim_output_schema: seriatim-intermediate dnd_pipeline_narratio_seriatim_output_schema: seriatim-intermediate
dnd_pipeline_narratio_normalize_output_path: transcripts/final.json dnd_pipeline_narratio_normalize_output_path: transcripts/final.json
dnd_pipeline_narratio_normalize_output_schema: seriatim-intermediate dnd_pipeline_narratio_normalize_output_schema: seriatim-intermediate

View File

@@ -43,6 +43,11 @@ argument_specs:
type: str type: str
required: true required: true
description: Shared group for suite-managed configuration. description: Shared group for suite-managed configuration.
dnd_pipeline_operator_users:
type: list
elements: str
required: true
description: Existing human accounts enrolled in the shared runtime group.
dnd_pipeline_secrets: dnd_pipeline_secrets:
type: dict type: dict
required: true required: true
@@ -216,6 +221,58 @@ argument_specs:
type: bool type: bool
required: true required: true
description: Whether Notarius records checkpoints. description: Whether Notarius records checkpoints.
dnd_pipeline_narratio_workspace_cleanup_after_publish:
type: bool
required: true
description: Whether Narratio cleans successfully published workspace state.
dnd_pipeline_narratio_storage_backend:
type: str
required: true
description: Narratio object-storage backend.
dnd_pipeline_narratio_storage_s3_bucket:
type: str
required: false
description: S3 bucket used by Narratio.
dnd_pipeline_narratio_storage_s3_root_prefix:
type: str
required: false
description: Root prefix for Narratio objects in the S3 bucket.
dnd_pipeline_narratio_storage_s3_region:
type: str
required: false
description: S3 region used by Narratio.
dnd_pipeline_narratio_storage_s3_endpoint:
type: str
required: false
description: S3-compatible endpoint used by Narratio.
dnd_pipeline_narratio_storage_s3_force_path_style:
type: bool
required: false
description: Whether Narratio uses path-style S3 requests.
dnd_pipeline_narratio_storage_s3_access_key_id:
type: str
required: false
description: Nullable access-key environment-variable reference.
dnd_pipeline_narratio_storage_s3_secret_access_key:
type: str
required: false
description: Nullable secret-key environment-variable reference.
dnd_pipeline_narratio_cache_s3_audio:
type: bool
required: true
description: Whether Narratio caches downloaded S3 audio.
dnd_pipeline_narratio_publish_enabled:
type: bool
required: true
description: Whether Narratio publication is enabled.
dnd_pipeline_narratio_publish_upload_run:
type: bool
required: true
description: Whether Narratio uploads immutable run content.
dnd_pipeline_narratio_publish_outputs:
type: list
required: true
description: Complete native list of Narratio output publication rules.
dnd_pipeline_narratio_seriatim_output_schema: dnd_pipeline_narratio_seriatim_output_schema:
type: str type: str
required: true required: true

View File

@@ -39,6 +39,19 @@ dependencies:
- path: artifacts/deranged-rumors.yml - path: artifacts/deranged-rumors.yml
- path: artifacts/scene-map.yml - path: artifacts/scene-map.yml
- path: artifact-families/character-meta-analysis.yml - path: artifact-families/character-meta-analysis.yml
narratio_workspace_cleanup_after_publish: "{{ dnd_pipeline_narratio_workspace_cleanup_after_publish }}"
narratio_storage_backend: "{{ dnd_pipeline_narratio_storage_backend }}"
narratio_storage_s3_bucket: "{{ dnd_pipeline_narratio_storage_s3_bucket }}"
narratio_storage_s3_root_prefix: "{{ dnd_pipeline_narratio_storage_s3_root_prefix }}"
narratio_storage_s3_region: "{{ dnd_pipeline_narratio_storage_s3_region }}"
narratio_storage_s3_endpoint: "{{ dnd_pipeline_narratio_storage_s3_endpoint }}"
narratio_storage_s3_force_path_style: "{{ dnd_pipeline_narratio_storage_s3_force_path_style }}"
narratio_storage_s3_access_key_id: "{{ dnd_pipeline_narratio_storage_s3_access_key_id }}"
narratio_storage_s3_secret_access_key: "{{ dnd_pipeline_narratio_storage_s3_secret_access_key }}"
narratio_cache_s3_audio: "{{ dnd_pipeline_narratio_cache_s3_audio }}"
narratio_publish_enabled: "{{ dnd_pipeline_narratio_publish_enabled }}"
narratio_publish_upload_run: "{{ dnd_pipeline_narratio_publish_upload_run }}"
narratio_publish_outputs: "{{ dnd_pipeline_narratio_publish_outputs }}"
narratio_seriatim_binary: /usr/local/bin/seriatim narratio_seriatim_binary: /usr/local/bin/seriatim
narratio_audita_binary: /usr/local/bin/audita narratio_audita_binary: /usr/local/bin/audita
narratio_audita_config_path: /usr/local/etc/audita/config.yml narratio_audita_config_path: /usr/local/etc/audita/config.yml

View File

@@ -1,4 +1,19 @@
--- ---
- name: Validate selected pipeline operator accounts
ansible.builtin.getent:
database: passwd
key: "{{ item }}"
loop: "{{ dnd_pipeline_operator_users }}"
- name: Enroll selected pipeline operators
become: true
ansible.builtin.user:
name: "{{ item }}"
groups: "{{ dnd_pipeline_runtime_group }}"
append: true
state: present
loop: "{{ dnd_pipeline_operator_users }}"
- name: Install ACL support - name: Install ACL support
become: true become: true
ansible.builtin.apt: ansible.builtin.apt:

View File

@@ -24,6 +24,8 @@ service_fixture_file="$shared_fixture_root/service.txt"
operator_fixture_file="$shared_fixture_root/operator.txt" operator_fixture_file="$shared_fixture_root/operator.txt"
synthetic_audita_api_key='audita-pipeline-synthetic-value' synthetic_audita_api_key='audita-pipeline-synthetic-value'
synthetic_notarius_api_key='notarius-pipeline-synthetic-value' synthetic_notarius_api_key='notarius-pipeline-synthetic-value'
synthetic_object_storage_key_id='object-storage-key-id-pipeline-synthetic-value'
synthetic_object_storage_key='object-storage-key-pipeline-synthetic-value'
baseline_args=( baseline_args=(
-e 'dnd_pipeline_whisperx_transcribe_url=http://127.0.0.1:8000/transcribe' -e 'dnd_pipeline_whisperx_transcribe_url=http://127.0.0.1:8000/transcribe'
-e "dnd_pipeline_campaigns_repository_url=file://$campaigns_repository" -e "dnd_pipeline_campaigns_repository_url=file://$campaigns_repository"
@@ -31,15 +33,25 @@ baseline_args=(
-e "dnd_pipeline_prompt_library_repository_url=file://$prompt_library_repository" -e "dnd_pipeline_prompt_library_repository_url=file://$prompt_library_repository"
-e "dnd_pipeline_prompt_library_revision=$prompt_library_revision" -e "dnd_pipeline_prompt_library_revision=$prompt_library_revision"
-e "dnd_pipeline_prompt_library_root=$prompt_library_root" -e "dnd_pipeline_prompt_library_root=$prompt_library_root"
-e "{\"dnd_pipeline_secrets\":{\"AUDITA_LLM_API_KEY\":\"$synthetic_audita_api_key\",\"OPENROUTER_API_KEY\":\"$synthetic_notarius_api_key\"}}" -e "{\"dnd_pipeline_operator_users\":[\"$operator_user\"]}"
-e "{\"dnd_pipeline_secrets\":{\"AUDITA_LLM_API_KEY\":\"$synthetic_audita_api_key\",\"OPENROUTER_API_KEY\":\"$synthetic_notarius_api_key\",\"OBJECT_STORAGE_KEY_ID\":\"$synthetic_object_storage_key_id\",\"OBJECT_STORAGE_KEY\":\"$synthetic_object_storage_key\"}}"
-e 'dnd_pipeline_narratio_storage_backend=s3'
-e 'dnd_pipeline_narratio_storage_s3_bucket=dnd-pipeline-fixture'
-e 'dnd_pipeline_narratio_storage_s3_root_prefix=fixture/dnd'
-e 'dnd_pipeline_narratio_storage_s3_region=fixture-1'
-e 'dnd_pipeline_narratio_storage_s3_endpoint=https://storage.fixture.invalid'
-e 'dnd_pipeline_narratio_storage_s3_access_key_id=OBJECT_STORAGE_KEY_ID'
-e 'dnd_pipeline_narratio_storage_s3_secret_access_key=OBJECT_STORAGE_KEY'
-e '{"dnd_pipeline_narratio_workspace_cleanup_after_publish":false,"dnd_pipeline_narratio_storage_s3_force_path_style":false,"dnd_pipeline_narratio_cache_s3_audio":false,"dnd_pipeline_narratio_publish_enabled":true,"dnd_pipeline_narratio_publish_upload_run":true}'
-e '{"dnd_pipeline_narratio_publish_outputs":[{"source":"narratio.transcript.final","required":true},{"source":"narratio.artifact.session_recap","required":true}]}'
) )
cleanup() { cleanup() {
exit_status=$? exit_status=$?
trap - EXIT trap - EXIT
/usr/bin/sudo /bin/rm -rf -- "$shared_fixture_root" || true /usr/bin/sudo /bin/rm -rf -- "$shared_fixture_root" || true
/usr/bin/sudo /usr/sbin/userdel --remove "$operator_user" 2>/dev/null || true
"$ansible_playbook" -i "$inventory" "${baseline_args[@]}" "$converge" >/dev/null 2>&1 || true "$ansible_playbook" -i "$inventory" "${baseline_args[@]}" "$converge" >/dev/null 2>&1 || true
/usr/bin/sudo /usr/sbin/userdel --remove "$operator_user" 2>/dev/null || true
rm -rf -- "$test_tmp" rm -rf -- "$test_tmp"
exit "$exit_status" exit "$exit_status"
} }
@@ -53,6 +65,7 @@ run_converge() {
output_file=$1 output_file=$1
shift shift
env -u AUDITA_LLM_API_KEY -u OPENROUTER_API_KEY \ env -u AUDITA_LLM_API_KEY -u OPENROUTER_API_KEY \
-u OBJECT_STORAGE_KEY_ID -u OBJECT_STORAGE_KEY \
"$ansible_playbook" -i "$inventory" "$@" "$converge" | tee "$output_file" "$ansible_playbook" -i "$inventory" "$@" "$converge" | tee "$output_file"
} }
@@ -70,6 +83,7 @@ printf '%s\n' \
-p "$test_tmp/roles" -p "$test_tmp/roles"
"$ansible_playbook" -i "$inventory" --syntax-check "$converge" "$ansible_playbook" -i "$inventory" --syntax-check "$converge"
"$workspace_venv/bin/ansible-lint" --offline --profile production "$converge" "$workspace_venv/bin/ansible-lint" --offline --profile production "$converge"
/usr/bin/sudo /usr/sbin/useradd --create-home --shell /usr/sbin/nologin "$operator_user"
baseline_log="$test_tmp/baseline.log" baseline_log="$test_tmp/baseline.log"
run_converge "$baseline_log" "${baseline_args[@]}" run_converge "$baseline_log" "${baseline_args[@]}"
@@ -102,8 +116,49 @@ grep -Fq 'resume: true' "$narratio_effective_config"
! grep -Fq 'chunk_cache:' "$narratio_effective_config" ! grep -Fq 'chunk_cache:' "$narratio_effective_config"
grep -Fq 'party: narratio.input.party' "$narratio_effective_config" grep -Fq 'party: narratio.input.party' "$narratio_effective_config"
grep -Fq 'lane_id: item-registry' "$narratio_effective_config" grep -Fq 'lane_id: item-registry' "$narratio_effective_config"
"$workspace_venv/bin/python" - "$narratio_effective_config" <<'PY'
import sys
import yaml
with open(sys.argv[1], encoding="utf-8") as config_file:
config = yaml.safe_load(config_file)
assert config["workspace"]["cleanup_after_publish"] is False
assert config["storage"] == {
"backend": "s3",
"s3": {
"bucket": "dnd-pipeline-fixture",
"root_prefix": "fixture/dnd",
"region": "fixture-1",
"endpoint": "https://storage.fixture.invalid",
"force_path_style": False,
"access_key_id": "OBJECT_STORAGE_KEY_ID",
"secret_access_key": "OBJECT_STORAGE_KEY",
},
}
assert config["cache"]["s3_audio"] is False
assert config["publish"] == {
"enabled": True,
"upload_run": True,
"outputs": [
{
"source": "narratio.transcript.final",
"dest": "transcripts/final.json",
"required": True,
},
{
"source": "narratio.artifact.session_recap",
"dest": "artifacts/session_recap.md",
"required": True,
},
],
}
PY
! grep -Fq "$synthetic_audita_api_key" "$baseline_log" "$narratio_effective_config" "$notarius_effective_config" ! grep -Fq "$synthetic_audita_api_key" "$baseline_log" "$narratio_effective_config" "$notarius_effective_config"
! grep -Fq "$synthetic_notarius_api_key" "$baseline_log" "$narratio_effective_config" "$notarius_effective_config" ! grep -Fq "$synthetic_notarius_api_key" "$baseline_log" "$narratio_effective_config" "$notarius_effective_config"
! grep -Fq "$synthetic_object_storage_key_id" "$baseline_log" "$narratio_effective_config" "$notarius_effective_config"
! grep -Fq "$synthetic_object_storage_key" "$baseline_log" "$narratio_effective_config" "$notarius_effective_config"
/usr/bin/sudo -u narratio /usr/local/bin/narratio config artifacts \ /usr/bin/sudo -u narratio /usr/local/bin/narratio config artifacts \
--config /usr/local/etc/narratio/pipeline.yml --campaign centaurs | \ --config /usr/local/etc/narratio/pipeline.yml --campaign centaurs | \
awk -F '\t' '$1 == "session_recap" && $4 == "true" { found = 1 } END { exit !found }' awk -F '\t' '$1 == "session_recap" && $4 == "true" { found = 1 } END { exit !found }'
@@ -116,8 +171,6 @@ grep -Fq 'lane_id: item-registry' "$narratio_effective_config"
/usr/bin/sudo -u narratio /usr/local/bin/narratio config diff default testing \ /usr/bin/sudo -u narratio /usr/local/bin/narratio config diff default testing \
--config /usr/local/etc/narratio/pipeline.yml --campaign centaurs | \ --config /usr/local/etc/narratio/pipeline.yml --campaign centaurs | \
awk -F '\t' '$1 != "changed" || $2 !~ /\.profile_id$/ { invalid = 1 } END { exit invalid || NR == 0 }' awk -F '\t' '$1 != "changed" || $2 !~ /\.profile_id$/ { invalid = 1 } END { exit invalid || NR == 0 }'
/usr/bin/sudo /usr/sbin/useradd --create-home --groups narratio \
--shell /usr/sbin/nologin "$operator_user"
/usr/bin/sudo -u "$operator_user" /usr/local/bin/narratio config validate \ /usr/bin/sudo -u "$operator_user" /usr/local/bin/narratio config validate \
--config /usr/local/etc/narratio/pipeline.yml --campaign centaurs --config /usr/local/etc/narratio/pipeline.yml --campaign centaurs
/usr/bin/sudo -u "$operator_user" /usr/local/bin/notarius config validate \ /usr/bin/sudo -u "$operator_user" /usr/local/bin/notarius config validate \

View File

@@ -22,7 +22,7 @@ baseline_args=(
-e "dnd_pipeline_campaigns_revision=$campaigns_revision" -e "dnd_pipeline_campaigns_revision=$campaigns_revision"
-e "dnd_pipeline_prompt_library_repository_url=file://$prompt_library_repository" -e "dnd_pipeline_prompt_library_repository_url=file://$prompt_library_repository"
-e "dnd_pipeline_prompt_library_revision=$prompt_library_revision" -e "dnd_pipeline_prompt_library_revision=$prompt_library_revision"
-e '{"dnd_pipeline_secrets":{"AUDITA_LLM_API_KEY":"audita-pipeline-synthetic-value","OPENROUTER_API_KEY":"notarius-pipeline-synthetic-value"}}' -e '{"dnd_pipeline_secrets":{"AUDITA_LLM_API_KEY":"audita-pipeline-synthetic-value","OPENROUTER_API_KEY":"notarius-pipeline-synthetic-value","OBJECT_STORAGE_KEY_ID":"object-storage-key-id-pipeline-synthetic-value","OBJECT_STORAGE_KEY":"object-storage-key-pipeline-synthetic-value"}}'
) )
cleanup() { cleanup() {
@@ -36,6 +36,7 @@ trap cleanup EXIT
run_converge() { run_converge() {
output_file=$1 output_file=$1
env -u AUDITA_LLM_API_KEY -u OPENROUTER_API_KEY \ env -u AUDITA_LLM_API_KEY -u OPENROUTER_API_KEY \
-u OBJECT_STORAGE_KEY_ID -u OBJECT_STORAGE_KEY \
"$ansible_playbook" -i "$inventory" "${baseline_args[@]}" "$converge" | \ "$ansible_playbook" -i "$inventory" "${baseline_args[@]}" "$converge" | \
tee "$output_file" tee "$output_file"
} }