336 lines
10 KiB
YAML
336 lines
10 KiB
YAML
# Install Packs Workflow
|
|
# Complete workflow for installing packs from multiple sources with dependency resolution
|
|
|
|
name: install_packs
|
|
ref: core.install_packs
|
|
label: "Install Packs"
|
|
description: "Install one or more packs from git repositories, HTTP archives, or pack registry with automatic dependency resolution"
|
|
version: "1.0.0"
|
|
|
|
# Input parameters
|
|
parameters:
|
|
type: object
|
|
properties:
|
|
packs:
|
|
type: array
|
|
description: "List of packs to install (git URLs, HTTP URLs, or pack refs like 'slack@1.0.0')"
|
|
items:
|
|
type: string
|
|
minItems: 1
|
|
ref_spec:
|
|
type: string
|
|
description: "Git reference to checkout for git URLs (branch, tag, or commit)"
|
|
skip_dependencies:
|
|
type: boolean
|
|
description: "Skip installing pack dependencies"
|
|
default: false
|
|
skip_tests:
|
|
type: boolean
|
|
description: "Skip running pack tests before registration"
|
|
default: false
|
|
skip_env_build:
|
|
type: boolean
|
|
description: "Skip building runtime environments (Python/Node.js)"
|
|
default: false
|
|
force:
|
|
type: boolean
|
|
description: "Force installation even if packs already exist or tests fail"
|
|
default: false
|
|
registry_url:
|
|
type: string
|
|
description: "Pack registry URL for resolving pack refs"
|
|
default: "https://registry.attune.io/index.json"
|
|
packs_base_dir:
|
|
type: string
|
|
description: "Base directory for permanent pack storage"
|
|
default: "/opt/attune/packs"
|
|
api_url:
|
|
type: string
|
|
description: "Attune API URL"
|
|
default: "http://localhost:8080"
|
|
timeout:
|
|
type: integer
|
|
description: "Timeout in seconds for the entire workflow"
|
|
default: 1800
|
|
minimum: 300
|
|
maximum: 7200
|
|
required:
|
|
- packs
|
|
|
|
# Workflow variables
|
|
vars:
|
|
- temp_dir: null
|
|
- downloaded_packs: []
|
|
- missing_dependencies: []
|
|
- installed_pack_refs: []
|
|
- failed_packs: []
|
|
- start_time: null
|
|
|
|
# Workflow tasks
|
|
tasks:
|
|
# Task 1: Initialize workflow
|
|
- name: initialize
|
|
action: core.noop
|
|
input:
|
|
message: "Starting pack installation workflow"
|
|
publish:
|
|
- start_time: "{{ now() }}"
|
|
- temp_dir: "/tmp/attune-pack-install-{{ uuid() }}"
|
|
on_success: download_packs
|
|
|
|
# Task 2: Download packs from specified sources
|
|
- name: download_packs
|
|
action: core.download_packs
|
|
input:
|
|
packs: "{{ parameters.packs }}"
|
|
destination_dir: "{{ vars.temp_dir }}"
|
|
registry_url: "{{ parameters.registry_url }}"
|
|
ref_spec: "{{ parameters.ref_spec }}"
|
|
api_url: "{{ parameters.api_url }}"
|
|
timeout: 300
|
|
verify_ssl: true
|
|
publish:
|
|
- downloaded_packs: "{{ task.download_packs.result.downloaded_packs }}"
|
|
- failed_packs: "{{ task.download_packs.result.failed_packs }}"
|
|
on_success:
|
|
- when: "{{ task.download_packs.result.success_count > 0 }}"
|
|
do: check_download_results
|
|
on_failure: cleanup_on_failure
|
|
|
|
# Task 3: Check if any packs were successfully downloaded
|
|
- name: check_download_results
|
|
action: core.noop
|
|
input:
|
|
message: "Downloaded {{ task.download_packs.result.success_count }} pack(s)"
|
|
on_success:
|
|
- when: "{{ not parameters.skip_dependencies }}"
|
|
do: get_dependencies
|
|
- when: "{{ parameters.skip_dependencies }}"
|
|
do: build_environments
|
|
|
|
# Task 4: Get pack dependencies from pack.yaml files
|
|
- name: get_dependencies
|
|
action: core.get_pack_dependencies
|
|
input:
|
|
pack_paths: "{{ vars.downloaded_packs | map(attribute='pack_path') | list }}"
|
|
api_url: "{{ parameters.api_url }}"
|
|
skip_validation: false
|
|
publish:
|
|
- missing_dependencies: "{{ task.get_dependencies.result.missing_dependencies }}"
|
|
on_success:
|
|
- when: "{{ task.get_dependencies.result.missing_dependencies | length > 0 }}"
|
|
do: install_dependencies
|
|
- when: "{{ task.get_dependencies.result.missing_dependencies | length == 0 }}"
|
|
do: build_environments
|
|
on_failure: cleanup_on_failure
|
|
|
|
# Task 5: Recursively install missing pack dependencies
|
|
- name: install_dependencies
|
|
action: core.install_packs
|
|
input:
|
|
packs: "{{ vars.missing_dependencies | map(attribute='pack_ref') | list }}"
|
|
skip_dependencies: false
|
|
skip_tests: "{{ parameters.skip_tests }}"
|
|
skip_env_build: "{{ parameters.skip_env_build }}"
|
|
force: "{{ parameters.force }}"
|
|
registry_url: "{{ parameters.registry_url }}"
|
|
packs_base_dir: "{{ parameters.packs_base_dir }}"
|
|
api_url: "{{ parameters.api_url }}"
|
|
timeout: 900
|
|
publish:
|
|
- installed_pack_refs: "{{ task.install_dependencies.result.registered_packs | map(attribute='pack_ref') | list }}"
|
|
on_success: build_environments
|
|
on_failure:
|
|
- when: "{{ parameters.force }}"
|
|
do: build_environments
|
|
- when: "{{ not parameters.force }}"
|
|
do: cleanup_on_failure
|
|
|
|
# Task 6: Build runtime environments (Python virtualenvs, npm install)
|
|
- name: build_environments
|
|
action: core.build_pack_envs
|
|
input:
|
|
pack_paths: "{{ vars.downloaded_packs | map(attribute='pack_path') | list }}"
|
|
packs_base_dir: "{{ parameters.packs_base_dir }}"
|
|
python_version: "3.11"
|
|
nodejs_version: "20"
|
|
skip_python: false
|
|
skip_nodejs: false
|
|
force_rebuild: "{{ parameters.force }}"
|
|
timeout: 600
|
|
on_success:
|
|
- when: "{{ not parameters.skip_tests }}"
|
|
do: run_tests
|
|
- when: "{{ parameters.skip_tests }}"
|
|
do: register_packs
|
|
on_failure:
|
|
- when: "{{ parameters.force or parameters.skip_env_build }}"
|
|
do:
|
|
- when: "{{ not parameters.skip_tests }}"
|
|
next: run_tests
|
|
- when: "{{ parameters.skip_tests }}"
|
|
next: register_packs
|
|
- when: "{{ not parameters.force and not parameters.skip_env_build }}"
|
|
do: cleanup_on_failure
|
|
|
|
# Task 7: Run pack tests to verify functionality
|
|
- name: run_tests
|
|
action: core.run_pack_tests
|
|
input:
|
|
pack_paths: "{{ vars.downloaded_packs | map(attribute='pack_path') | list }}"
|
|
timeout: 300
|
|
fail_on_error: false
|
|
on_success: register_packs
|
|
on_failure:
|
|
- when: "{{ parameters.force }}"
|
|
do: register_packs
|
|
- when: "{{ not parameters.force }}"
|
|
do: cleanup_on_failure
|
|
|
|
# Task 8: Register packs in database and copy to permanent storage
|
|
- name: register_packs
|
|
action: core.register_packs
|
|
input:
|
|
pack_paths: "{{ vars.downloaded_packs | map(attribute='pack_path') | list }}"
|
|
packs_base_dir: "{{ parameters.packs_base_dir }}"
|
|
skip_validation: false
|
|
skip_tests: "{{ parameters.skip_tests }}"
|
|
force: "{{ parameters.force }}"
|
|
api_url: "{{ parameters.api_url }}"
|
|
on_success: cleanup_success
|
|
on_failure: cleanup_on_failure
|
|
|
|
# Task 9: Cleanup temporary directory on success
|
|
- name: cleanup_success
|
|
action: core.noop
|
|
input:
|
|
message: "Pack installation completed successfully. Cleaning up temporary directory: {{ vars.temp_dir }}"
|
|
publish:
|
|
- cleanup_status: "success"
|
|
|
|
# Task 10: Cleanup temporary directory on failure
|
|
- name: cleanup_on_failure
|
|
action: core.noop
|
|
input:
|
|
message: "Pack installation failed. Cleaning up temporary directory: {{ vars.temp_dir }}"
|
|
publish:
|
|
- cleanup_status: "failed"
|
|
|
|
# Output schema
|
|
output_schema:
|
|
type: object
|
|
properties:
|
|
registered_packs:
|
|
type: array
|
|
description: "Successfully registered packs"
|
|
items:
|
|
type: object
|
|
properties:
|
|
pack_ref:
|
|
type: string
|
|
pack_id:
|
|
type: integer
|
|
pack_version:
|
|
type: string
|
|
storage_path:
|
|
type: string
|
|
components_count:
|
|
type: integer
|
|
failed_packs:
|
|
type: array
|
|
description: "Packs that failed to install"
|
|
items:
|
|
type: object
|
|
properties:
|
|
source:
|
|
type: string
|
|
error:
|
|
type: string
|
|
stage:
|
|
type: string
|
|
installed_dependencies:
|
|
type: array
|
|
description: "Pack dependencies that were installed"
|
|
items:
|
|
type: string
|
|
summary:
|
|
type: object
|
|
description: "Installation summary"
|
|
properties:
|
|
total_requested:
|
|
type: integer
|
|
success_count:
|
|
type: integer
|
|
failure_count:
|
|
type: integer
|
|
dependencies_installed:
|
|
type: integer
|
|
duration_seconds:
|
|
type: integer
|
|
|
|
# Metadata
|
|
metadata:
|
|
description: |
|
|
This workflow orchestrates the complete pack installation process:
|
|
|
|
1. Download Packs: Downloads packs from git repositories, HTTP archives, or pack registry
|
|
2. Get Dependencies: Analyzes pack.yaml files to identify dependencies
|
|
3. Install Dependencies: Recursively installs missing pack dependencies
|
|
4. Build Environments: Creates Python virtualenvs, installs requirements.txt and package.json deps
|
|
5. Run Tests: Executes pack test suites (if present and not skipped)
|
|
6. Register Packs: Loads pack components into database and copies to permanent storage
|
|
|
|
The workflow supports:
|
|
- Multiple pack sources (git URLs, HTTP archives, pack refs)
|
|
- Automatic dependency resolution (recursive)
|
|
- Runtime environment setup (Python, Node.js)
|
|
- Pack testing before registration
|
|
- Force mode to override validation failures
|
|
- Comprehensive error handling and cleanup
|
|
|
|
examples:
|
|
- name: "Install pack from git repository"
|
|
input:
|
|
packs:
|
|
- "https://github.com/attune/pack-slack.git"
|
|
ref_spec: "v1.0.0"
|
|
skip_dependencies: false
|
|
skip_tests: false
|
|
force: false
|
|
|
|
- name: "Install multiple packs from registry"
|
|
input:
|
|
packs:
|
|
- "slack@1.0.0"
|
|
- "aws@2.1.0"
|
|
- "kubernetes@3.0.0"
|
|
skip_dependencies: false
|
|
skip_tests: false
|
|
force: false
|
|
|
|
- name: "Install pack with force mode (skip validations)"
|
|
input:
|
|
packs:
|
|
- "https://github.com/myorg/pack-custom.git"
|
|
ref_spec: "main"
|
|
skip_dependencies: true
|
|
skip_tests: true
|
|
force: true
|
|
|
|
- name: "Install from HTTP archive"
|
|
input:
|
|
packs:
|
|
- "https://example.com/packs/custom-pack.tar.gz"
|
|
skip_dependencies: false
|
|
skip_tests: false
|
|
force: false
|
|
|
|
tags:
|
|
- pack
|
|
- installation
|
|
- workflow
|
|
- automation
|
|
- dependencies
|
|
- git
|
|
- registry
|