diff --git a/README.md b/README.md index 505e537..5da2b45 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ root-owned application state. ## Variables ```yaml -notarius_version: v0.6.0 +notarius_version: v0.7.0 notarius_repository_url: https://gitea.maximumdirect.net/eric/notarius.git notarius_source_dir: /usr/local/src/notarius notarius_binary_path: /usr/local/bin/notarius @@ -20,11 +20,12 @@ notarius_config_owner: root notarius_config_group: root notarius_config_directory_mode: "0755" notarius_config_file_mode: "0644" -notarius_config_version: 4 +notarius_config_version: 5 notarius_promptkit_profile_dir: null notarius_promptkit_profile_file: null notarius_promptkit_local_backend_endpoint: null notarius_promptkit_local_backend_concurrency_limit: null +notarius_configkit_imports: null notarius_pipelines: null notarius_concurrency_total_llm: null notarius_concurrency_stage_workers_extract: null @@ -61,6 +62,11 @@ the ordinary way: notarius_pipelines: "{{ notarius_pipeline_group_one | combine(notarius_pipeline_group_two) }}" ``` +`notarius_configkit_imports` is the complete native ConfigKit import list. It +is caller-owned composition input: the role renders it into the root document +but does not create or merge imported fragments. Relative import paths resolve +from the managed root configuration directory. + PromptKit profile values identify profile sources or a local backend endpoint; they never contain credentials. Supply any credential environment variables outside this role. @@ -81,9 +87,10 @@ native configuration validation before requiring clean repeated convergence. It verifies an explicitly selected Notarius release, combines missing-binary recovery with a caller-supplied Go executable while dependency management is disabled, and covers one representative configuration with null omission, -intentional falsey values, caller-side pipeline composition, and native -validation. It mutates only the managed source, binary, configuration, and a -private temporary directory, then restores the default deployment during +intentional falsey values, caller-side pipeline composition through a +test-owned ConfigKit import, and native validation and inspection. It mutates +only the managed source, binary, configuration, a test-owned imported fragment, +and a private temporary directory, then restores the default deployment during cleanup. ```sh diff --git a/defaults/main.yml b/defaults/main.yml index ec5d406..081867d 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,5 +1,5 @@ --- -notarius_version: v0.6.0 +notarius_version: v0.7.0 notarius_repository_url: https://gitea.maximumdirect.net/eric/notarius.git notarius_source_dir: /usr/local/src/notarius notarius_binary_path: /usr/local/bin/notarius @@ -11,11 +11,12 @@ notarius_config_owner: root notarius_config_group: root notarius_config_directory_mode: "0755" notarius_config_file_mode: "0644" -notarius_config_version: 4 +notarius_config_version: 5 notarius_promptkit_profile_dir: null notarius_promptkit_profile_file: null notarius_promptkit_local_backend_endpoint: null notarius_promptkit_local_backend_concurrency_limit: null +notarius_configkit_imports: null notarius_pipelines: null notarius_concurrency_total_llm: null notarius_concurrency_stage_workers_extract: null diff --git a/meta/argument_specs.yml b/meta/argument_specs.yml index cb34c20..fd5f2c3 100644 --- a/meta/argument_specs.yml +++ b/meta/argument_specs.yml @@ -54,6 +54,10 @@ argument_specs: notarius_promptkit_local_backend_concurrency_limit: type: int required: false + notarius_configkit_imports: + type: list + elements: dict + required: false notarius_pipelines: type: dict required: false diff --git a/templates/config.yml.j2 b/templates/config.yml.j2 index 0df404e..3b03f82 100644 --- a/templates/config.yml.j2 +++ b/templates/config.yml.j2 @@ -1,4 +1,8 @@ version: {{ notarius_config_version }} +{% if notarius_configkit_imports is not none %} +configkit: + imports: {{ notarius_configkit_imports | to_json }} +{% endif %} {% if notarius_promptkit_profile_dir is not none or notarius_promptkit_profile_file is not none or notarius_promptkit_local_backend_endpoint is not none or notarius_promptkit_local_backend_concurrency_limit is not none %} promptkit: {% if notarius_promptkit_profile_dir is not none %} diff --git a/tests/integration b/tests/integration index fc44bf2..22cdc27 100755 --- a/tests/integration +++ b/tests/integration @@ -11,15 +11,17 @@ export ANSIBLE_ROLES_PATH="$(dirname "$repository_root")" inventory="$repository_root/tests/inventory" converge="$repository_root/tests/converge.yml" -verify_config="$repository_root/tests/verify-config.yml" +prepare_import="$repository_root/tests/prepare-import.yml" ansible_playbook="$workspace_venv/bin/ansible-playbook" binary_path=/usr/local/bin/notarius config_path=/usr/local/etc/notarius/config.yml +imported_pipeline_path=/usr/local/etc/notarius/test-pipelines.yml cleanup() { exit_status=$? trap - EXIT "$ansible_playbook" -i "$inventory" "$converge" >/dev/null 2>&1 || true + sudo rm -f -- "$imported_pipeline_path" rm -rf -- "$test_tmp" exit "$exit_status" } @@ -44,7 +46,7 @@ cd "$repository_root" -r collections/requirements.yml \ -p "$ANSIBLE_COLLECTIONS_PATH" "$ansible_playbook" -i "$inventory" --syntax-check "$converge" -"$workspace_venv/bin/ansible-lint" "$converge" "$verify_config" +"$workspace_venv/bin/ansible-lint" "$converge" "$prepare_import" baseline_log="$test_tmp/baseline.log" run_converge "$baseline_log" @@ -55,8 +57,8 @@ run_converge "$baseline_repeat_log" require_clean_recap "$baseline_repeat_log" selected_release_log="$test_tmp/selected-release.log" -run_converge "$selected_release_log" -e notarius_version=v0.5.0 -[[ "$("$binary_path" --version)" == 'notarius v0.5.0' ]] +run_converge "$selected_release_log" -e notarius_version=v0.7.0 +[[ "$("$binary_path" --version)" == 'notarius v0.7.0' ]] custom_go_binary="$test_tmp/go" custom_go_invocations="$test_tmp/go-invocations.log" @@ -69,24 +71,32 @@ chmod 0755 "$custom_go_binary" sudo rm -f -- "$binary_path" recovery_log="$test_tmp/recovery.log" run_converge "$recovery_log" \ - -e notarius_version=v0.5.0 \ + -e notarius_version=v0.7.0 \ -e '{"notarius_manage_build_dependencies": false}' \ -e "notarius_go_binary=$custom_go_binary" grep -q . "$custom_go_invocations" -[[ "$("$binary_path" --version)" == 'notarius v0.5.0' ]] +[[ "$("$binary_path" --version)" == 'notarius v0.7.0' ]] recovery_repeat_log="$test_tmp/recovery-repeat.log" run_converge "$recovery_repeat_log" \ - -e notarius_version=v0.5.0 \ + -e notarius_version=v0.7.0 \ -e '{"notarius_manage_build_dependencies": false}' \ -e "notarius_go_binary=$custom_go_binary" require_clean_recap "$recovery_repeat_log" -pipeline_group_one='{"dnd-session":{"llm_profile":"dnd-extraction","input":"seriatim","artifacts":{"spells":{"extract":"dnd/spells","normalize":"dnd/spells"}}}}' -pipeline_group_two='{"dnd-archive":{"llm_profile":"dnd-extraction","input":"seriatim","artifacts":{"spells":{"extract":"dnd/spells","normalize":"dnd/spells"}}}}' -representative_config="{\"notarius_pipeline_group_one\":$pipeline_group_one,\"notarius_pipeline_group_two\":$pipeline_group_two,\"notarius_pipelines\":\"{{ notarius_pipeline_group_one | combine(notarius_pipeline_group_two) }}\",\"notarius_config_version\":4,\"notarius_promptkit_local_backend_endpoint\":\"http://localhost:8000/v1\",\"notarius_promptkit_local_backend_concurrency_limit\":0,\"notarius_cache_checkpoints_enabled\":false,\"notarius_cache_chunk_plans_directory\":\"\",\"notarius_output_directory\":\"/tmp/notarius-output\",\"notarius_promptkit_profile_dir\":null,\"notarius_promptkit_profile_file\":null,\"notarius_debug_directory\":null}" +pipeline_group_one='{"dnd-session":{"llm_profile":"dnd-extraction","input":{"module":"seriatim"},"artifacts":{"spells":{"extract":{"module":"dnd/spells"},"normalize":{"module":"dnd/spells"}}}}}' +pipeline_group_two='{"dnd-archive":{"llm_profile":"dnd-extraction","input":{"module":"seriatim"},"artifacts":{"spells":{"extract":{"module":"dnd/spells"},"normalize":{"module":"dnd/spells"}}}}}' +representative_config="{\"notarius_pipeline_group_one\":$pipeline_group_one,\"notarius_pipeline_group_two\":$pipeline_group_two,\"notarius_configkit_imports\":[{\"path\":\"test-pipelines.yml\"}],\"notarius_promptkit_local_backend_endpoint\":\"http://localhost:8000/v1\",\"notarius_promptkit_local_backend_concurrency_limit\":0,\"notarius_cache_checkpoints_enabled\":false,\"notarius_cache_chunk_plans_mode\":\"bypass\",\"notarius_cache_chunk_plans_directory\":\"/tmp/notarius-cache/chunk-plans\",\"notarius_cache_checkpoints_directory\":\"/tmp/notarius-cache/checkpoints\",\"notarius_output_directory\":\"/tmp/notarius-output\",\"notarius_promptkit_profile_dir\":null,\"notarius_promptkit_profile_file\":null,\"notarius_debug_directory\":null}" +"$ansible_playbook" -i "$inventory" "$prepare_import" -e "$representative_config" representative_log="$test_tmp/representative.log" run_converge "$representative_log" -e "$representative_config" -"$ansible_playbook" -i "$inventory" "$verify_config" +"$binary_path" config validate --config "$config_path" --pipeline dnd-session +effective_config="$test_tmp/effective-config.yml" +"$binary_path" config effective --config "$config_path" > "$effective_config" +grep -Fq 'dnd-session:' "$effective_config" +grep -Fq 'dnd-archive:' "$effective_config" +grep -Fq 'mode: bypass' "$effective_config" +grep -Fq 'enabled: false' "$effective_config" +grep -Fq 'directory: /tmp/notarius-cache/chunk-plans' "$effective_config" representative_repeat_log="$test_tmp/representative-repeat.log" run_converge "$representative_repeat_log" -e "$representative_config" require_clean_recap "$representative_repeat_log" diff --git a/tests/prepare-import.yml b/tests/prepare-import.yml new file mode 100644 index 0000000..5754d0e --- /dev/null +++ b/tests/prepare-import.yml @@ -0,0 +1,13 @@ +--- +- name: Prepare imported Notarius test configuration + hosts: localhost + gather_facts: false + tasks: + - name: Write test-owned imported pipeline configuration + become: true + ansible.builtin.copy: + content: "{{ {'pipelines': notarius_pipeline_group_one | combine(notarius_pipeline_group_two)} | to_nice_yaml }}" + dest: /usr/local/etc/notarius/test-pipelines.yml + owner: root + group: root + mode: "0644" diff --git a/tests/verify-config.yml b/tests/verify-config.yml deleted file mode 100644 index 39bcbee..0000000 --- a/tests/verify-config.yml +++ /dev/null @@ -1,44 +0,0 @@ ---- -- name: Verify rendered Notarius configuration - hosts: localhost - gather_facts: false - tasks: - - name: Read rendered configuration - become: true - ansible.builtin.slurp: - src: /usr/local/etc/notarius/config.yml - register: notarius_rendered_config_file - - - name: Check representative rendered configuration - ansible.builtin.assert: - that: - - notarius_rendered_config.version == 4 - - notarius_rendered_config.promptkit.local_backend.endpoint == "http://localhost:8000/v1" - - notarius_rendered_config.promptkit.local_backend.concurrency_limit == 0 - - notarius_rendered_config.cache.checkpoints.enabled is false - - notarius_rendered_config.cache.chunk_plans.directory == "" - - notarius_rendered_config.output.directory == "/tmp/notarius-output" - - notarius_rendered_config.pipelines["dnd-session"] == notarius_expected_pipeline - - notarius_rendered_config.pipelines["dnd-archive"] == notarius_expected_pipeline - - notarius_rendered_config.promptkit.profile_dir is not defined - - notarius_rendered_config.promptkit.profile_file is not defined - - notarius_rendered_config.debug is not defined - vars: - notarius_rendered_config: "{{ notarius_rendered_config_file.content | b64decode | from_yaml }}" - notarius_expected_pipeline: - llm_profile: dnd-extraction - input: seriatim - artifacts: - spells: - extract: dnd/spells - normalize: dnd/spells - - - name: Validate rendered configuration - ansible.builtin.command: - argv: - - /usr/local/bin/notarius - - config - - validate - - --config - - /usr/local/etc/notarius/config.yml - changed_when: false