yera 0.1.1__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- yera-0.2.1/.containerignore +14 -0
- yera-0.2.1/.github/actions/build-ui/action.yml +38 -0
- yera-0.2.1/.github/actions/run-build-tests/action.yml +19 -0
- yera-0.2.1/.github/actions/run-package-tests/action.yml +24 -0
- yera-0.2.1/.github/python-versions.json +1 -0
- yera-0.2.1/.github/workflows/benchmarks.yml +35 -0
- yera-0.2.1/.github/workflows/build-and-test-package.yml +67 -0
- yera-0.2.1/.github/workflows/ci-cd.yml +178 -0
- yera-0.2.1/.github/workflows/deploy-aks.yml +64 -0
- yera-0.2.1/.github/workflows/deploy-eks.yml +86 -0
- yera-0.2.1/.github/workflows/destroy-aks.yml +138 -0
- yera-0.2.1/.github/workflows/destroy-eks.yml +131 -0
- yera-0.2.1/.github/workflows/release.yml +93 -0
- yera-0.2.1/.gitignore +45 -0
- yera-0.2.1/.pre-commit-config.yaml +39 -0
- yera-0.2.1/CONTRIBUTING.md +157 -0
- yera-0.2.1/PKG-INFO +65 -0
- yera-0.2.1/README.md +27 -0
- yera-0.2.1/pyproject.toml +298 -0
- yera-0.2.1/src/infra_mvp/base_client.py +29 -0
- yera-0.2.1/src/infra_mvp/base_server.py +68 -0
- yera-0.2.1/src/infra_mvp/monitoring/__init__.py +15 -0
- yera-0.2.1/src/infra_mvp/monitoring/metrics.py +185 -0
- yera-0.2.1/src/infra_mvp/stream/README.md +56 -0
- yera-0.2.1/src/infra_mvp/stream/__init__.py +14 -0
- yera-0.2.1/src/infra_mvp/stream/__main__.py +101 -0
- yera-0.2.1/src/infra_mvp/stream/agents/demos/financial/chart_additions_plan.md +170 -0
- yera-0.2.1/src/infra_mvp/stream/agents/demos/financial/portfolio_assistant_stream.json +1571 -0
- yera-0.2.1/src/infra_mvp/stream/agents/reference/blocks/action.json +170 -0
- yera-0.2.1/src/infra_mvp/stream/agents/reference/blocks/button.json +66 -0
- yera-0.2.1/src/infra_mvp/stream/agents/reference/blocks/date.json +65 -0
- yera-0.2.1/src/infra_mvp/stream/agents/reference/blocks/input_prompt.json +94 -0
- yera-0.2.1/src/infra_mvp/stream/agents/reference/blocks/layout.json +288 -0
- yera-0.2.1/src/infra_mvp/stream/agents/reference/blocks/markdown.json +344 -0
- yera-0.2.1/src/infra_mvp/stream/agents/reference/blocks/slider.json +67 -0
- yera-0.2.1/src/infra_mvp/stream/agents/reference/blocks/spinner.json +110 -0
- yera-0.2.1/src/infra_mvp/stream/agents/reference/blocks/table.json +56 -0
- yera-0.2.1/src/infra_mvp/stream/agents/reference/chat_dynamics/branching_test_stream.json +145 -0
- yera-0.2.1/src/infra_mvp/stream/app.py +49 -0
- yera-0.2.1/src/infra_mvp/stream/container.py +112 -0
- yera-0.2.1/src/infra_mvp/stream/schemas/__init__.py +16 -0
- yera-0.2.1/src/infra_mvp/stream/schemas/agent.py +24 -0
- yera-0.2.1/src/infra_mvp/stream/schemas/interaction.py +28 -0
- yera-0.2.1/src/infra_mvp/stream/schemas/session.py +30 -0
- yera-0.2.1/src/infra_mvp/stream/server.py +321 -0
- yera-0.2.1/src/infra_mvp/stream/services/__init__.py +12 -0
- yera-0.2.1/src/infra_mvp/stream/services/agent_service.py +40 -0
- yera-0.2.1/src/infra_mvp/stream/services/event_converter.py +83 -0
- yera-0.2.1/src/infra_mvp/stream/services/session_service.py +247 -0
- yera-0.2.1/src/yera/__init__.py +51 -0
- yera-0.2.1/src/yera/agents/__init__.py +2 -0
- yera-0.2.1/src/yera/agents/context.py +41 -0
- yera-0.2.1/src/yera/agents/dataclasses.py +69 -0
- yera-0.2.1/src/yera/agents/decorator.py +207 -0
- yera-0.2.1/src/yera/agents/discovery.py +124 -0
- yera-0.2.1/src/yera/agents/typing/__init__.py +0 -0
- yera-0.2.1/src/yera/agents/typing/coerce.py +408 -0
- yera-0.2.1/src/yera/agents/typing/utils.py +19 -0
- yera-0.2.1/src/yera/agents/typing/validate.py +206 -0
- yera-0.2.1/src/yera/cli.py +377 -0
- yera-0.2.1/src/yera/config/__init__.py +1 -0
- yera-0.2.1/src/yera/config/config_utils.py +164 -0
- yera-0.2.1/src/yera/config/function_config.py +55 -0
- yera-0.2.1/src/yera/config/logging.py +18 -0
- yera-0.2.1/src/yera/config/tool_config.py +8 -0
- yera-0.2.1/src/yera/config2/__init__.py +8 -0
- yera-0.2.1/src/yera/config2/dataclasses.py +534 -0
- yera-0.2.1/src/yera/config2/keyring.py +270 -0
- yera-0.2.1/src/yera/config2/paths.py +28 -0
- yera-0.2.1/src/yera/config2/read.py +113 -0
- yera-0.2.1/src/yera/config2/setup.py +109 -0
- yera-0.2.1/src/yera/config2/setup_handlers/__init__.py +1 -0
- yera-0.2.1/src/yera/config2/setup_handlers/anthropic.py +126 -0
- yera-0.2.1/src/yera/config2/setup_handlers/azure.py +236 -0
- yera-0.2.1/src/yera/config2/setup_handlers/base.py +125 -0
- yera-0.2.1/src/yera/config2/setup_handlers/llama_cpp.py +205 -0
- yera-0.2.1/src/yera/config2/setup_handlers/ollama.py +157 -0
- yera-0.2.1/src/yera/config2/setup_handlers/openai.py +137 -0
- yera-0.2.1/src/yera/config2/write.py +87 -0
- yera-0.2.1/src/yera/dsl/__init__.py +0 -0
- yera-0.2.1/src/yera/dsl/functions.py +94 -0
- yera-0.2.1/src/yera/dsl/struct.py +20 -0
- yera-0.2.1/src/yera/dsl/workspace.py +79 -0
- yera-0.2.1/src/yera/events/__init__.py +57 -0
- yera-0.2.1/src/yera/events/blocks/__init__.py +68 -0
- yera-0.2.1/src/yera/events/blocks/action.py +57 -0
- yera-0.2.1/src/yera/events/blocks/bar_chart.py +92 -0
- yera-0.2.1/src/yera/events/blocks/base/__init__.py +20 -0
- yera-0.2.1/src/yera/events/blocks/base/base.py +166 -0
- yera-0.2.1/src/yera/events/blocks/base/chart.py +288 -0
- yera-0.2.1/src/yera/events/blocks/base/layout.py +111 -0
- yera-0.2.1/src/yera/events/blocks/buttons.py +37 -0
- yera-0.2.1/src/yera/events/blocks/columns.py +26 -0
- yera-0.2.1/src/yera/events/blocks/container.py +24 -0
- yera-0.2.1/src/yera/events/blocks/date_picker.py +50 -0
- yera-0.2.1/src/yera/events/blocks/exit.py +39 -0
- yera-0.2.1/src/yera/events/blocks/form.py +24 -0
- yera-0.2.1/src/yera/events/blocks/input_echo.py +22 -0
- yera-0.2.1/src/yera/events/blocks/input_request.py +31 -0
- yera-0.2.1/src/yera/events/blocks/line_chart.py +97 -0
- yera-0.2.1/src/yera/events/blocks/markdown.py +67 -0
- yera-0.2.1/src/yera/events/blocks/slider.py +54 -0
- yera-0.2.1/src/yera/events/blocks/spinner.py +55 -0
- yera-0.2.1/src/yera/events/blocks/system_prompt.py +22 -0
- yera-0.2.1/src/yera/events/blocks/table.py +291 -0
- yera-0.2.1/src/yera/events/models/__init__.py +39 -0
- yera-0.2.1/src/yera/events/models/block_data.py +112 -0
- yera-0.2.1/src/yera/events/models/in_event.py +7 -0
- yera-0.2.1/src/yera/events/models/out_event.py +75 -0
- yera-0.2.1/src/yera/events/runtime.py +187 -0
- yera-0.2.1/src/yera/events/stream.py +91 -0
- yera-0.2.1/src/yera/models/__init__.py +0 -0
- yera-0.2.1/src/yera/models/data_classes.py +20 -0
- yera-0.2.1/src/yera/models/llm_atlas_proxy.py +44 -0
- yera-0.2.1/src/yera/models/llm_context.py +99 -0
- yera-0.2.1/src/yera/models/llm_interfaces/__init__.py +0 -0
- yera-0.2.1/src/yera/models/llm_interfaces/anthropic.py +153 -0
- yera-0.2.1/src/yera/models/llm_interfaces/aws_bedrock.py +14 -0
- yera-0.2.1/src/yera/models/llm_interfaces/azure_openai.py +143 -0
- yera-0.2.1/src/yera/models/llm_interfaces/base.py +26 -0
- yera-0.2.1/src/yera/models/llm_interfaces/interface_registry.py +74 -0
- yera-0.2.1/src/yera/models/llm_interfaces/llama_cpp.py +136 -0
- yera-0.2.1/src/yera/models/llm_interfaces/mock.py +29 -0
- yera-0.2.1/src/yera/models/llm_interfaces/ollama_interface.py +118 -0
- yera-0.2.1/src/yera/models/llm_interfaces/open_ai.py +150 -0
- yera-0.2.1/src/yera/models/llm_workspace.py +19 -0
- yera-0.2.1/src/yera/models/model_atlas.py +139 -0
- yera-0.2.1/src/yera/models/model_definition.py +38 -0
- yera-0.2.1/src/yera/models/model_factory.py +33 -0
- yera-0.2.1/src/yera/opaque/__init__.py +9 -0
- yera-0.2.1/src/yera/opaque/base.py +20 -0
- yera-0.2.1/src/yera/opaque/decorator.py +8 -0
- yera-0.2.1/src/yera/opaque/markdown.py +57 -0
- yera-0.2.1/src/yera/opaque/opaque_function.py +25 -0
- yera-0.2.1/src/yera/tools/__init__.py +29 -0
- yera-0.2.1/src/yera/tools/atlas_tool.py +20 -0
- yera-0.2.1/src/yera/tools/base.py +24 -0
- yera-0.2.1/src/yera/tools/decorated_tool.py +18 -0
- yera-0.2.1/src/yera/tools/decorator.py +35 -0
- yera-0.2.1/src/yera/tools/tool_atlas.py +51 -0
- yera-0.2.1/src/yera/tools/tool_utils.py +361 -0
- yera-0.2.1/src/yera/ui/dist/404.html +1 -0
- yera-0.2.1/src/yera/ui/dist/__next.__PAGE__.txt +10 -0
- yera-0.2.1/src/yera/ui/dist/__next._full.txt +23 -0
- yera-0.2.1/src/yera/ui/dist/__next._head.txt +6 -0
- yera-0.2.1/src/yera/ui/dist/__next._index.txt +5 -0
- yera-0.2.1/src/yera/ui/dist/__next._tree.txt +7 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/T8WGYqDMoHDKKoHj0O3HK/_buildManifest.js +11 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/T8WGYqDMoHDKKoHj0O3HK/_clientMiddlewareManifest.json +1 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/T8WGYqDMoHDKKoHj0O3HK/_ssgManifest.js +1 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/chunks/4c4688e1ff21ad98.js +1 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/chunks/652cd53c27924d50.js +4 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/chunks/786d2107b51e8499.css +1 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/chunks/7de9141b1af425c3.js +1 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/chunks/87ef65064d3524c1.js +2 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/chunks/a6dad97d9634a72d.js +1 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/chunks/a6dad97d9634a72d.js.map +1 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/chunks/c4c79d5d0b280aeb.js +1 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/chunks/dc2d2a247505d66f.css +5 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/chunks/f773f714b55ec620.js +37 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/chunks/turbopack-98b3031e1b1dbc33.js +4 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/media/14e23f9b59180572-s.9c448f3c.woff2 +0 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/media/2a65768255d6b625-s.p.d19752fb.woff2 +0 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/media/2b2eb4836d2dad95-s.f36de3af.woff2 +0 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/media/31183d9fd602dc89-s.c4ff9b73.woff2 +0 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/media/3fcb63a1ac6a562e-s.2f77a576.woff2 +0 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/media/45ec8de98929b0f6-s.81056204.woff2 +0 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/media/4fa387ec64143e14-s.c1fdd6c2.woff2 +0 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/media/65c558afe41e89d6-s.e2c8389a.woff2 +0 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/media/67add6cc0f54b8cf-s.8ce53448.woff2 +0 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/media/7178b3e590c64307-s.b97b3418.woff2 +0 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/media/797e433ab948586e-s.p.dbea232f.woff2 +0 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/media/8a480f0b521d4e75-s.8e0177b5.woff2 +0 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/media/a8ff2d5d0ccb0d12-s.fc5b72a7.woff2 +0 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/media/aae5f0be330e13db-s.p.853e26d6.woff2 +0 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/media/b11a6ccf4a3edec7-s.2113d282.woff2 +0 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/media/b49b0d9b851e4899-s.4f3fa681.woff2 +0 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/media/bbc41e54d2fcbd21-s.799d8ef8.woff2 +0 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/media/caa3a2e1cccd8315-s.p.853070df.woff2 +0 -0
- yera-0.2.1/src/yera/ui/dist/_next/static/media/favicon.0b3bf435.ico +0 -0
- yera-0.2.1/src/yera/ui/dist/_not-found/__next._full.txt +14 -0
- yera-0.2.1/src/yera/ui/dist/_not-found/__next._head.txt +6 -0
- yera-0.2.1/src/yera/ui/dist/_not-found/__next._index.txt +5 -0
- yera-0.2.1/src/yera/ui/dist/_not-found/__next._not-found.__PAGE__.txt +5 -0
- yera-0.2.1/src/yera/ui/dist/_not-found/__next._not-found.txt +4 -0
- yera-0.2.1/src/yera/ui/dist/_not-found/__next._tree.txt +2 -0
- yera-0.2.1/src/yera/ui/dist/_not-found.html +1 -0
- yera-0.2.1/src/yera/ui/dist/_not-found.txt +14 -0
- yera-0.2.1/src/yera/ui/dist/agent-icon.svg +3 -0
- yera-0.2.1/src/yera/ui/dist/favicon.ico +0 -0
- yera-0.2.1/src/yera/ui/dist/file.svg +1 -0
- yera-0.2.1/src/yera/ui/dist/globe.svg +1 -0
- yera-0.2.1/src/yera/ui/dist/index.html +1 -0
- yera-0.2.1/src/yera/ui/dist/index.txt +23 -0
- yera-0.2.1/src/yera/ui/dist/logo/full_logo.png +0 -0
- yera-0.2.1/src/yera/ui/dist/logo/rune_logo.png +0 -0
- yera-0.2.1/src/yera/ui/dist/logo/rune_logo_borderless.png +0 -0
- yera-0.2.1/src/yera/ui/dist/logo/text_logo.png +0 -0
- yera-0.2.1/src/yera/ui/dist/next.svg +1 -0
- yera-0.2.1/src/yera/ui/dist/send.png +0 -0
- yera-0.2.1/src/yera/ui/dist/send_single.png +0 -0
- yera-0.2.1/src/yera/ui/dist/vercel.svg +1 -0
- yera-0.2.1/src/yera/ui/dist/window.svg +1 -0
- yera-0.2.1/src/yera/utils/__init__.py +1 -0
- yera-0.2.1/src/yera/utils/path_utils.py +38 -0
- yera-0.2.1/uv.lock +5418 -0
- yera-0.1.1/.gitignore +0 -10
- yera-0.1.1/PKG-INFO +0 -11
- yera-0.1.1/README.md +0 -4
- yera-0.1.1/main.py +0 -6
- yera-0.1.1/pyproject.toml +0 -11
- yera-0.1.1/src/yera/__init__.py +0 -2
- {yera-0.1.1 → yera-0.2.1}/.python-version +0 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: 'Build UI for Editable Install'
|
|
2
|
+
description: 'Builds the Next.js UI and copies it to src/yera/ui/dist for hatchling force-include'
|
|
3
|
+
|
|
4
|
+
inputs:
|
|
5
|
+
node-version:
|
|
6
|
+
description: 'Node.js version to use'
|
|
7
|
+
required: false
|
|
8
|
+
default: '20'
|
|
9
|
+
|
|
10
|
+
runs:
|
|
11
|
+
using: 'composite'
|
|
12
|
+
steps:
|
|
13
|
+
- name: Set up Node.js
|
|
14
|
+
uses: actions/setup-node@v4
|
|
15
|
+
with:
|
|
16
|
+
node-version: ${{ inputs.node-version }}
|
|
17
|
+
cache: 'npm'
|
|
18
|
+
cache-dependency-path: web/yera-chat/package-lock.json
|
|
19
|
+
|
|
20
|
+
- name: Build UI for editable install
|
|
21
|
+
shell: bash
|
|
22
|
+
run: |
|
|
23
|
+
cd web/yera-chat
|
|
24
|
+
npm install
|
|
25
|
+
npm run build
|
|
26
|
+
cd ../..
|
|
27
|
+
mkdir -p src/yera/ui
|
|
28
|
+
rm -rf src/yera/ui/dist
|
|
29
|
+
cp -r web/yera-chat/dist src/yera/ui/
|
|
30
|
+
|
|
31
|
+
- name: Verify UI build succeeded
|
|
32
|
+
shell: bash
|
|
33
|
+
run: |
|
|
34
|
+
if [ ! -f "src/yera/ui/dist/index.html" ]; then
|
|
35
|
+
echo "❌ UI build failed: src/yera/ui/dist/index.html not found"
|
|
36
|
+
exit 1
|
|
37
|
+
fi
|
|
38
|
+
echo "✅ UI build verified: dist/index.html exists"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
name: 'Run build verification tests'
|
|
2
|
+
description: 'Runs tests/release/build/ in a clean venv. Expects dist/ (wheel + sdist) to exist; call after building the package.'
|
|
3
|
+
|
|
4
|
+
runs:
|
|
5
|
+
using: 'composite'
|
|
6
|
+
steps:
|
|
7
|
+
- name: Install uv
|
|
8
|
+
uses: astral-sh/setup-uv@v4
|
|
9
|
+
with:
|
|
10
|
+
version: "latest"
|
|
11
|
+
enable-cache: true
|
|
12
|
+
|
|
13
|
+
- name: Install Python (from .python-version)
|
|
14
|
+
shell: bash
|
|
15
|
+
run: uv python install $(cat .python-version)
|
|
16
|
+
|
|
17
|
+
- name: Run build verification tests
|
|
18
|
+
shell: bash
|
|
19
|
+
run: ./scripts/release/tests/test_build.sh
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: 'Run package-level tests'
|
|
2
|
+
description: 'Runs tests/release/package/ in a clean venv. Expects dist/ (wheel) to exist; call after downloading the build artifact.'
|
|
3
|
+
|
|
4
|
+
inputs:
|
|
5
|
+
python-version:
|
|
6
|
+
description: 'Python version to use (e.g. 3.10, 3.11, 3.12).'
|
|
7
|
+
required: true
|
|
8
|
+
|
|
9
|
+
runs:
|
|
10
|
+
using: 'composite'
|
|
11
|
+
steps:
|
|
12
|
+
- name: Install uv
|
|
13
|
+
uses: astral-sh/setup-uv@v4
|
|
14
|
+
with:
|
|
15
|
+
version: "latest"
|
|
16
|
+
enable-cache: true
|
|
17
|
+
|
|
18
|
+
- name: Install Python
|
|
19
|
+
shell: bash
|
|
20
|
+
run: uv python install "${{ inputs.python-version }}"
|
|
21
|
+
|
|
22
|
+
- name: Run package tests
|
|
23
|
+
shell: bash
|
|
24
|
+
run: ./scripts/release/tests/test_package.sh
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
["3.10", "3.11", "3.12"]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: CodSpeed Benchmarks
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- "main"
|
|
7
|
+
pull_request:
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read # for actions/checkout
|
|
12
|
+
id-token: write # for OIDC authentication with CodSpeed (public repos)
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
benchmarks:
|
|
16
|
+
name: Run performance benchmarks
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Install uv
|
|
23
|
+
uses: astral-sh/setup-uv@v7
|
|
24
|
+
|
|
25
|
+
- name: Build UI for editable install
|
|
26
|
+
uses: ./.github/actions/build-ui
|
|
27
|
+
|
|
28
|
+
- name: Install dependencies
|
|
29
|
+
run: uv sync --dev
|
|
30
|
+
|
|
31
|
+
- name: Run benchmarks
|
|
32
|
+
uses: CodSpeedHQ/action@v4
|
|
33
|
+
with:
|
|
34
|
+
mode: instrumentation # Uses Valgrind for consistent measurements + flame graphs
|
|
35
|
+
run: uv run pytest tests/src/performance/ --codspeed
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Reusable workflow: build distribution with bundled UI and run build/package tests.
|
|
2
|
+
# Used by ci-cd.yml (on push/PR) and release.yml (after version verification).
|
|
3
|
+
# Callers must pass python-versions (JSON array of version strings, e.g. ["3.10","3.11","3.12"]).
|
|
4
|
+
name: Build and test package
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
workflow_call:
|
|
8
|
+
inputs:
|
|
9
|
+
python-versions:
|
|
10
|
+
description: 'JSON array of Python versions to test (e.g. ["3.10","3.11","3.12"])'
|
|
11
|
+
required: true
|
|
12
|
+
type: string
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
name: Build and test distribution
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
timeout-minutes: 15
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Set up Node.js
|
|
23
|
+
uses: actions/setup-node@v4
|
|
24
|
+
with:
|
|
25
|
+
node-version: "20"
|
|
26
|
+
cache: 'npm'
|
|
27
|
+
cache-dependency-path: web/yera-chat/package-lock.json
|
|
28
|
+
|
|
29
|
+
- name: Install uv
|
|
30
|
+
uses: astral-sh/setup-uv@v4
|
|
31
|
+
with:
|
|
32
|
+
version: "latest"
|
|
33
|
+
enable-cache: true
|
|
34
|
+
|
|
35
|
+
- name: Build package with bundled UI
|
|
36
|
+
run: ./scripts/release/build_package.sh
|
|
37
|
+
|
|
38
|
+
- name: Run build verification tests
|
|
39
|
+
uses: ./.github/actions/run-build-tests
|
|
40
|
+
|
|
41
|
+
- name: Upload distribution packages
|
|
42
|
+
uses: actions/upload-artifact@v4
|
|
43
|
+
with:
|
|
44
|
+
name: python-package-distributions
|
|
45
|
+
path: dist/
|
|
46
|
+
|
|
47
|
+
test:
|
|
48
|
+
name: Test installation (Python ${{ matrix.python-version }})
|
|
49
|
+
needs: [build]
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
timeout-minutes: 10
|
|
52
|
+
strategy:
|
|
53
|
+
matrix:
|
|
54
|
+
python-version: ${{ fromJson(inputs.python-versions) }}
|
|
55
|
+
steps:
|
|
56
|
+
- uses: actions/checkout@v4
|
|
57
|
+
|
|
58
|
+
- name: Download distributions
|
|
59
|
+
uses: actions/download-artifact@v4
|
|
60
|
+
with:
|
|
61
|
+
name: python-package-distributions
|
|
62
|
+
path: dist/
|
|
63
|
+
|
|
64
|
+
- name: Run package tests
|
|
65
|
+
uses: ./.github/actions/run-package-tests
|
|
66
|
+
with:
|
|
67
|
+
python-version: ${{ matrix.python-version }}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
name: Python CI/CD with uv
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [ main, devel ]
|
|
5
|
+
pull_request:
|
|
6
|
+
types: [opened, synchronize, reopened, ready_for_review]
|
|
7
|
+
paths-ignore:
|
|
8
|
+
- '**.md'
|
|
9
|
+
- 'docs/**'
|
|
10
|
+
- '.gitignore'
|
|
11
|
+
- '.pre-commit-config.yaml'
|
|
12
|
+
- '.containerignore'
|
|
13
|
+
- '.dockerignore'
|
|
14
|
+
jobs:
|
|
15
|
+
setup:
|
|
16
|
+
name: Set Python matrix
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
outputs:
|
|
19
|
+
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- id: set-matrix
|
|
23
|
+
run: echo "matrix=$(tr -d '\n' < .github/python-versions.json)" >> $GITHUB_OUTPUT
|
|
24
|
+
|
|
25
|
+
test:
|
|
26
|
+
needs: setup
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
timeout-minutes: 10
|
|
29
|
+
strategy:
|
|
30
|
+
matrix:
|
|
31
|
+
python-version: ${{ fromJson(needs.setup.outputs.matrix) }}
|
|
32
|
+
steps:
|
|
33
|
+
# downloads repository's source code into the GitHub Actions runner
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
- name: Install uv
|
|
36
|
+
uses: astral-sh/setup-uv@v4
|
|
37
|
+
with:
|
|
38
|
+
version: "latest"
|
|
39
|
+
enable-cache: true
|
|
40
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
41
|
+
run: uv python install ${{ matrix.python-version }}
|
|
42
|
+
- name: Build UI for editable install
|
|
43
|
+
uses: ./.github/actions/build-ui
|
|
44
|
+
# Fail fast: Check formatting and linting before installing dependencies
|
|
45
|
+
- name: Check code formatting with ruff
|
|
46
|
+
run: uvx ruff format --check .
|
|
47
|
+
- name: Lint with ruff
|
|
48
|
+
run: uvx ruff check . --output-format=github
|
|
49
|
+
- name: Install dependencies
|
|
50
|
+
run: |
|
|
51
|
+
uv sync --python ${{ matrix.python-version }} --group dev
|
|
52
|
+
- name: Run pip-audit
|
|
53
|
+
run: uv run pip-audit
|
|
54
|
+
- name: Run pip-licenses check
|
|
55
|
+
run: |
|
|
56
|
+
LICENSES="MIT;MIT License;BSD License;BSD-2-Clause;BSD-3-Clause;\
|
|
57
|
+
Apache Software License;Apache-2.0;Apache 2.0;ISC License (ISCL);\
|
|
58
|
+
Python Software Foundation License;PSF-2.0;Unlicense;\
|
|
59
|
+
Mozilla Public License 2.0 (MPL 2.0);ISC"
|
|
60
|
+
uv run --no-dev pip-licenses \
|
|
61
|
+
--partial-match \
|
|
62
|
+
--allow-only "$LICENSES" \
|
|
63
|
+
--ignore-packages yera matplotlib-inline
|
|
64
|
+
- name: Run tests with pytest
|
|
65
|
+
run: |
|
|
66
|
+
uv run pytest tests/src --cov=./ --cov-report=xml
|
|
67
|
+
- name: Upload coverage to Codecov
|
|
68
|
+
uses: codecov/codecov-action@v4
|
|
69
|
+
with:
|
|
70
|
+
file: ./coverage.xml
|
|
71
|
+
flags: unittests
|
|
72
|
+
name: codecov-umbrella
|
|
73
|
+
|
|
74
|
+
release-build-and-test:
|
|
75
|
+
name: Build and test package
|
|
76
|
+
needs: setup
|
|
77
|
+
uses: ./.github/workflows/build-and-test-package.yml
|
|
78
|
+
with:
|
|
79
|
+
python-versions: ${{ needs.setup.outputs.matrix }}
|
|
80
|
+
|
|
81
|
+
deploy:
|
|
82
|
+
needs: test
|
|
83
|
+
runs-on: ubuntu-latest
|
|
84
|
+
timeout-minutes: 10
|
|
85
|
+
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
|
|
86
|
+
steps:
|
|
87
|
+
# downloads repository's source code into the GitHub Actions runner
|
|
88
|
+
- uses: actions/checkout@v4
|
|
89
|
+
- name: Install uv
|
|
90
|
+
uses: astral-sh/setup-uv@v4
|
|
91
|
+
with:
|
|
92
|
+
version: "latest"
|
|
93
|
+
enable-cache: true
|
|
94
|
+
- name: Build Docker image
|
|
95
|
+
run: |
|
|
96
|
+
docker build -t python-app:${{ github.sha }} .
|
|
97
|
+
docker tag python-app:${{ github.sha }} python-app:latest
|
|
98
|
+
- name: Run application in Docker container
|
|
99
|
+
run: |
|
|
100
|
+
# Run the container in detached mode
|
|
101
|
+
docker run -d \
|
|
102
|
+
--name python-app-container \
|
|
103
|
+
-p 8000:8000 \
|
|
104
|
+
-e ENVIRONMENT=production \
|
|
105
|
+
-e LOG_LEVEL=info \
|
|
106
|
+
python-app:latest
|
|
107
|
+
- name: Wait for application to start
|
|
108
|
+
run: |
|
|
109
|
+
echo "Waiting for application to start..."
|
|
110
|
+
sleep 10
|
|
111
|
+
|
|
112
|
+
# Check if container is running
|
|
113
|
+
if docker ps | grep -q python-app-container; then
|
|
114
|
+
echo "✅ Container is running successfully!"
|
|
115
|
+
docker logs python-app-container
|
|
116
|
+
else
|
|
117
|
+
echo "❌ Container failed to start"
|
|
118
|
+
docker logs python-app-container
|
|
119
|
+
exit 1
|
|
120
|
+
fi
|
|
121
|
+
- name: Run integration tests against containerized app
|
|
122
|
+
run: |
|
|
123
|
+
# Test if the application is responding, for now just initiate a test against the health endpoint
|
|
124
|
+
echo "Running integration tests..."
|
|
125
|
+
|
|
126
|
+
# Test HTTP endpoints
|
|
127
|
+
if curl -f http://localhost:8000/health; then
|
|
128
|
+
echo "✅ Health check passed!"
|
|
129
|
+
else
|
|
130
|
+
echo "❌ Health check failed!"
|
|
131
|
+
docker logs python-app-container
|
|
132
|
+
exit 1
|
|
133
|
+
fi
|
|
134
|
+
- name: Security scan
|
|
135
|
+
run: |
|
|
136
|
+
# Install Trivy for container security scanning
|
|
137
|
+
sudo apt-get update
|
|
138
|
+
sudo apt-get install wget apt-transport-https gnupg lsb-release
|
|
139
|
+
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
|
|
140
|
+
echo "deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | sudo tee -a /etc/apt/sources.list.d/trivy.list
|
|
141
|
+
sudo apt-get update
|
|
142
|
+
sudo apt-get install trivy
|
|
143
|
+
|
|
144
|
+
# Scan the Docker image for vulnerabilities
|
|
145
|
+
trivy image --severity HIGH,CRITICAL python-app:latest
|
|
146
|
+
- name: Run application tasks
|
|
147
|
+
run: |
|
|
148
|
+
# Run tests inside container (assuming your Dockerfile includes uv)
|
|
149
|
+
docker run --rm python-app:latest uv run pytest tests/
|
|
150
|
+
- name: Collect logs and artifacts
|
|
151
|
+
if: always()
|
|
152
|
+
run: |
|
|
153
|
+
# Save container logs
|
|
154
|
+
docker logs python-app-container > container.log 2>&1
|
|
155
|
+
|
|
156
|
+
# Copy files from container if needed
|
|
157
|
+
docker cp python-app-container:/app/logs ./logs/ || true
|
|
158
|
+
docker cp python-app-container:/app/reports ./reports/ || true
|
|
159
|
+
- name: Upload logs as artifacts
|
|
160
|
+
if: always()
|
|
161
|
+
uses: actions/upload-artifact@v4
|
|
162
|
+
with:
|
|
163
|
+
name: application-logs-${{ github.sha }}
|
|
164
|
+
path: |
|
|
165
|
+
container.log
|
|
166
|
+
logs/
|
|
167
|
+
reports/
|
|
168
|
+
retention-days: 7
|
|
169
|
+
- name: Cleanup
|
|
170
|
+
if: always()
|
|
171
|
+
run: |
|
|
172
|
+
# Stop and remove container
|
|
173
|
+
docker stop python-app-container || true
|
|
174
|
+
docker rm python-app-container || true
|
|
175
|
+
|
|
176
|
+
# Remove images to save space (optional)
|
|
177
|
+
# docker rmi python-app:${{ github.sha }} || true
|
|
178
|
+
# docker rmi python-app:latest || true
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
name: Deploy AKS Cluster
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
paths:
|
|
8
|
+
- 'infra/azure/**'
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
env:
|
|
16
|
+
TERRAFORM_VERSION: '1.9.0'
|
|
17
|
+
WORKING_DIR: './infra/azure'
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
terraform:
|
|
21
|
+
name: Deploy AKS
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
|
|
24
|
+
steps:
|
|
25
|
+
- name: Checkout
|
|
26
|
+
uses: actions/checkout@v4
|
|
27
|
+
|
|
28
|
+
- name: Azure Login (OIDC)
|
|
29
|
+
uses: azure/login@v2
|
|
30
|
+
with:
|
|
31
|
+
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
|
32
|
+
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
|
33
|
+
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
|
34
|
+
|
|
35
|
+
- name: Setup Terraform
|
|
36
|
+
uses: hashicorp/setup-terraform@v3
|
|
37
|
+
with:
|
|
38
|
+
terraform_version: ${{ env.TERRAFORM_VERSION }}
|
|
39
|
+
|
|
40
|
+
- name: Terraform Init
|
|
41
|
+
working-directory: ${{ env.WORKING_DIR }}
|
|
42
|
+
run: terraform init
|
|
43
|
+
|
|
44
|
+
- name: Terraform Validate
|
|
45
|
+
working-directory: ${{ env.WORKING_DIR }}
|
|
46
|
+
run: terraform validate
|
|
47
|
+
|
|
48
|
+
- name: Terraform Plan
|
|
49
|
+
working-directory: ${{ env.WORKING_DIR }}
|
|
50
|
+
run: terraform plan -out=tfplan
|
|
51
|
+
|
|
52
|
+
- name: Terraform Apply
|
|
53
|
+
working-directory: ${{ env.WORKING_DIR }}
|
|
54
|
+
run: terraform apply -auto-approve tfplan
|
|
55
|
+
|
|
56
|
+
- name: Get Kubeconfig
|
|
57
|
+
run: |
|
|
58
|
+
az aks get-credentials \
|
|
59
|
+
--resource-group aks-devel-rg \
|
|
60
|
+
--name aks-devel \
|
|
61
|
+
--overwrite-existing
|
|
62
|
+
|
|
63
|
+
- name: Verify Cluster
|
|
64
|
+
run: kubectl get nodes
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
name: 'Terraform EKS Deployment'
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
paths:
|
|
8
|
+
- 'infra/aws/**'
|
|
9
|
+
pull_request:
|
|
10
|
+
branches:
|
|
11
|
+
- main
|
|
12
|
+
paths:
|
|
13
|
+
- 'infra/aws/**'
|
|
14
|
+
workflow_dispatch:
|
|
15
|
+
|
|
16
|
+
env:
|
|
17
|
+
TF_VERSION: '1.5.0'
|
|
18
|
+
AWS_REGION: 'eu-west-2'
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
terraform:
|
|
22
|
+
name: 'Terraform'
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
environment: production
|
|
25
|
+
|
|
26
|
+
# Use the Bash shell regardless of the GitHub Actions runner operating system
|
|
27
|
+
defaults:
|
|
28
|
+
run:
|
|
29
|
+
shell: bash
|
|
30
|
+
working-directory: ./infra/aws
|
|
31
|
+
|
|
32
|
+
steps:
|
|
33
|
+
# Checkout the repository to the GitHub Actions runner
|
|
34
|
+
- name: Checkout
|
|
35
|
+
uses: actions/checkout@v4
|
|
36
|
+
|
|
37
|
+
# Configure AWS credentials using GitHub secrets
|
|
38
|
+
- name: Configure AWS credentials
|
|
39
|
+
uses: aws-actions/configure-aws-credentials@v4
|
|
40
|
+
with:
|
|
41
|
+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
|
42
|
+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
|
43
|
+
aws-region: ${{ env.AWS_REGION }}
|
|
44
|
+
|
|
45
|
+
# Install the latest version of Terraform CLI
|
|
46
|
+
- name: Setup Terraform
|
|
47
|
+
uses: hashicorp/setup-terraform@v3
|
|
48
|
+
with:
|
|
49
|
+
terraform_version: ${{ env.TF_VERSION }}
|
|
50
|
+
|
|
51
|
+
# Initialize a new or existing Terraform working directory
|
|
52
|
+
- name: Terraform Init
|
|
53
|
+
run: terraform init
|
|
54
|
+
|
|
55
|
+
# Checks that all Terraform configuration files adhere to a canonical format
|
|
56
|
+
- name: Terraform Format
|
|
57
|
+
run: terraform fmt -check
|
|
58
|
+
|
|
59
|
+
# Import existing IAM roles if they exist
|
|
60
|
+
- name: Import Existing IAM Roles
|
|
61
|
+
continue-on-error: true
|
|
62
|
+
run: |
|
|
63
|
+
echo "🔄 Attempting to import existing IAM roles..."
|
|
64
|
+
terraform import aws_iam_role.eks_cluster devel-cluster-role || echo "eks_cluster role not found or already imported"
|
|
65
|
+
terraform import aws_iam_role.eks_nodes devel-nodes-role || echo "eks_nodes role not found or already imported"
|
|
66
|
+
echo "✅ Import attempt complete"
|
|
67
|
+
|
|
68
|
+
# Validates the configuration used in the GitHub action workflow
|
|
69
|
+
- name: Terraform Validate
|
|
70
|
+
run: terraform validate
|
|
71
|
+
|
|
72
|
+
# Generates an execution plan for Terraform
|
|
73
|
+
- name: Terraform Plan
|
|
74
|
+
run: terraform plan -no-color -input=false
|
|
75
|
+
continue-on-error: true
|
|
76
|
+
|
|
77
|
+
# Apply the configuration only on push to main branch or manual trigger
|
|
78
|
+
- name: Terraform Apply
|
|
79
|
+
if: (github.ref == 'refs/heads/main' && github.event_name == 'push') || github.event_name == 'workflow_dispatch'
|
|
80
|
+
run: terraform apply -auto-approve -input=false
|
|
81
|
+
# Output the kubeconfig command for easy access
|
|
82
|
+
- name: Output Kubeconfig Command
|
|
83
|
+
if: (github.ref == 'refs/heads/main' && github.event_name == 'push') || github.event_name == 'workflow_dispatch'
|
|
84
|
+
run: |
|
|
85
|
+
echo "To configure kubectl, run:"
|
|
86
|
+
terraform output -raw kubeconfig_command
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
name: 'Destroy AKS Infrastructure'
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
confirm_destroy:
|
|
7
|
+
description: 'Type "DESTROY" to confirm destruction'
|
|
8
|
+
required: true
|
|
9
|
+
type: string
|
|
10
|
+
cluster_name:
|
|
11
|
+
description: 'Cluster name to destroy (must match terraform variable)'
|
|
12
|
+
required: true
|
|
13
|
+
type: string
|
|
14
|
+
resource_group:
|
|
15
|
+
description: 'Resource group name (must match terraform variable)'
|
|
16
|
+
required: true
|
|
17
|
+
type: string
|
|
18
|
+
|
|
19
|
+
env:
|
|
20
|
+
TF_VERSION: '1.5.0'
|
|
21
|
+
ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
|
22
|
+
ARM_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
destroy:
|
|
26
|
+
name: 'Terraform Destroy'
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
environment: production
|
|
29
|
+
|
|
30
|
+
defaults:
|
|
31
|
+
run:
|
|
32
|
+
shell: bash
|
|
33
|
+
working-directory: infra/azure
|
|
34
|
+
|
|
35
|
+
steps:
|
|
36
|
+
- name: Checkout
|
|
37
|
+
uses: actions/checkout@v4
|
|
38
|
+
|
|
39
|
+
- name: Validate Destruction Confirmation
|
|
40
|
+
run: |
|
|
41
|
+
if [ "${{ github.event.inputs.confirm_destroy }}" != "DESTROY" ]; then
|
|
42
|
+
echo "❌ Destruction not confirmed. You must type 'DESTROY' exactly."
|
|
43
|
+
exit 1
|
|
44
|
+
fi
|
|
45
|
+
echo "✅ Destruction confirmed"
|
|
46
|
+
|
|
47
|
+
- name: Azure Login
|
|
48
|
+
uses: azure/login@v1
|
|
49
|
+
with:
|
|
50
|
+
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
|
51
|
+
|
|
52
|
+
- name: Setup Terraform
|
|
53
|
+
uses: hashicorp/setup-terraform@v3
|
|
54
|
+
with:
|
|
55
|
+
terraform_version: ${{ env.TF_VERSION }}
|
|
56
|
+
|
|
57
|
+
- name: Terraform Init
|
|
58
|
+
run: terraform init
|
|
59
|
+
env:
|
|
60
|
+
ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
|
|
61
|
+
ARM_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
|
|
62
|
+
|
|
63
|
+
- name: Verify Terraform Variables
|
|
64
|
+
run: |
|
|
65
|
+
echo "📝 Using existing terraform.tfvars:"
|
|
66
|
+
cat terraform.tfvars
|
|
67
|
+
echo ""
|
|
68
|
+
echo "🔍 Verifying cluster name and resource group match input:"
|
|
69
|
+
if grep -q "cluster_name.*=.*\"${{ github.event.inputs.cluster_name }}\"" terraform.tfvars; then
|
|
70
|
+
echo "✅ Cluster name matches terraform.tfvars"
|
|
71
|
+
else
|
|
72
|
+
echo "⚠️ Warning: Cluster name doesn't match terraform.tfvars"
|
|
73
|
+
fi
|
|
74
|
+
if grep -q "resource_group_name.*=.*\"${{ github.event.inputs.resource_group }}\"" terraform.tfvars; then
|
|
75
|
+
echo "✅ Resource group matches terraform.tfvars"
|
|
76
|
+
else
|
|
77
|
+
echo "⚠️ Warning: Resource group doesn't match terraform.tfvars"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
- name: Pre-cleanup Kubernetes Resources
|
|
81
|
+
continue-on-error: true
|
|
82
|
+
run: |
|
|
83
|
+
echo "🧹 Cleaning up Kubernetes resources..."
|
|
84
|
+
|
|
85
|
+
# Get AKS credentials
|
|
86
|
+
az aks get-credentials \
|
|
87
|
+
--resource-group ${{ github.event.inputs.resource_group }} \
|
|
88
|
+
--name ${{ github.event.inputs.cluster_name }} \
|
|
89
|
+
--overwrite-existing || {
|
|
90
|
+
echo "⚠️ Could not get AKS credentials. Cluster may not exist or is inaccessible."
|
|
91
|
+
exit 0
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
# Delete LoadBalancer services
|
|
95
|
+
echo "Deleting LoadBalancer services..."
|
|
96
|
+
kubectl get svc --all-namespaces -o json 2>/dev/null | \
|
|
97
|
+
jq -r '.items[] | select(.spec.type=="LoadBalancer") | "\(.metadata.namespace) \(.metadata.name)"' | \
|
|
98
|
+
while read namespace name; do
|
|
99
|
+
echo " Deleting: $namespace/$name"
|
|
100
|
+
kubectl delete svc "$name" -n "$namespace" --timeout=60s || true
|
|
101
|
+
done
|
|
102
|
+
|
|
103
|
+
# Delete PVCs
|
|
104
|
+
echo "Deleting PersistentVolumeClaims..."
|
|
105
|
+
kubectl delete pvc --all --all-namespaces --timeout=60s || true
|
|
106
|
+
|
|
107
|
+
echo "⏳ Waiting for Azure resources cleanup..."
|
|
108
|
+
sleep 30
|
|
109
|
+
|
|
110
|
+
- name: Terraform Plan Destroy
|
|
111
|
+
run: |
|
|
112
|
+
echo "📋 Resources that will be destroyed:"
|
|
113
|
+
terraform plan -destroy -no-color -input=false
|
|
114
|
+
env:
|
|
115
|
+
ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
|
|
116
|
+
ARM_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
|
|
117
|
+
|
|
118
|
+
- name: Terraform Destroy
|
|
119
|
+
run: |
|
|
120
|
+
echo "🚨 Starting infrastructure destruction..."
|
|
121
|
+
terraform destroy -auto-approve -input=false
|
|
122
|
+
echo "✅ Infrastructure destroyed successfully"
|
|
123
|
+
env:
|
|
124
|
+
ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
|
|
125
|
+
ARM_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
|
|
126
|
+
|
|
127
|
+
- name: Verify Cleanup
|
|
128
|
+
continue-on-error: true
|
|
129
|
+
run: |
|
|
130
|
+
echo "🔍 Verifying cleanup..."
|
|
131
|
+
|
|
132
|
+
echo "Checking for AKS clusters in resource group..."
|
|
133
|
+
az aks list --resource-group ${{ github.event.inputs.resource_group }} -o table || true
|
|
134
|
+
|
|
135
|
+
echo "Checking if resource group still exists..."
|
|
136
|
+
az group show --name ${{ github.event.inputs.resource_group }} -o table || echo "Resource group deleted"
|
|
137
|
+
|
|
138
|
+
echo "✅ Cleanup verification complete"
|