From 34f814c79e537609cd7f953d176bc9e8f17b00c2 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sat, 6 Dec 2025 16:26:35 -0500 Subject: [PATCH 01/61] initial test --- .github/workflows/_reusable-test.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/_reusable-test.yml b/.github/workflows/_reusable-test.yml index b3e78e042..a0ea1572b 100644 --- a/.github/workflows/_reusable-test.yml +++ b/.github/workflows/_reusable-test.yml @@ -75,7 +75,7 @@ jobs: with: fetch-depth: 3 - - name: Setup Python environment + - name: Setup Python environment with Mise if: ${{ matrix.experimental == false }} uses: ./.github/actions/setup-mise-env with: @@ -84,7 +84,7 @@ jobs: profile: "dev" skip-checkout: true id: setup-mise - - name: Run quality checks + - name: Run quality checks before tests if: ${{ inputs.run-quality-checks && matrix.experimental == false }} env: MISE_YES: 1 @@ -136,11 +136,10 @@ jobs: if: ${{ matrix.experimental == true }} shell: bash run: | - uv sync --no-extra --group test --resolution highest --frozen 2>&1 + uv sync --group test --resolution highest --frozen 2>&1 - name: Run test coverage for experimental Python if: ${{ matrix.experimental == true }} run: | export PATH="$HOME/.local/bin:$PATH" uv run -m pytest tests/ --cov=codeweaver --cov-report=xml --cov-report=term-missing --junit-xml=test-results.xml -v -m "${{ inputs.test-markers }}" - From 3b287ea3de1d708269cbea12413c0805ee358e6e Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sat, 6 Dec 2025 16:45:45 -0500 Subject: [PATCH 02/61] fix: enhance CI configuration with Python version support and Mise environment setup --- .github/workflows/ci.yml | 7 ++++++- .github/workflows/copilot-setup-steps.yml | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 04e681975..64253c1e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,6 +51,11 @@ jobs: CODEWEAVER_VECTOR_STORE_URL: ${{ secrets.CODEWEAVER_VECTOR_STORE_URL }} QDRANT__SERVICE__API_KEY: ${{ secrets.QDRANT__SERVICE__API_KEY }} VOYAGE_API_KEY: ${{ secrets.VOYAGE_API_KEY }} + with: + python-versions: '["3.12", "3.13", "3.14"]' + test-markers: "not docker and not qdrant and not dev_only and not skip_ci and not network and not external_api and not flaky" + upload-coverage: true + run-quality-checks: true lint: name: Lint @@ -63,4 +68,4 @@ jobs: - test - lint uses: ./.github/workflows/_reusable-build.yml - # No secrets needed for build job + # Build doesn't need secrets. diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index 5651e67fb..ecd36a083 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -60,3 +60,21 @@ jobs: run: | chmod -R +x scripts chmod -R +x mise-tasks + - name: Setup Mise Environment + uses: ./.github/actions/setup-mise-env + with: + python-version: "3.13" + github-token: ${{ secrets.GITHUB_TOKEN }} + profile: "dev" + skip-checkout: "true" + id: setup-mise + - name: Verify Mise Setup + shell: bash + env: + MISE_PYTHON: "3.13" + MISE_YES: 1 + MISE_EXPERIMENTAL: 1 + MISE_PATH: ${{ steps.setup-mise.outputs.MISE_PATH }} + run: | + mise --version || echo "Mise not in path" || "$MISE_PATH" --version + echo "Mise Python:" From 036b74b59ced069b8c16ca1287d64041392671d7 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sat, 6 Dec 2025 16:48:34 -0500 Subject: [PATCH 03/61] fix: enhance CI configuration with Python version support and Mise environment setup --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 64253c1e1..c2cdf8834 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,7 +52,6 @@ jobs: QDRANT__SERVICE__API_KEY: ${{ secrets.QDRANT__SERVICE__API_KEY }} VOYAGE_API_KEY: ${{ secrets.VOYAGE_API_KEY }} with: - python-versions: '["3.12", "3.13", "3.14"]' test-markers: "not docker and not qdrant and not dev_only and not skip_ci and not network and not external_api and not flaky" upload-coverage: true run-quality-checks: true From f48671c6d20eabd8f21afca0cffe5125d9ef7c8a Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 6 Dec 2025 22:08:18 +0000 Subject: [PATCH 04/61] fix: prevent CI skip by disabling env export in mise-action The mise-action was hanging during the "Exporting mise environment variables" step, causing the runner to kill the job with exit code 137 (SIGKILL). This was happening because: 1. The mise.toml has complex template expressions with command executions 2. The hooks.enter configuration may execute during env export 3. The env export was timing out after ~1 minute Solution: Disable the env parameter (set to false) in all mise-action configurations to prevent the hanging during environment variable export. Fixes #issue --- .github/actions/setup-mise-env/action.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 386b88f9b..481418353 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -57,6 +57,7 @@ runs: install: true cache: true cache_key_prefix: ${{ inputs.profile }} + env: false id: mise-setup-minimal - name: Setup Mise for Reviewer Profile if: inputs.profile == 'reviewer' @@ -72,6 +73,7 @@ runs: install: true cache: true cache_key_prefix: ${{ inputs.profile }} + env: false - name: Activate Reviewer Profile Environment if: inputs.profile == 'reviewer' shell: bash @@ -92,6 +94,7 @@ runs: install: true cache: true cache_key_prefix: ${{ inputs.profile }} + env: false id: mise-setup-dev - name: Set outputs From 596900d26e6a24d90e45c869698a21f8349dcaa2 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sat, 6 Dec 2025 17:15:12 -0500 Subject: [PATCH 05/61] fix: remove unnecessary echo statement for Mise Python version in CI setup --- .github/workflows/copilot-setup-steps.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index ecd36a083..e7f009dd2 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -77,4 +77,3 @@ jobs: MISE_PATH: ${{ steps.setup-mise.outputs.MISE_PATH }} run: | mise --version || echo "Mise not in path" || "$MISE_PATH" --version - echo "Mise Python:" From 5cbce61ce985078da8a75a54064d76d7d404ec92 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 6 Dec 2025 22:20:56 +0000 Subject: [PATCH 06/61] fix: add mise bin directory to PATH for proper command execution The previous fix disabled env export to prevent hanging, but this caused MISE_PATH to be empty because mise wasn't in the PATH. Changes: 1. Add mise bin directory to PATH in "Set outputs" step 2. Add mise bin directory to PATH in workflow steps that execute mise commands This ensures: - The "Set outputs" step can find mise using which - Workflow steps can execute mise commands via $MISE_PATH - No hanging during env export (env: false is still set) Fixes the "command not found" error when running mise commands. --- .github/actions/setup-mise-env/action.yml | 2 ++ .github/workflows/_reusable-test.yml | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 481418353..74ac44427 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -101,6 +101,8 @@ runs: shell: bash id: mise-outputs run: | + # Add mise to PATH since env export is disabled + export PATH="$HOME/.local/share/mise/bin:$PATH" echo "MISE_PATH=$(which mise)" >> $GITHUB_OUTPUT echo "MISE_ENV=$MISE_ENV" >> $GITHUB_OUTPUT echo "PROFILE=${{ inputs.profile }}" >> $GITHUB_OUTPUT diff --git a/.github/workflows/_reusable-test.yml b/.github/workflows/_reusable-test.yml index b3e78e042..4a26b2636 100644 --- a/.github/workflows/_reusable-test.yml +++ b/.github/workflows/_reusable-test.yml @@ -93,7 +93,7 @@ jobs: MISE_EXPERIMENTAL: 1 MISE_PATH: ${{ steps.setup-mise.outputs.MISE_PATH }} run: | - export PATH="$HOME/.local/bin:$PATH" + export PATH="$HOME/.local/share/mise/bin:$HOME/.local/bin:$PATH" "$MISE_PATH" //:check 2>&1 continue-on-error: true - name: Run tests with coverage @@ -105,7 +105,7 @@ jobs: MISE_EXPERIMENTAL: 1 MISE_PATH: ${{ steps.setup-mise.outputs.MISE_PATH }} run: | - export PATH="$HOME/.local/bin:$PATH" + export PATH="$HOME/.local/share/mise/bin:$HOME/.local/bin:$PATH" "$MISE_PATH" //:test-cov -m "${{ inputs.test-markers }}" - name: Upload coverage to Codecov if: ${{ inputs.upload-coverage && matrix.python-version == '3.12' }} From 9dfdd3c486c907ecddd2c39eb370e1a08ae0414e Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 6 Dec 2025 22:26:10 +0000 Subject: [PATCH 07/61] fix: add outputs section to composite action for proper output exposure The composite action was setting outputs in the mise-outputs step, but those outputs were not being exposed by the action itself because the action.yml was missing the outputs section. Changes: - Add outputs section to action.yml defining all output variables - Map outputs from mise-outputs step to action outputs This ensures that steps.setup-mise.outputs.MISE_PATH and other outputs are properly available to the calling workflow. Related to the CI skip issue fix. --- .github/actions/setup-mise-env/action.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 74ac44427..a8781bbb8 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -28,6 +28,23 @@ inputs: required: true default: 'minimal' +outputs: + MISE_PATH: + description: Path to mise executable + value: ${{ steps.mise-outputs.outputs.MISE_PATH }} + MISE_ENV: + description: Mise environment name + value: ${{ steps.mise-outputs.outputs.MISE_ENV }} + PROFILE: + description: Profile used for setup + value: ${{ steps.mise-outputs.outputs.PROFILE }} + PYTHON_VERSION: + description: Python version installed + value: ${{ steps.mise-outputs.outputs.PYTHON_VERSION }} + PYTHON_PATH: + description: Path to Python executable + value: ${{ steps.mise-outputs.outputs.PYTHON_PATH }} + runs: using: composite steps: From fb5ad88d1d57bbbcc2ff96eaf93a3973c137fc5e Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sat, 6 Dec 2025 17:35:28 -0500 Subject: [PATCH 08/61] fix: missing tools on path --- .github/actions/setup-mise-env/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index a8781bbb8..3a032eaaa 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -119,7 +119,7 @@ runs: id: mise-outputs run: | # Add mise to PATH since env export is disabled - export PATH="$HOME/.local/share/mise/bin:$PATH" + export PATH="$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" echo "MISE_PATH=$(which mise)" >> $GITHUB_OUTPUT echo "MISE_ENV=$MISE_ENV" >> $GITHUB_OUTPUT echo "PROFILE=${{ inputs.profile }}" >> $GITHUB_OUTPUT From 147548c77c16bb5b5dc37c91376d048208d1e412 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> Date: Sat, 6 Dec 2025 17:46:55 -0500 Subject: [PATCH 09/61] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> --- .github/actions/setup-mise-env/action.yml | 2 +- .github/workflows/copilot-setup-steps.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 3a032eaaa..8f88b9bcf 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -121,7 +121,7 @@ runs: # Add mise to PATH since env export is disabled export PATH="$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" echo "MISE_PATH=$(which mise)" >> $GITHUB_OUTPUT - echo "MISE_ENV=$MISE_ENV" >> $GITHUB_OUTPUT + echo "MISE_ENV=${MISE_ENV:-}" >> $GITHUB_OUTPUT echo "PROFILE=${{ inputs.profile }}" >> $GITHUB_OUTPUT echo "PYTHON_VERSION=$(python --version | awk '{print $2}')" >> $GITHUB_OUTPUT echo "PYTHON_PATH=$(which python)" >> $GITHUB_OUTPUT diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index e7f009dd2..2f0da4588 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -76,4 +76,4 @@ jobs: MISE_EXPERIMENTAL: 1 MISE_PATH: ${{ steps.setup-mise.outputs.MISE_PATH }} run: | - mise --version || echo "Mise not in path" || "$MISE_PATH" --version + mise --version || { echo "Mise not in path"; "$MISE_PATH" --version; } From a6397861bf3ef3417a24fa8d6c490adafb24d5e8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 6 Dec 2025 22:50:55 +0000 Subject: [PATCH 10/61] Initial plan From eae8605933d131dcb15b764539c16622cd500181 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 6 Dec 2025 22:55:32 +0000 Subject: [PATCH 11/61] fix: remove duplicate Setup Mise Environment step Remove the first instance of "Setup Mise Environment" step (lines 52-58) as it was a duplicate. The second instance with id: setup-mise is kept since it's needed for the Verify Mise Setup step that references it. Co-authored-by: bashandbone <89049923+bashandbone@users.noreply.github.com> --- .github/workflows/copilot-setup-steps.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index 2f0da4588..2e6a7164e 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -49,13 +49,6 @@ jobs: fetch-depth: 2 - name: Free up disk space run: ./scripts/dev-env/ci-free-disk-space.sh - - name: Setup Mise Environment - uses: ./.github/actions/setup-mise-env - with: - python-version: "3.13" - github-token: ${{ secrets.GITHUB_TOKEN }} - profile: "dev" - skip-checkout: "true" - name: Make scripts executable run: | chmod -R +x scripts From db32aad7e95584384ef075fc3d9811923b2a8a13 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sat, 6 Dec 2025 21:52:11 -0500 Subject: [PATCH 12/61] fix: update PATH in workflows and improve MCP Registry submission process --- .github/actions/setup-mise-env/action.yml | 2 - .github/workflows/_reusable-lint.yml | 4 +- .github/workflows/_reusable-test.yml | 6 +- .github/workflows/claude.yml | 1 + .github/workflows/copilot-setup-steps.yml | 1 + .github/workflows/mcp-registry-submit.yml | 246 +++++++--------------- .github/workflows/release.yml | 4 +- 7 files changed, 90 insertions(+), 174 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 8f88b9bcf..319070f4b 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -125,5 +125,3 @@ runs: echo "PROFILE=${{ inputs.profile }}" >> $GITHUB_OUTPUT echo "PYTHON_VERSION=$(python --version | awk '{print $2}')" >> $GITHUB_OUTPUT echo "PYTHON_PATH=$(which python)" >> $GITHUB_OUTPUT - - diff --git a/.github/workflows/_reusable-lint.yml b/.github/workflows/_reusable-lint.yml index 50e5299a3..7e5bb283f 100644 --- a/.github/workflows/_reusable-lint.yml +++ b/.github/workflows/_reusable-lint.yml @@ -53,7 +53,7 @@ jobs: MISE_EXPERIMENTAL: 1 PYTHON_PATH: ${{ steps.mise-outputs.outputs.PYTHON_PATH }} run: | - export PATH="$HOME/.local/bin:$PATH" + export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" mise //:lint || echo "::warning::Lint checks failed but allowing workflow to continue" continue-on-error: true @@ -66,6 +66,6 @@ jobs: MISE_EXPERIMENTAL: 1 PYTHON_PATH: ${{ steps.mise-outputs.outputs.PYTHON_PATH }} run: | - export PATH="$HOME/.local/bin:$PATH" + export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" mise //:format || echo "::warning::License checks or formatting checks failed but allowing workflow to continue" continue-on-error: true diff --git a/.github/workflows/_reusable-test.yml b/.github/workflows/_reusable-test.yml index 760e60a9c..535f21fcf 100644 --- a/.github/workflows/_reusable-test.yml +++ b/.github/workflows/_reusable-test.yml @@ -93,7 +93,7 @@ jobs: MISE_EXPERIMENTAL: 1 MISE_PATH: ${{ steps.setup-mise.outputs.MISE_PATH }} run: | - export PATH="$HOME/.local/share/mise/bin:$HOME/.local/bin:$PATH" + export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" "$MISE_PATH" //:check 2>&1 continue-on-error: true - name: Run tests with coverage @@ -105,7 +105,7 @@ jobs: MISE_EXPERIMENTAL: 1 MISE_PATH: ${{ steps.setup-mise.outputs.MISE_PATH }} run: | - export PATH="$HOME/.local/share/mise/bin:$HOME/.local/bin:$PATH" + export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" "$MISE_PATH" //:test-cov -m "${{ inputs.test-markers }}" - name: Upload coverage to Codecov if: ${{ inputs.upload-coverage && matrix.python-version == '3.12' }} @@ -141,5 +141,5 @@ jobs: - name: Run test coverage for experimental Python if: ${{ matrix.experimental == true }} run: | - export PATH="$HOME/.local/bin:$PATH" + export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" uv run -m pytest tests/ --cov=codeweaver --cov-report=xml --cov-report=term-missing --junit-xml=test-results.xml -v -m "${{ inputs.test-markers }}" diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index fde6b9af6..036145d57 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -61,6 +61,7 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} profile: "reviewer" skip-checkout: "true" + - name: PR Review if: github.event_name == 'pull_request_review' uses: anthropics/claude-code-action@e8bad572273ce919ba15fec95aef0ce974464753 diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index 2e6a7164e..61324ec86 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -69,4 +69,5 @@ jobs: MISE_EXPERIMENTAL: 1 MISE_PATH: ${{ steps.setup-mise.outputs.MISE_PATH }} run: | + export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" mise --version || { echo "Mise not in path"; "$MISE_PATH" --version; } diff --git a/.github/workflows/mcp-registry-submit.yml b/.github/workflows/mcp-registry-submit.yml index 9b85ca145..785d16107 100644 --- a/.github/workflows/mcp-registry-submit.yml +++ b/.github/workflows/mcp-registry-submit.yml @@ -29,17 +29,14 @@ jobs: uses: actions/checkout@b3498302c5c423fa896b97a26bb183df735d08f8 with: ref: ${{ github.event.release.tag_name || github.ref }} + fetch-depth: 1 - - name: Set up Python - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c + - name: Install uv + uses: ./.github/actions/setup-uv-env with: python-version: "3.12" - - - name: Install uv - run: | - curl -LsSf "https://astral.sh/uv/install.sh" | sh - echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" - + github-token: ${{ secrets.GITHUB_TOKEN }} + id: uv-setup - name: Extract version information id: version run: | @@ -64,90 +61,7 @@ jobs: # Run the generation script (uses PEP 723 dependencies) uv run scripts/build/generate-mcp-server-json.py - - # Update version in generated server.json - python -c " - import json - - with open('server.json', 'r') as f: - data = json.load(f) - - # Update top-level version - data['version'] = '${VERSION}' - - # Update package versions - if 'packages' in data: - for pkg in data['packages']: - pkg['version'] = '${VERSION}' - - with open('server.json', 'w') as f: - json.dump(data, f, indent=2) - - print(f'✓ Regenerated and versioned server.json to ${VERSION}') - " - - - name: Update tools.json with release version - run: | - VERSION="${{ steps.version.outputs.version }}" - # Update the version fields in tools.json - python -c " - import json - import sys - - with open('tools.json', 'r') as f: - tools_data = json.load(f) - - # Update top-level version - tools_data['version'] = '${VERSION}' - # Update server version if present - if 'server' in tools_data: - tools_data['server']['version'] = '${VERSION}' - - with open('tools.json', 'w') as f: - json.dump(tools_data, f, indent=2) - - print(f'Updated tools.json to version ${VERSION}') - " - - - name: Validate server.json format - run: | - python -c " - import json - import sys - - try: - with open('server.json', 'r') as f: - data = json.load(f) - - # Basic validation checks - required_fields = ['name', 'description', 'version'] - missing = [f for f in required_fields if f not in data] - - if missing: - print(f'ERROR: Missing required fields: {missing}') - sys.exit(1) - - # Validate name format (must be namespace/server-name) - if '/' not in data['name']: - print('ERROR: name must be in format namespace/server-name') - sys.exit(1) - - # Validate packages or remotes exist - if 'packages' not in data and 'remotes' not in data: - print('ERROR: Must have either packages or remotes array') - sys.exit(1) - - print('✓ server.json validation passed') - print(f' Name: {data[\"name\"]}') - print(f' Version: {data[\"version\"]}') - print(f' Description: {data[\"description\"][:80]}...') - - except json.JSONDecodeError as e: - print(f'ERROR: Invalid JSON in server.json: {e}') - sys.exit(1) - except Exception as e: - print(f'ERROR: Validation failed: {e}') - sys.exit(1) + echo "✓ server.json regenerated " - name: Wait for PyPI package availability @@ -201,48 +115,38 @@ jobs: - name: Install mcp-publisher CLI env: - MCP_PUBLISHER_VERSION: "v1.0.0" + MCP_PUBLISHER_VERSION: "v1.3.10" run: | ARCH="$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')" OS="$(uname -s | tr '[:upper:]' '[:lower:]')" - VERSION="${MCP_PUBLISHER_VERSION:- v1.0.0}" - NO_V_VERSION="${VERSION#v}" - + VERSION="${MCP_PUBLISHER_VERSION:- v1.3.10}" + # TODO: I don't know why we're doing all this to get and use the CLI when we could use the api directly echo "Downloading mcp-publisher ${VERSION} for ${OS}/${ARCH}..." - curl -L "https://github.com/modelcontextprotocol/registry/releases/download/${VERSION}/mcp-publisher_${NO_V_VERSION}_${OS}_${ARCH}.tar.gz" \ - -o mcp-publisher.tar.gz - curl -L "https://github.com/modelcontextprotocol/registry/releases/download/${VERSION}/mcp-publisher_${NO_V_VERSION}_${OS}_${ARCH}.tar.gz.sha256" \ - -o mcp-publisher.tar.gz.sha256 - - echo "Verifying checksum for mcp-publisher.tar.gz..." - if ! sha256sum -c mcp-publisher.tar.gz.sha256; then - echo "ERROR: Checksum verification failed for mcp-publisher.tar.gz" + assets="$(curl -L \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer " \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/OWNER/REPO/releases/latest)" + our_index="$(echo "$assets" | jq -r '.assets[].name' | grep -n "^mcp-publisher_${OS}_${ARCH}.tar.gz$" | cut -d: -f1)" + asset="$(echo "$assets" | jq -r ".assets[$((our_index - 1))]")" + download_url="$(echo "$asset" | jq -r '.browser_download_url')" + digest="$(echo "$asset" | jq -r '.digest' | cut -d: -f2)" + curl -L -o mcp-publisher.tar.gz "$download_url" + downloaded_digest="$(sha256sum mcp-publisher.tar.gz | awk '{print $1}')" + if [ "$digest" != "$downloaded_digest" ]; then + echo "ERROR: Checksum verification failed for mcp-publisher" + echo "Expected: $digest" + echo "Got: $downloaded_digest" exit 1 fi - tar xz < mcp-publisher.tar.gz mcp-publisher sudo mv mcp-publisher /usr/local/bin/ chmod +x /usr/local/bin/mcp-publisher - rm mcp-publisher.tar.gz mcp-publisher.tar.gz.sha256 + rm mcp-publisher.tar.gz echo "✓ mcp-publisher installed" mcp-publisher --version || echo "Version check not available" - - name: Validate server.json with mcp-publisher - run: | - echo "Validating server.json against MCP schema..." - - # mcp-publisher validate should validate the server.json - # Note: exact command may vary based on mcp-publisher version - if command -v mcp-publisher &> /dev/null; then - mcp-publisher validate server.json || { - echo "ERROR: server.json validation failed" - exit 1 - } - else - echo "WARNING: mcp-publisher validate command not available, skipping" - fi - - name: Submit to MCP Registry env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -250,52 +154,62 @@ jobs: run: | echo "Submitting to MCP Registry..." - # Note: The exact submission process depends on mcp-publisher CLI implementation - # and may require manual intervention if the API/CLI has changed. - # The following attempts multiple submission methods in order of preference. - MESSAGE="" - # login to mcp-publisher - if command -v mcp-publisher &> /dev/null; then - echo "Logging in to mcp-publisher..." - mcp-publisher login dns --domain knitli.com --private-key "${MCP_REGISTRY_KEY}" || { - echo "WARNING: mcp-publisher login failed, proceeding without login" - } - MESSAGE="$(mcp-publisher publish)" - else - echo "WARNING: mcp-publisher CLI not available, skipping login" - fi - if [ -n "$MESSAGE" ] && [[ "$MESSAGE" == *Successfully* ]]; then - echo "✓ Successfully submitted to MCP Registry via mcp-publisher" - echo "$MESSAGE" - exit 0 - else - RESPONSE="$(curl -X POST \ - -H "Authorization: Bearer ${GITHUB_TOKEN}" \ - -H "Content-Type: application/json" \ - -d @server.json \ - -w "\n%{http_code}" \ - https://registry.modelcontextprotocol.io/v0/servers 2>&1)" + # we need to login with our domain key first + # the request has three fields: domain (knitli.com), signed_timestamp (hex encoded signature), timestamp (RFC3339) + # we need to sign the timestamp with the private key, which is in MCP_REGISTRY_KEY + # MCP_REGISTRY_KEY is expected to be in PEM format, and it uses ed25519 algorithm + # unfortunately, pkeyutl can only work with files because of how it has to buffer the input for signing - HTTP_CODE="$(echo "$RESPONSE" | tail -n 1)" - BODY="$(echo "$RESPONSE" | head -n -1)" + domain="knitli.com" + indata="$(mktemp)" + echo -n "$(date -u +"%Y-%m-%dT%+H:%+M:%+SZ")" > "$indata" - if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "201" ]; then - echo "✓ Successfully submitted to MCP Registry (HTTP ${HTTP_CODE})" - exit 0 - else - # Submission failed - provide helpful error message - echo "ERROR: Failed to submit to MCP Registry (HTTP ${HTTP_CODE})" - echo "Response: ${BODY}" - echo "" - echo "This may require manual submission via:" - echo " 1. The registry web interface at https://registry.modelcontextprotocol.io" - echo " 2. The mcp-publisher CLI tool" - echo " 3. Contact registry maintainers for assistance" - exit 1 - fi + key_file="$(mktemp)" + echo "$MCP_REGISTRY_KEY" > "$key_file" + chmod 600 "$key_file" + outfile="$(mktemp)" + + openssl pkeyutl -sign -inkey "$key_file" -out "$outfile" -rawin -in "$indata" + signed_timestamp_hex="$(xxd -p "$outfile" | tr -d '\n')" + request_body="$(mktemp)" + { + echo -n '{"domain":"'"$domain"'",' + echo -n '"signed_timestamp":"'"$signed_timestamp_hex"'",' + echo -n '"timestamp":"'"$(cat "$indata")"'"}' + } > "$request_body" + echo "Logging in to MCP Registry..." + response="$(curl --request POST \ + --url "https://registry.modelcontextprotocol.io/v0.1/auth/dns" \ + --header "Accept: application/json, application/problem+json" \ + --header "Content-Type: application/json" \ + --data @"$request_body")" + token="$(echo "$response" | jq -r '.registry_token')" + rm "$indata" "$key_file" "$outfile" + rm "$request_body" + if [ -z "$token" ] || [ "$token" = "null" ]; then + echo "ERROR: Failed to obtain registry token" + echo "Response: $response" + exit 1 fi + echo "✓ Obtained registry token" + export MCP_LOGIN_TOKEN="$token" + publication_response="$(curl --request POST \ + --url https://registry.modelcontextprotocol.io/v0.1/publish \ + --header 'Accept: application/json, application/problem+json' \ + --header "Authorization: Bearer $MCP_LOGIN_TOKEN" \ + --header 'Content-Type: application/json' \ + --data @./server.json)" + echo "Publication response: $publication_response" + publication_time="$(echo "$publication_response" | jq -r '._meta."io.modelcontextprotocol.registry/official".published_at')" + if [ -z "$publication_time" ] || [ "$publication_time" = "null" ]; then + echo "ERROR: Submission to MCP Registry failed" + exit 1 + fi + echo "✓ Successfully submitted to MCP Registry at $publication_time" + export "MCP_PUBLICATION_TIME"="$publication_time" + exit 0 - - name: Summary + - name: Summary of MCP Registry Submission if: always() run: | { @@ -303,6 +217,9 @@ jobs: echo "" echo "- **Version**: ${{ steps.version.outputs.version }}" echo "- **Status**: ${{ job.status }}" + if [ -n "$MCP_PUBLICATION_TIME" ]; then + echo "- **Published At**: $MCP_PUBLICATION_TIME" + fi echo "" } >> "$GITHUB_STEP_SUMMARY" @@ -310,13 +227,12 @@ jobs: { echo "✅ Successfully submitted to MCP Registry" echo "" - echo "View your server at: https://registry.modelcontextprotocol.io/servers/com.knitli/codeweaver" + echo "View your server at: https://registry.modelcontextprotocol.io/v0.1/servers/com.knitli%2Fcodeweaver/versions/${{ steps.version.outputs.version }}" } >> "$GITHUB_STEP_SUMMARY" else { echo "❌ Submission failed" echo "" echo "Please check the workflow logs for details." - echo "You may need to submit manually at: https://registry.modelcontextprotocol.io" } >> "$GITHUB_STEP_SUMMARY" fi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6205d2f94..289a74129 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,8 +32,8 @@ jobs: if: github.event_name == 'workflow_dispatch' || github.event_name == 'release' uses: ./.github/workflows/_reusable-test.yml with: - python-versions: '["3.12", "3.13"]' - test-markers: "not docker and not qdrant and not dev_only and not skip_ci and not network and not external_api" + python-versions: '["3.12", "3.13", "3.14"]' + test-markers: "not docker and not qdrant and not dev_only and not skip_ci and not network and not external_api and not flaky" upload-coverage: false run-quality-checks: true secrets: inherit From 7631fdc1c581271bc6b08e1a2bf33a91cc6db5f6 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sat, 6 Dec 2025 22:05:46 -0500 Subject: [PATCH 13/61] fix: removed 'frozen' flag from uv for experimental python installs. This was preventing package resolution --- .github/workflows/_reusable-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/_reusable-test.yml b/.github/workflows/_reusable-test.yml index 535f21fcf..cdcb6dfc7 100644 --- a/.github/workflows/_reusable-test.yml +++ b/.github/workflows/_reusable-test.yml @@ -136,7 +136,7 @@ jobs: if: ${{ matrix.experimental == true }} shell: bash run: | - uv sync --group test --resolution highest --frozen 2>&1 + uv sync --group test --resolution highest 2>&1 - name: Run test coverage for experimental Python if: ${{ matrix.experimental == true }} From 38d05088cda5d7acef14a1fa80e2793fffef1053 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> Date: Sat, 6 Dec 2025 22:18:11 -0500 Subject: [PATCH 14/61] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> --- .github/workflows/mcp-registry-submit.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/mcp-registry-submit.yml b/.github/workflows/mcp-registry-submit.yml index 785d16107..9e54e108a 100644 --- a/.github/workflows/mcp-registry-submit.yml +++ b/.github/workflows/mcp-registry-submit.yml @@ -61,8 +61,7 @@ jobs: # Run the generation script (uses PEP 723 dependencies) uv run scripts/build/generate-mcp-server-json.py - echo "✓ server.json regenerated - " + echo "✓ server.json regenerated" - name: Wait for PyPI package availability run: | @@ -162,7 +161,7 @@ jobs: domain="knitli.com" indata="$(mktemp)" - echo -n "$(date -u +"%Y-%m-%dT%+H:%+M:%+SZ")" > "$indata" + echo -n "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" > "$indata" key_file="$(mktemp)" echo "$MCP_REGISTRY_KEY" > "$key_file" @@ -206,7 +205,7 @@ jobs: exit 1 fi echo "✓ Successfully submitted to MCP Registry at $publication_time" - export "MCP_PUBLICATION_TIME"="$publication_time" + export MCP_PUBLICATION_TIME="$publication_time" exit 0 - name: Summary of MCP Registry Submission From 6092ce7d458e9149f889632e747c2ffeee012942 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sat, 6 Dec 2025 22:21:46 -0500 Subject: [PATCH 15/61] fix: remove mcp-publisher CLI installation step and streamline submission process --- .github/workflows/mcp-registry-submit.yml | 42 +++-------------------- 1 file changed, 4 insertions(+), 38 deletions(-) diff --git a/.github/workflows/mcp-registry-submit.yml b/.github/workflows/mcp-registry-submit.yml index 9e54e108a..9488cc0dd 100644 --- a/.github/workflows/mcp-registry-submit.yml +++ b/.github/workflows/mcp-registry-submit.yml @@ -112,44 +112,11 @@ jobs: echo "Please verify that the package was successfully published" exit 1 - - name: Install mcp-publisher CLI - env: - MCP_PUBLISHER_VERSION: "v1.3.10" - run: | - ARCH="$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')" - OS="$(uname -s | tr '[:upper:]' '[:lower:]')" - VERSION="${MCP_PUBLISHER_VERSION:- v1.3.10}" - # TODO: I don't know why we're doing all this to get and use the CLI when we could use the api directly - echo "Downloading mcp-publisher ${VERSION} for ${OS}/${ARCH}..." - assets="$(curl -L \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer " \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - https://api.github.com/repos/OWNER/REPO/releases/latest)" - our_index="$(echo "$assets" | jq -r '.assets[].name' | grep -n "^mcp-publisher_${OS}_${ARCH}.tar.gz$" | cut -d: -f1)" - asset="$(echo "$assets" | jq -r ".assets[$((our_index - 1))]")" - download_url="$(echo "$asset" | jq -r '.browser_download_url')" - digest="$(echo "$asset" | jq -r '.digest' | cut -d: -f2)" - curl -L -o mcp-publisher.tar.gz "$download_url" - downloaded_digest="$(sha256sum mcp-publisher.tar.gz | awk '{print $1}')" - if [ "$digest" != "$downloaded_digest" ]; then - echo "ERROR: Checksum verification failed for mcp-publisher" - echo "Expected: $digest" - echo "Got: $downloaded_digest" - exit 1 - fi - tar xz < mcp-publisher.tar.gz mcp-publisher - sudo mv mcp-publisher /usr/local/bin/ - chmod +x /usr/local/bin/mcp-publisher - rm mcp-publisher.tar.gz - - echo "✓ mcp-publisher installed" - mcp-publisher --version || echo "Version check not available" - - name: Submit to MCP Registry env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} MCP_REGISTRY_KEY: ${{ secrets.MCP_REGISTRY_KEY }} + id: submit-mcp run: | echo "Submitting to MCP Registry..." @@ -183,8 +150,7 @@ jobs: --header "Content-Type: application/json" \ --data @"$request_body")" token="$(echo "$response" | jq -r '.registry_token')" - rm "$indata" "$key_file" "$outfile" - rm "$request_body" + rm "$indata" "$key_file" "$outfile" "$request_body" if [ -z "$token" ] || [ "$token" = "null" ]; then echo "ERROR: Failed to obtain registry token" echo "Response: $response" @@ -205,7 +171,7 @@ jobs: exit 1 fi echo "✓ Successfully submitted to MCP Registry at $publication_time" - export MCP_PUBLICATION_TIME="$publication_time" + echo "MCP_PUBLICATION_TIME=$publication_time" >> "$GITHUB_OUTPUT" exit 0 - name: Summary of MCP Registry Submission @@ -217,7 +183,7 @@ jobs: echo "- **Version**: ${{ steps.version.outputs.version }}" echo "- **Status**: ${{ job.status }}" if [ -n "$MCP_PUBLICATION_TIME" ]; then - echo "- **Published At**: $MCP_PUBLICATION_TIME" + echo "- **Published At**: ${{ steps.submit-mcp.outputs.MCP_PUBLICATION_TIME }}" fi echo "" } >> "$GITHUB_STEP_SUMMARY" From 9508d15f3ac0c2c6fc9c0933f4412eef928154e9 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sat, 6 Dec 2025 23:32:09 -0500 Subject: [PATCH 16/61] fix: enhance CI workflows by adding outputs and environment variables for better integration and testing --- .github/actions/setup-uv-env/action.yml | 8 ++++ .github/workflows/_reusable-build.yml | 5 ++- .github/workflows/_reusable-lint.yml | 35 ++++++++-------- .github/workflows/_reusable-test.yml | 50 +++++++++++------------ .github/workflows/claude.yml | 41 ++++++++++--------- .github/workflows/copilot-setup-steps.yml | 8 ++++ .github/workflows/mcp-registry-submit.yml | 4 +- .github/workflows/release.yml | 4 ++ 8 files changed, 89 insertions(+), 66 deletions(-) diff --git a/.github/actions/setup-uv-env/action.yml b/.github/actions/setup-uv-env/action.yml index 918113526..a5972c170 100644 --- a/.github/actions/setup-uv-env/action.yml +++ b/.github/actions/setup-uv-env/action.yml @@ -28,6 +28,14 @@ inputs: required: false default: 'false' +outputs: + UV_PATH: + description: Path to uv executable + value: ${{ steps.uv-outputs.outputs.UV_PATH }} + UVX_PATH: + description: Path to uvx executable + value: ${{ steps.uv-outputs.outputs.UVX_PATH }} + runs: using: composite steps: diff --git a/.github/workflows/_reusable-build.yml b/.github/workflows/_reusable-build.yml index a3f0346f8..b59641359 100644 --- a/.github/workflows/_reusable-build.yml +++ b/.github/workflows/_reusable-build.yml @@ -33,13 +33,15 @@ jobs: build: name: Build Package runs-on: ubuntu-latest + env: + UV_PYTHON: ${{ inputs.python-version }} permissions: contents: read steps: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 with: - fetch-depth: 0 + fetch-depth: 2 - name: Setup UV and build uses: ./.github/actions/setup-uv-env @@ -54,7 +56,6 @@ jobs: - name: Build package with UV env: UV_PATH: ${{ steps.setup-uv.outputs.uv-path }} - UV_PYTHON: ${{ inputs.python-version }} run: | if [ "${{ inputs.clean-build }}" = "true" ]; then "$UV_PATH" build --clear diff --git a/.github/workflows/_reusable-lint.yml b/.github/workflows/_reusable-lint.yml index 7e5bb283f..066b90456 100644 --- a/.github/workflows/_reusable-lint.yml +++ b/.github/workflows/_reusable-lint.yml @@ -21,15 +21,21 @@ on: type: boolean default: true +env: + MISE_EXPERIMENTAL: 1 + MISE_YES: 1 + PROFILE: "reviewer" + jobs: lint: permissions: contents: read name: Lint and Format - runs-on: ubuntu-latest env: - MISE_ENV: ci - MISE_EXPERIMENTAL: 1 + python-version: ${{ inputs.python-version }} + MISE_PYTHON: ${{ inputs.python-version }} + UV_PYTHON: ${{ inputs.python-version }} + runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 @@ -39,33 +45,26 @@ jobs: - name: Setup Python environment uses: ./.github/actions/setup-mise-env with: - python-version: ${{ inputs.python-version }} + python-version: ${{ env.python-version }} github-token: ${{ secrets.GITHUB_TOKEN }} - profile: "reviewer" + profile: "${{ env.PROFILE }}" skip-checkout: true id: mise-outputs - name: Check code style and linting env: - MISE_YES: 1 - MISE_PYTHON: ${{ inputs.python-version }} - UV_PYTHON: ${{ inputs.python-version }} - MISE_EXPERIMENTAL: 1 PYTHON_PATH: ${{ steps.mise-outputs.outputs.PYTHON_PATH }} + shell: bash run: | - export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" + export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$PATH" + echo "PYTHON_PATH=$PYTHON_PATH" >> "$GITHUB_ENV" + eval "$(mise activate bash)" + echo "PATH=$PATH" >> "$GITHUB_ENV" mise //:lint || echo "::warning::Lint checks failed but allowing workflow to continue" continue-on-error: true - name: Check formatting and licenses - if: inputs.run-format-check - env: - MISE_YES: 1 - MISE_PYTHON: ${{ inputs.python-version }} - UV_PYTHON: ${{ inputs.python-version }} - MISE_EXPERIMENTAL: 1 - PYTHON_PATH: ${{ steps.mise-outputs.outputs.PYTHON_PATH }} + if: ${{ inputs.run-format-check == true }} run: | - export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" mise //:format || echo "::warning::License checks or formatting checks failed but allowing workflow to continue" continue-on-error: true diff --git a/.github/workflows/_reusable-test.yml b/.github/workflows/_reusable-test.yml index cdcb6dfc7..f1422893c 100644 --- a/.github/workflows/_reusable-test.yml +++ b/.github/workflows/_reusable-test.yml @@ -39,6 +39,18 @@ on: required: false VOYAGE_API_KEY: required: false +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + MISE_EXPERIMENTAL: 1 + MISE_YES: 1 + PROFILE: "dev" + CODEWEAVER_PROJECT_PATH: ${{ github.workspace }} + CODEWEAVER_TESTING: "true" + CODEWEAVER_VECTOR_STORE_URL: ${{ secrets.CODEWEAVER_VECTOR_STORE_URL }} + QDRANT__SERVICE__API_KEY: ${{ secrets.QDRANT__SERVICE__API_KEY }} + VOYAGE_API_KEY: ${{ secrets.VOYAGE_API_KEY }} + MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} jobs: test: @@ -57,16 +69,6 @@ jobs: - python-version: "3.14t" experimental: true env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - CODEWEAVER_TESTING: "true" - CODEWEAVER_VECTOR_STORE_URL: ${{ secrets.CODEWEAVER_VECTOR_STORE_URL }} - QDRANT__SERVICE__API_KEY: ${{ secrets.QDRANT__SERVICE__API_KEY }} - VOYAGE_API_KEY: ${{ secrets.VOYAGE_API_KEY }} - CODEWEAVER_PROJECT_PATH: ${{ github.workspace }} - MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - MISE_EXPERIMENTAL: 1 - MISE_YES: 1 MISE_PYTHON: ${{ matrix.python-version }} UV_PYTHON: ${{ matrix.python-version }} steps: @@ -87,26 +89,18 @@ jobs: - name: Run quality checks before tests if: ${{ inputs.run-quality-checks && matrix.experimental == false }} env: - MISE_YES: 1 - MISE_PYTHON: ${{ matrix.python-version }} - UV_PYTHON: ${{ matrix.python-version }} - MISE_EXPERIMENTAL: 1 MISE_PATH: ${{ steps.setup-mise.outputs.MISE_PATH }} run: | export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" - "$MISE_PATH" //:check 2>&1 + echo "MISE_PATH=$MISE_PATH" >> "$GITHUB_ENV" + eval "$(mise activate bash)" + echo "PATH=$PATH" >> "$GITHUB_ENV" + mise //:check 2>&1 continue-on-error: true - name: Run tests with coverage if: ${{ matrix.experimental == false }} - env: - MISE_YES: 1 - MISE_PYTHON: ${{ matrix.python-version }} - UV_PYTHON: ${{ matrix.python-version }} - MISE_EXPERIMENTAL: 1 - MISE_PATH: ${{ steps.setup-mise.outputs.MISE_PATH }} run: | - export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" - "$MISE_PATH" //:test-cov -m "${{ inputs.test-markers }}" + mise //:test-cov -m "${{ inputs.test-markers }}" - name: Upload coverage to Codecov if: ${{ inputs.upload-coverage && matrix.python-version == '3.12' }} uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 @@ -132,14 +126,18 @@ jobs: with: python-version: ${{ matrix.python-version }} skip-checkout: true + id: setup-uv - name: Setup Env for Experimental Python if: ${{ matrix.experimental == true }} shell: bash + env: + UV_PYTHON: ${{ matrix.python-version }} + UV_PATH: ${{ steps.setup-uv.outputs.UV_PATH }} run: | - uv sync --group test --resolution highest 2>&1 + "$UV_PATH" sync --group test --resolution highest 2>&1 + echo "UV_PATH=$UV_PATH" >> "$GITHUB_ENV" - name: Run test coverage for experimental Python if: ${{ matrix.experimental == true }} run: | - export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" - uv run -m pytest tests/ --cov=codeweaver --cov-report=xml --cov-report=term-missing --junit-xml=test-results.xml -v -m "${{ inputs.test-markers }}" + "$UV_PATH" run -m pytest tests/ --cov=codeweaver --cov-report=xml --cov-report=term-missing --junit-xml=test-results.xml -v -m "${{ inputs.test-markers }}" diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 036145d57..fb3035e5d 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -19,6 +19,7 @@ on: pull_request_review: types: - submitted + permissions: actions: read checks: read @@ -26,27 +27,26 @@ permissions: contents: write discussions: write pull-requests: write + +env: + CODEWEAVER_VECTOR_STORE_URL: ${{ secrets.CODEWEAVER_VECTOR_STORE_URL }} + QDRANT__SERVICE__API_KEY: ${{ secrets.QDRANT__SERVICE__API_KEY }} + VOYAGE_API_KEY: ${{ secrets.VOYAGE_API_KEY }} + CODEWEAVER_PROJECT_PATH: ${{ github.workspace }} + MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + MISE_ENV: "dev" + MISE_YES: 1 + TAVILY_API_KEY: ${{ secrets.TAVILY_API_KEY }} + # Limit CodeQL memory usage to prevent OOM kills on standard runners (7GB total RAM) + # Note: Standard runners have ~7GB, so limit to 3GB to leave headroom for system + CODEQL_RAM: 3072 + CODEQL_THREADS: 2 + # Additional limits for CodeQL extractor and evaluator + CODEQL_EXTRACTOR_PYTHON_RAM: 2048 + CODEQL_EVALUATOR_RAM: 2048 jobs: claude-response: - # Alternative: Use ubuntu-latest-4-cores (16GB RAM) if OOM issues persist - # Requires GitHub Team/Enterprise plan runs-on: ubuntu-latest - env: - CODEWEAVER_VECTOR_STORE_URL: ${{ secrets.CODEWEAVER_VECTOR_STORE_URL }} - QDRANT__SERVICE__API_KEY: ${{ secrets.QDRANT__SERVICE__API_KEY }} - VOYAGE_API_KEY: ${{ secrets.VOYAGE_API_KEY }} - CODEWEAVER_PROJECT_PATH: ${{ github.workspace }} - MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - MISE_ENV: "dev" - MISE_YES: 1 - TAVILY_API_KEY: ${{ secrets.TAVILY_API_KEY }} - # Limit CodeQL memory usage to prevent OOM kills on standard runners (7GB total RAM) - # Note: Standard runners have ~7GB, so limit to 3GB to leave headroom for system - CODEQL_RAM: 3072 - CODEQL_THREADS: 2 - # Additional limits for CodeQL extractor and evaluator - CODEQL_EXTRACTOR_PYTHON_RAM: 2048 - CODEQL_EVALUATOR_RAM: 2048 steps: - name: Checkout Repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 @@ -156,6 +156,7 @@ jobs: - Provide feedback on the code quality, functionality, and adherence to best practices. - Consider the library's existing code style and whether the code aligns with it. - Consider possible security or performance effects. + - If the code does not follow APIs as you would expect, remember that you have access to the context7 tool to look up library documentation. APIs may have changed since your training data. - Suggest improvements or alternatives where applicable. - If the changes are satisfactory and the code passes checks, approve the PR with a comment. - name: Setup Environment for Assigned or Labeled Issues/PRs @@ -186,11 +187,13 @@ jobs: --mcp-config .mcp.json prompt: | REPO: ${{ github.repository }} - ISSUE NUMBER: ${{ github.event.issue.number }} + ISSUE/ PR NUMBER: ${{ github.event.issue.number || github.event.pull_request.number }} When you are assigned an issue or it's labeled 'claude': - Your job is to resolve it. - Gather all necessary information about the issue from discussions and comments and the codebase. - If the issue involves external libraries, use the context7 tool to get the latest information on the API. + - Pay attention to external API versions--they may have changed since your training data, or even since the sources you research. When in doubt, use the tavily tool or web search to find the current documentation. + - Research similar issues in this repository and others to inform your approach. - Communicate with the issue reporter for clarification if needed. - Create an issue branch. - Develop a detailed plan to fix the problem. diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index 61324ec86..8fe587f3b 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -14,14 +14,20 @@ on: pull_request: paths: - .github/workflows/copilot-setup-steps.yml + jobs: # The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot. copilot-setup-steps: + outputs: + MISE_PATH: ${{ steps.setup-mise.outputs.MISE_PATH }} + env: CODEWEAVER_VECTOR_STORE_URL: ${{ secrets.CODEWEAVER_VECTOR_STORE_URL }} QDRANT__SERVICE__API_KEY: ${{ secrets.QDRANT__SERVICE__API_KEY }} VOYAGE_API_KEY: ${{ secrets.VOYAGE_API_KEY }} CODEWEAVER_PROJECT_PATH: ${{ github.workspace }} + MISE_ENV: dev + MISE_EXPERIMENTAL: 1 MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} MISE_YES: 1 # Limit CodeQL memory usage to prevent OOM kills on standard runners (7GB total RAM) @@ -71,3 +77,5 @@ jobs: run: | export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" mise --version || { echo "Mise not in path"; "$MISE_PATH" --version; } + echo "MISE_PATH=$MISE_PATH" >> "$GITHUB_OUTPUT" + echo "MISE_ENV=$MISE_ENV" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/mcp-registry-submit.yml b/.github/workflows/mcp-registry-submit.yml index 9488cc0dd..4d78447c5 100644 --- a/.github/workflows/mcp-registry-submit.yml +++ b/.github/workflows/mcp-registry-submit.yml @@ -8,7 +8,9 @@ name: Submit to MCP Registry on: release: - types: [published] + types: + - published + - prereleased workflow_dispatch: inputs: version: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 289a74129..c5bc8bedc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,6 +6,9 @@ name: Release on: push: + branches: + - main + - staging tags: - v* workflow_dispatch: @@ -29,6 +32,7 @@ jobs: tests: name: Run Tests # EFFICIENCY: Skip tests on tag push (rely on PR tests), but allow manual trigger + # TODO: Add smoke tests for releases if: github.event_name == 'workflow_dispatch' || github.event_name == 'release' uses: ./.github/workflows/_reusable-test.yml with: From 0fa134c6d2b461811b3dfaf9cf566ce04ffebd6f Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sat, 6 Dec 2025 23:41:18 -0500 Subject: [PATCH 17/61] fix: update Python setup action to include outputs for PYTHON_PATH and UV_PATH --- .github/actions/setup-python-env/action.yml | 12 ++++++++++++ .github/workflows/_reusable-test.yml | 5 ++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/actions/setup-python-env/action.yml b/.github/actions/setup-python-env/action.yml index c90a79aad..61235a3b6 100644 --- a/.github/actions/setup-python-env/action.yml +++ b/.github/actions/setup-python-env/action.yml @@ -24,6 +24,14 @@ inputs: required: false default: '' +outputs: + PYTHON_PATH: + description: Path to the Python executable + value: ${{ steps.python-setup.outputs.python-path }} + UV_PATH: + description: Path to uv executable + value: ${{ steps.python-setup.outputs.UV_PATH }} + runs: using: composite steps: @@ -48,4 +56,8 @@ runs: run: | python -m pip install --upgrade pip setuptools wheel python -m pip install uv + echo "PYTHON_PATH=$(which python)" >> "$GITHUB_ENV" + echo "UV_PATH=$(which uv)" >> "$GITHUB_ENV" + id: python-setup + diff --git a/.github/workflows/_reusable-test.yml b/.github/workflows/_reusable-test.yml index f1422893c..a343bcb0b 100644 --- a/.github/workflows/_reusable-test.yml +++ b/.github/workflows/_reusable-test.yml @@ -126,13 +126,12 @@ jobs: with: python-version: ${{ matrix.python-version }} skip-checkout: true - id: setup-uv + id: setup-python - name: Setup Env for Experimental Python if: ${{ matrix.experimental == true }} shell: bash env: - UV_PYTHON: ${{ matrix.python-version }} - UV_PATH: ${{ steps.setup-uv.outputs.UV_PATH }} + UV_PATH: ${{ steps.setup-python.outputs.UV_PATH }} run: | "$UV_PATH" sync --group test --resolution highest 2>&1 echo "UV_PATH=$UV_PATH" >> "$GITHUB_ENV" From df2099878f4466b252ecf10bf389eb7d02a3391c Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sat, 6 Dec 2025 23:53:48 -0500 Subject: [PATCH 18/61] fix: update CI workflows to ensure uv is available when called --- .github/workflows/_reusable-lint.yml | 1 + .github/workflows/_reusable-test.yml | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/.github/workflows/_reusable-lint.yml b/.github/workflows/_reusable-lint.yml index 066b90456..f141757ce 100644 --- a/.github/workflows/_reusable-lint.yml +++ b/.github/workflows/_reusable-lint.yml @@ -60,6 +60,7 @@ jobs: echo "PYTHON_PATH=$PYTHON_PATH" >> "$GITHUB_ENV" eval "$(mise activate bash)" echo "PATH=$PATH" >> "$GITHUB_ENV" + mise use -g uv@latest mise //:lint || echo "::warning::Lint checks failed but allowing workflow to continue" continue-on-error: true diff --git a/.github/workflows/_reusable-test.yml b/.github/workflows/_reusable-test.yml index a343bcb0b..72e0ae4b8 100644 --- a/.github/workflows/_reusable-test.yml +++ b/.github/workflows/_reusable-test.yml @@ -94,6 +94,7 @@ jobs: export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" echo "MISE_PATH=$MISE_PATH" >> "$GITHUB_ENV" eval "$(mise activate bash)" + mise use -g uv@latest echo "PATH=$PATH" >> "$GITHUB_ENV" mise //:check 2>&1 continue-on-error: true @@ -133,6 +134,14 @@ jobs: env: UV_PATH: ${{ steps.setup-python.outputs.UV_PATH }} run: | + if [ -z "$UV_PATH" ]; then + echo "UV_PATH is not set." + if ! command -v uv &> /dev/null; then + echo "uv could not be found" + exit 1 + fi + UV_PATH="$(which uv)" + fi "$UV_PATH" sync --group test --resolution highest 2>&1 echo "UV_PATH=$UV_PATH" >> "$GITHUB_ENV" From 855c5ba2f6fee2f317fe6bd66000d6e2f7b69fa8 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sun, 7 Dec 2025 00:01:20 -0500 Subject: [PATCH 19/61] fix: add tools to mise check task for CI availability --- mise.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mise.toml b/mise.toml index 988a6f217..f0b00cdc7 100644 --- a/mise.toml +++ b/mise.toml @@ -155,6 +155,9 @@ sources = ["{src,scripts,tests,mise-tasks}/*.py"] [tasks.check] tools.hk = "latest" tools.pkl = "latest" +tools."pipx:ty" = "latest" +tools."pipx:reuse" = "latest" +tools.ruff = "latest" run = ''' echo "${CW_PREFIX} Running quality checks..." hk check From b7dbc413fc073aa035437b318ae4b99422f80427 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sun, 7 Dec 2025 00:10:13 -0500 Subject: [PATCH 20/61] fix: add setup step for mise dev installs in CI --- .github/actions/setup-mise-env/action.yml | 14 ++++++++++++++ .github/workflows/claude.yml | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 319070f4b..fbc211ac5 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -45,6 +45,7 @@ outputs: description: Path to Python executable value: ${{ steps.mise-outputs.outputs.PYTHON_PATH }} + runs: using: composite steps: @@ -94,6 +95,8 @@ runs: - name: Activate Reviewer Profile Environment if: inputs.profile == 'reviewer' shell: bash + env: + MISE_GITHUB_TOKEN: ${{ inputs.github-token }} id: mise-setup-reviewer run: | uv sync @@ -113,6 +116,17 @@ runs: cache_key_prefix: ${{ inputs.profile }} env: false id: mise-setup-dev + - name: Activate Dev Profile Environment + if: inputs.profile == 'dev' + shell: bash + id: mise-setup-dev-activate + env: + MISE_ENV: dev + MISE_EXPERIMENTAL: 1 + MISE_YES: 1 + MISE_GITHUB_TOKEN: ${{ inputs.github-token }} + run: | + mise ://setup - name: Set outputs shell: bash diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index fb3035e5d..05db17a6d 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -187,7 +187,7 @@ jobs: --mcp-config .mcp.json prompt: | REPO: ${{ github.repository }} - ISSUE/ PR NUMBER: ${{ github.event.issue.number || github.event.pull_request.number }} + ISSUE/PR NUMBER: ${{ github.event.issue.number || github.event.pull_request.number }} When you are assigned an issue or it's labeled 'claude': - Your job is to resolve it. - Gather all necessary information about the issue from discussions and comments and the codebase. From 0bf40811357a8946ea84b5f96278a623ebbea75a Mon Sep 17 00:00:00 2001 From: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> Date: Sun, 7 Dec 2025 00:22:46 -0500 Subject: [PATCH 21/61] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> --- .github/actions/setup-python-env/action.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/setup-python-env/action.yml b/.github/actions/setup-python-env/action.yml index 61235a3b6..ce12ad1ca 100644 --- a/.github/actions/setup-python-env/action.yml +++ b/.github/actions/setup-python-env/action.yml @@ -27,7 +27,7 @@ inputs: outputs: PYTHON_PATH: description: Path to the Python executable - value: ${{ steps.python-setup.outputs.python-path }} + value: ${{ steps.python-setup.outputs.PYTHON_PATH }} UV_PATH: description: Path to uv executable value: ${{ steps.python-setup.outputs.UV_PATH }} @@ -56,8 +56,8 @@ runs: run: | python -m pip install --upgrade pip setuptools wheel python -m pip install uv - echo "PYTHON_PATH=$(which python)" >> "$GITHUB_ENV" - echo "UV_PATH=$(which uv)" >> "$GITHUB_ENV" + echo "PYTHON_PATH=$(which python)" >> "$GITHUB_OUTPUT" + echo "UV_PATH=$(which uv)" >> "$GITHUB_OUTPUT" id: python-setup From 47a86142565a4b1851a87b6e064235030666c4a0 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sun, 7 Dec 2025 00:41:24 -0500 Subject: [PATCH 22/61] fix: improve CI workflows by setting PATH for mise and cleaning up temporary files --- .github/workflows/_reusable-lint.yml | 9 +++++---- .github/workflows/_reusable-test.yml | 21 +++++++++++++-------- .github/workflows/copilot-setup-steps.yml | 2 -- .github/workflows/mcp-registry-submit.yml | 6 +++++- 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/.github/workflows/_reusable-lint.yml b/.github/workflows/_reusable-lint.yml index f141757ce..434c3c382 100644 --- a/.github/workflows/_reusable-lint.yml +++ b/.github/workflows/_reusable-lint.yml @@ -50,16 +50,17 @@ jobs: profile: "${{ env.PROFILE }}" skip-checkout: true id: mise-outputs + - name: Set Path + run: | + export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" + eval "$(mise activate bash)" + echo "PATH=$PATH" >> "$GITHUB_ENV" - name: Check code style and linting env: PYTHON_PATH: ${{ steps.mise-outputs.outputs.PYTHON_PATH }} shell: bash run: | - export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$PATH" - echo "PYTHON_PATH=$PYTHON_PATH" >> "$GITHUB_ENV" - eval "$(mise activate bash)" - echo "PATH=$PATH" >> "$GITHUB_ENV" mise use -g uv@latest mise //:lint || echo "::warning::Lint checks failed but allowing workflow to continue" continue-on-error: true diff --git a/.github/workflows/_reusable-test.yml b/.github/workflows/_reusable-test.yml index 72e0ae4b8..c02c72d0e 100644 --- a/.github/workflows/_reusable-test.yml +++ b/.github/workflows/_reusable-test.yml @@ -86,16 +86,18 @@ jobs: profile: "dev" skip-checkout: true id: setup-mise + - name: Set Path + if: ${{ matrix.experimental == false }} + run: | + export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" + eval "$(mise activate bash)" + echo "PATH=$PATH" >> "$GITHUB_ENV" - name: Run quality checks before tests if: ${{ inputs.run-quality-checks && matrix.experimental == false }} env: MISE_PATH: ${{ steps.setup-mise.outputs.MISE_PATH }} run: | - export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" - echo "MISE_PATH=$MISE_PATH" >> "$GITHUB_ENV" - eval "$(mise activate bash)" mise use -g uv@latest - echo "PATH=$PATH" >> "$GITHUB_ENV" mise //:check 2>&1 continue-on-error: true - name: Run tests with coverage @@ -128,12 +130,11 @@ jobs: python-version: ${{ matrix.python-version }} skip-checkout: true id: setup-python - - name: Setup Env for Experimental Python + - name: Set UV Path if: ${{ matrix.experimental == true }} shell: bash - env: - UV_PATH: ${{ steps.setup-python.outputs.UV_PATH }} run: | + UV_PATH="${{ steps.setup-python.outputs.UV_PATH }}" if [ -z "$UV_PATH" ]; then echo "UV_PATH is not set." if ! command -v uv &> /dev/null; then @@ -142,8 +143,12 @@ jobs: fi UV_PATH="$(which uv)" fi - "$UV_PATH" sync --group test --resolution highest 2>&1 echo "UV_PATH=$UV_PATH" >> "$GITHUB_ENV" + - name: Setup Env for Experimental Python + if: ${{ matrix.experimental == true }} + shell: bash + run: | + "$UV_PATH" sync --group test --resolution highest 2>&1 - name: Run test coverage for experimental Python if: ${{ matrix.experimental == true }} diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index 8fe587f3b..a59ccd116 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -77,5 +77,3 @@ jobs: run: | export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" mise --version || { echo "Mise not in path"; "$MISE_PATH" --version; } - echo "MISE_PATH=$MISE_PATH" >> "$GITHUB_OUTPUT" - echo "MISE_ENV=$MISE_ENV" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/mcp-registry-submit.yml b/.github/workflows/mcp-registry-submit.yml index 4d78447c5..2db0788b9 100644 --- a/.github/workflows/mcp-registry-submit.yml +++ b/.github/workflows/mcp-registry-submit.yml @@ -127,6 +127,11 @@ jobs: # we need to sign the timestamp with the private key, which is in MCP_REGISTRY_KEY # MCP_REGISTRY_KEY is expected to be in PEM format, and it uses ed25519 algorithm # unfortunately, pkeyutl can only work with files because of how it has to buffer the input for signing + # shellcheck disable=SC2329 + cleanup() { + shred -u "$key_file" "$outfile" || rm -f "$key_file" "$outfile" + } + trap cleanup EXIT domain="knitli.com" indata="$(mktemp)" @@ -152,7 +157,6 @@ jobs: --header "Content-Type: application/json" \ --data @"$request_body")" token="$(echo "$response" | jq -r '.registry_token')" - rm "$indata" "$key_file" "$outfile" "$request_body" if [ -z "$token" ] || [ "$token" = "null" ]; then echo "ERROR: Failed to obtain registry token" echo "Response: $response" From 766575ce703213e6911396beeff0617376c36723 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> Date: Sun, 7 Dec 2025 00:45:14 -0500 Subject: [PATCH 23/61] Update .github/workflows/mcp-registry-submit.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> --- .github/workflows/mcp-registry-submit.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/mcp-registry-submit.yml b/.github/workflows/mcp-registry-submit.yml index 2db0788b9..9c6b95fa6 100644 --- a/.github/workflows/mcp-registry-submit.yml +++ b/.github/workflows/mcp-registry-submit.yml @@ -198,7 +198,10 @@ jobs: { echo "✅ Successfully submitted to MCP Registry" echo "" - echo "View your server at: https://registry.modelcontextprotocol.io/v0.1/servers/com.knitli%2Fcodeweaver/versions/${{ steps.version.outputs.version }}" + # Extract and encode server name from server.json + SERVER_NAME=$(jq -r '.name' server.json) + ENCODED_SERVER_NAME=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1], safe=''))" "$SERVER_NAME") + echo "View your server at: https://registry.modelcontextprotocol.io/v0.1/servers/${ENCODED_SERVER_NAME}/versions/${{ steps.version.outputs.version }}" } >> "$GITHUB_STEP_SUMMARY" else { From 407161d889a8e5b6176f8db46a3db8dc37539dda Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sun, 7 Dec 2025 09:46:10 -0500 Subject: [PATCH 24/61] fix: enhance CI workflows by adding NEWPATH output and updating PATH setup --- .github/actions/setup-mise-env/action.yml | 27 ++++++++++++---- .github/workflows/_reusable-test.yml | 22 ++++++++----- .github/workflows/copilot-setup-steps.yml | 3 +- mise.toml | 39 +++++++++++++++++++++++ 4 files changed, 75 insertions(+), 16 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index fbc211ac5..10e49d693 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -44,6 +44,9 @@ outputs: PYTHON_PATH: description: Path to Python executable value: ${{ steps.mise-outputs.outputs.PYTHON_PATH }} + NEWPATH: + description: Updated PATH including mise and python paths + value: ${{ steps.mise-outputs.outputs.NEWPATH }} runs: @@ -57,7 +60,7 @@ runs: - name: Install system dependencies shell: bash run: | - sudo apt-get update && sudo apt-get install -y zsh curl git + sudo apt-get update && sudo apt-get install -y curl git - name: Free up disk space shell: bash run: ./scripts/dev-env/ci-free-disk-space.sh @@ -133,9 +136,19 @@ runs: id: mise-outputs run: | # Add mise to PATH since env export is disabled - export PATH="$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" - echo "MISE_PATH=$(which mise)" >> $GITHUB_OUTPUT - echo "MISE_ENV=${MISE_ENV:-}" >> $GITHUB_OUTPUT - echo "PROFILE=${{ inputs.profile }}" >> $GITHUB_OUTPUT - echo "PYTHON_VERSION=$(python --version | awk '{print $2}')" >> $GITHUB_OUTPUT - echo "PYTHON_PATH=$(which python)" >> $GITHUB_OUTPUT + if [ "${{ inputs.profile }}" == "dev" ]; then + echo "MISE_ENV=dev" >> "$GITHUB_OUTPUT" + mise //:cloud-setup 2>&1 || true + else + echo "MISE_ENV=" >> "$GITHUB_OUTPUT" + fi + # setup PATH + echo "MISE_PATH=$(which mise)" >> "$GITHUB_OUTPUT" + mise_bin_dir="$(dirname "$MISE_PATH")" + python_path="$(which python)" + python_bin_dir="$(dirname "$python_path")" + NEWPATH="$mise_bin_dir:$python_bin_dir:$PATH" + echo "NEWPATH=${NEWPATH}" >> "$GITHUB_OUTPUT" + echo "PROFILE=${{ inputs.profile }}" >> "$GITHUB_OUTPUT" + echo "PYTHON_VERSION=$(python --version | awk '{print $2}')" >> "$GITHUB_OUTPUT" + echo "PYTHON_PATH=$python_path" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/_reusable-test.yml b/.github/workflows/_reusable-test.yml index c02c72d0e..4b48a2805 100644 --- a/.github/workflows/_reusable-test.yml +++ b/.github/workflows/_reusable-test.yml @@ -88,14 +88,13 @@ jobs: id: setup-mise - name: Set Path if: ${{ matrix.experimental == false }} + env: + NEWPATH: ${{ steps.setup-mise.outputs.NEWPATH }} + shell: bash run: | - export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" - eval "$(mise activate bash)" - echo "PATH=$PATH" >> "$GITHUB_ENV" + echo "PATH=$NEWPATH" >> "$GITHUB_ENV" - name: Run quality checks before tests if: ${{ inputs.run-quality-checks && matrix.experimental == false }} - env: - MISE_PATH: ${{ steps.setup-mise.outputs.MISE_PATH }} run: | mise use -g uv@latest mise //:check 2>&1 @@ -103,6 +102,7 @@ jobs: - name: Run tests with coverage if: ${{ matrix.experimental == false }} run: | + mise use -g uv@latest mise //:test-cov -m "${{ inputs.test-markers }}" - name: Upload coverage to Codecov if: ${{ inputs.upload-coverage && matrix.python-version == '3.12' }} @@ -137,20 +137,26 @@ jobs: UV_PATH="${{ steps.setup-python.outputs.UV_PATH }}" if [ -z "$UV_PATH" ]; then echo "UV_PATH is not set." + if [ -d ".venv" ]; then + export PATH=".venv/bin:$PATH" + else + export PATH="$HOME/.local/bin:$HOME/.local/share/uv/bin:$HOME/.uv/bin:$PATH" + fi if ! command -v uv &> /dev/null; then - echo "uv could not be found" + echo "uv could not be found even after adjusting PATH." exit 1 fi UV_PATH="$(which uv)" fi + echo "PATH=$PATH" >> "$GITHUB_ENV" echo "UV_PATH=$UV_PATH" >> "$GITHUB_ENV" - name: Setup Env for Experimental Python if: ${{ matrix.experimental == true }} shell: bash run: | - "$UV_PATH" sync --group test --resolution highest 2>&1 + uv sync --group test --resolution highest 2>&1 - name: Run test coverage for experimental Python if: ${{ matrix.experimental == true }} run: | - "$UV_PATH" run -m pytest tests/ --cov=codeweaver --cov-report=xml --cov-report=term-missing --junit-xml=test-results.xml -v -m "${{ inputs.test-markers }}" + uv run -m pytest tests/ --cov=codeweaver --cov-report=xml --cov-report=term-missing --junit-xml=test-results.xml -v -m "${{ inputs.test-markers }}" diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index a59ccd116..7848f25dc 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -74,6 +74,7 @@ jobs: MISE_YES: 1 MISE_EXPERIMENTAL: 1 MISE_PATH: ${{ steps.setup-mise.outputs.MISE_PATH }} + NEWPATH: ${{ steps.setup-mise.outputs.NEWPATH }} run: | - export PATH="$HOME/.local/bin:$HOME/.local/share/mise/bin:$HOME/.local/share/mise/shims:$PATH" + export PATH="$NEWPATH" mise --version || { echo "Mise not in path"; "$MISE_PATH" --version; } diff --git a/mise.toml b/mise.toml index f0b00cdc7..dc0a0a0f7 100644 --- a/mise.toml +++ b/mise.toml @@ -135,6 +135,45 @@ ACTIVE_SHELL = '''{{ exec(command='basename "$SHELL" 2>/dev/null || echo zsh') } [tasks.setup.tools] uv = "latest" +[tasks.cloud-setup] +run = [ + "echo \"[codeweaver] Setting up cloud development environment...\"", + "ln -sf AGENTS.md CLAUDE.md", + '''if ! command -v mise &>/dev/null; then + if [ -d "$HOME/.local/share/mise" || -d "$HOME/.mise" || -f "$HOME/.local/bin/mise" ]; then + export PATH="$HOME/.local/bin:$HOME/.mise/bin:$HOME/.local/share/mise/bin:$PATH" + if ! grep -qx "mise activate" "$HOME/.bashrc"; then + echo "eval \"$(mise activate \"${ACTIVE_SHELL:-bash}\")\" 2>&1 || true" >> "$HOME/.bashrc" + fi + else + chmod +x scripts/dev-env/install-mise.sh 2>&1 || true + ./scripts/dev-env/install-mise.sh 2>&1 || true + fi + fi''', + "mise -y trust --all 2>&1 || true", + "mise install 2>&1 || true", + "hk install --mise 2>&1 || mise x hk@latest -- hk install --mise 2>&1 || true", + "mise x uv@latest -- uv venv --allow-existing --seed --keyring-provider subprocess --python {{ get_env(name='MISE_PYTHON', default='3.13') }} .venv 2>&1", + "source .venv/bin/activate 2>&1 || true", + "mise x uv@latest -- uv sync --group dev --group test 2>&1", + "git config include.path .gitconfig 2>&1 || true", + ''' + ignore_files=('src/codeweaver/_version.py' 'coverage.xml' 'test-results.xml') + for file in "${ignore_files[@]}"; do + if ! grep -qx "$file" .git/info/exclude; then + echo "$file" >> .git/info/exclude 2>&1 + fi + done + ''', + "echo \"[codeweaver] Cloud development environment setup complete!\"", +] +[tasks.cloud-setup.env] +ACTIVE_SHELL = '''{{ exec(command='basename "$SHELL" 2>/dev/null || echo bash') }}''' +MISE_EXPERIMENTAL = "1" +MISE_ENV = "dev" +MISE_YES = "1" + + [tasks.fix-python] tools.uv = "latest" tools.ast-grep = "latest" From cb8618ce64004178c6d91595badd2f90b9fe872f Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sun, 7 Dec 2025 09:46:55 -0500 Subject: [PATCH 25/61] fix: update cloud setup task environment variables for consistency --- mise.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mise.toml b/mise.toml index dc0a0a0f7..545ef24a5 100644 --- a/mise.toml +++ b/mise.toml @@ -167,13 +167,13 @@ run = [ ''', "echo \"[codeweaver] Cloud development environment setup complete!\"", ] + [tasks.cloud-setup.env] ACTIVE_SHELL = '''{{ exec(command='basename "$SHELL" 2>/dev/null || echo bash') }}''' MISE_EXPERIMENTAL = "1" MISE_ENV = "dev" MISE_YES = "1" - [tasks.fix-python] tools.uv = "latest" tools.ast-grep = "latest" From 0d768714acd0c02edf7d40cfe2095af0676bb363 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sun, 7 Dec 2025 10:00:34 -0500 Subject: [PATCH 26/61] fix: enhance setup and testing workflows by adding missing dependencies and adjusting environment variables --- .github/actions/setup-mise-env/action.yml | 2 +- .github/workflows/_reusable-test.yml | 1 + mise.dev.toml | 5 ++++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 10e49d693..5e45bb673 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -60,7 +60,7 @@ runs: - name: Install system dependencies shell: bash run: | - sudo apt-get update && sudo apt-get install -y curl git + sudo apt-get update && sudo apt-get install -y curl git readline-common lzma bzip2 - name: Free up disk space shell: bash run: ./scripts/dev-env/ci-free-disk-space.sh diff --git a/.github/workflows/_reusable-test.yml b/.github/workflows/_reusable-test.yml index 4b48a2805..5aa39523e 100644 --- a/.github/workflows/_reusable-test.yml +++ b/.github/workflows/_reusable-test.yml @@ -92,6 +92,7 @@ jobs: NEWPATH: ${{ steps.setup-mise.outputs.NEWPATH }} shell: bash run: | + echo "PROFILE=dev" >> "$GITHUB_ENV" echo "PATH=$NEWPATH" >> "$GITHUB_ENV" - name: Run quality checks before tests if: ${{ inputs.run-quality-checks && matrix.experimental == false }} diff --git a/mise.dev.toml b/mise.dev.toml index c7a2b942d..858bdd9e3 100644 --- a/mise.dev.toml +++ b/mise.dev.toml @@ -22,7 +22,10 @@ ruff = "latest" # Python linting/formatting [hooks.enter] env.MISE_EXPERIMENTAL = "1" script = ''' -mise //:enter +# PROFILE is set to 'dev' in a cloud CI environment for cloud agents. 'enter' tends to break there. +if [ ! "$PROFILE" == "dev" ]; then + mise //:enter +fi ''' [tasks] From c40e7c18d9dbeb382ea7d9fad53e960414520a66 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> Date: Sun, 7 Dec 2025 11:20:40 -0500 Subject: [PATCH 27/61] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> --- .github/actions/setup-mise-env/action.yml | 5 +++-- mise.dev.toml | 2 +- mise.toml | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 5e45bb673..611faafb9 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -136,14 +136,15 @@ runs: id: mise-outputs run: | # Add mise to PATH since env export is disabled - if [ "${{ inputs.profile }}" == "dev" ]; then + if [ "${{ inputs.profile }}" = "dev" ]; then echo "MISE_ENV=dev" >> "$GITHUB_OUTPUT" mise //:cloud-setup 2>&1 || true else echo "MISE_ENV=" >> "$GITHUB_OUTPUT" fi # setup PATH - echo "MISE_PATH=$(which mise)" >> "$GITHUB_OUTPUT" + MISE_PATH="$(which mise)" + echo "MISE_PATH=$MISE_PATH" >> "$GITHUB_OUTPUT" mise_bin_dir="$(dirname "$MISE_PATH")" python_path="$(which python)" python_bin_dir="$(dirname "$python_path")" diff --git a/mise.dev.toml b/mise.dev.toml index 858bdd9e3..af14d9de6 100644 --- a/mise.dev.toml +++ b/mise.dev.toml @@ -23,7 +23,7 @@ ruff = "latest" # Python linting/formatting env.MISE_EXPERIMENTAL = "1" script = ''' # PROFILE is set to 'dev' in a cloud CI environment for cloud agents. 'enter' tends to break there. -if [ ! "$PROFILE" == "dev" ]; then +if [ ! "$PROFILE" = "dev" ]; then mise //:enter fi ''' diff --git a/mise.toml b/mise.toml index 545ef24a5..993b21704 100644 --- a/mise.toml +++ b/mise.toml @@ -140,9 +140,9 @@ run = [ "echo \"[codeweaver] Setting up cloud development environment...\"", "ln -sf AGENTS.md CLAUDE.md", '''if ! command -v mise &>/dev/null; then - if [ -d "$HOME/.local/share/mise" || -d "$HOME/.mise" || -f "$HOME/.local/bin/mise" ]; then + if [ -d "$HOME/.local/share/mise" ] || [ -d "$HOME/.mise" ] || [ -f "$HOME/.local/bin/mise" ]; then export PATH="$HOME/.local/bin:$HOME/.mise/bin:$HOME/.local/share/mise/bin:$PATH" - if ! grep -qx "mise activate" "$HOME/.bashrc"; then + if ! grep -q "mise activate" "$HOME/.bashrc"; then echo "eval \"$(mise activate \"${ACTIVE_SHELL:-bash}\")\" 2>&1 || true" >> "$HOME/.bashrc" fi else From a5ce307c5b03acc19dc00ca3cbb9578d5ccbb83c Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sun, 7 Dec 2025 11:25:42 -0500 Subject: [PATCH 28/61] fix: improve cleanup process in MCP Registry submission workflow --- .github/workflows/mcp-registry-submit.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/mcp-registry-submit.yml b/.github/workflows/mcp-registry-submit.yml index 9c6b95fa6..29db9d5b4 100644 --- a/.github/workflows/mcp-registry-submit.yml +++ b/.github/workflows/mcp-registry-submit.yml @@ -128,8 +128,15 @@ jobs: # MCP_REGISTRY_KEY is expected to be in PEM format, and it uses ed25519 algorithm # unfortunately, pkeyutl can only work with files because of how it has to buffer the input for signing # shellcheck disable=SC2329 + indata="" + key_file="" + outfile="" + request_body="" + # shellcheck disable=SC2329 cleanup() { shred -u "$key_file" "$outfile" || rm -f "$key_file" "$outfile" + # these aren't sensitive, but let's keep things tidy + rm -f "$indata" "$request_body" } trap cleanup EXIT From b7169d95a11e286d27ad0f5d211bdca04a0cd39c Mon Sep 17 00:00:00 2001 From: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> Date: Sun, 7 Dec 2025 11:36:02 -0500 Subject: [PATCH 29/61] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> --- .github/actions/setup-mise-env/action.yml | 2 +- .github/workflows/_reusable-test.yml | 11 ++++++----- mise.dev.toml | 2 +- mise.toml | 6 +++--- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 611faafb9..d3d6e2238 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -138,7 +138,7 @@ runs: # Add mise to PATH since env export is disabled if [ "${{ inputs.profile }}" = "dev" ]; then echo "MISE_ENV=dev" >> "$GITHUB_OUTPUT" - mise //:cloud-setup 2>&1 || true + mise //:cloud-setup 2>&1 else echo "MISE_ENV=" >> "$GITHUB_OUTPUT" fi diff --git a/.github/workflows/_reusable-test.yml b/.github/workflows/_reusable-test.yml index 5aa39523e..ef30ce038 100644 --- a/.github/workflows/_reusable-test.yml +++ b/.github/workflows/_reusable-test.yml @@ -136,20 +136,21 @@ jobs: shell: bash run: | UV_PATH="${{ steps.setup-python.outputs.UV_PATH }}" + FINAL_PATH="$PATH" if [ -z "$UV_PATH" ]; then echo "UV_PATH is not set." if [ -d ".venv" ]; then - export PATH=".venv/bin:$PATH" + FINAL_PATH=".venv/bin:$FINAL_PATH" else - export PATH="$HOME/.local/bin:$HOME/.local/share/uv/bin:$HOME/.uv/bin:$PATH" + FINAL_PATH="$HOME/.local/bin:$HOME/.local/share/uv/bin:$HOME/.uv/bin:$FINAL_PATH" fi - if ! command -v uv &> /dev/null; then + if ! PATH="$FINAL_PATH" command -v uv &> /dev/null; then echo "uv could not be found even after adjusting PATH." exit 1 fi - UV_PATH="$(which uv)" + UV_PATH="$(PATH="$FINAL_PATH" which uv)" fi - echo "PATH=$PATH" >> "$GITHUB_ENV" + echo "PATH=$FINAL_PATH" >> "$GITHUB_ENV" echo "UV_PATH=$UV_PATH" >> "$GITHUB_ENV" - name: Setup Env for Experimental Python if: ${{ matrix.experimental == true }} diff --git a/mise.dev.toml b/mise.dev.toml index af14d9de6..2aee2d484 100644 --- a/mise.dev.toml +++ b/mise.dev.toml @@ -23,7 +23,7 @@ ruff = "latest" # Python linting/formatting env.MISE_EXPERIMENTAL = "1" script = ''' # PROFILE is set to 'dev' in a cloud CI environment for cloud agents. 'enter' tends to break there. -if [ ! "$PROFILE" = "dev" ]; then +if [ "$PROFILE" != "dev" ]; then mise //:enter fi ''' diff --git a/mise.toml b/mise.toml index 993b21704..461ab8ac2 100644 --- a/mise.toml +++ b/mise.toml @@ -150,11 +150,11 @@ run = [ ./scripts/dev-env/install-mise.sh 2>&1 || true fi fi''', - "mise -y trust --all 2>&1 || true", - "mise install 2>&1 || true", + '''mise -y trust --all 2>&1 || { echo "[WARNING] mise -y trust --all failed during cloud-setup" >&2; }''', + '''mise install 2>&1 || { echo "[WARNING] mise install failed during cloud-setup" >&2; }''', "hk install --mise 2>&1 || mise x hk@latest -- hk install --mise 2>&1 || true", "mise x uv@latest -- uv venv --allow-existing --seed --keyring-provider subprocess --python {{ get_env(name='MISE_PYTHON', default='3.13') }} .venv 2>&1", - "source .venv/bin/activate 2>&1 || true", + ". .venv/bin/activate 2>&1 || true", "mise x uv@latest -- uv sync --group dev --group test 2>&1", "git config include.path .gitconfig 2>&1 || true", ''' From 9a7a2f85cf32007f31400f2e67f8cca4825ed630 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> Date: Sun, 7 Dec 2025 14:27:38 -0500 Subject: [PATCH 30/61] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> --- .github/workflows/mcp-registry-submit.yml | 6 +++--- mise.toml | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/mcp-registry-submit.yml b/.github/workflows/mcp-registry-submit.yml index 29db9d5b4..aff670d88 100644 --- a/.github/workflows/mcp-registry-submit.yml +++ b/.github/workflows/mcp-registry-submit.yml @@ -144,6 +144,7 @@ jobs: indata="$(mktemp)" echo -n "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" > "$indata" + umask 077 key_file="$(mktemp)" echo "$MCP_REGISTRY_KEY" > "$key_file" chmod 600 "$key_file" @@ -170,11 +171,10 @@ jobs: exit 1 fi echo "✓ Obtained registry token" - export MCP_LOGIN_TOKEN="$token" publication_response="$(curl --request POST \ --url https://registry.modelcontextprotocol.io/v0.1/publish \ --header 'Accept: application/json, application/problem+json' \ - --header "Authorization: Bearer $MCP_LOGIN_TOKEN" \ + --header "Authorization: Bearer $token" \ --header 'Content-Type: application/json' \ --data @./server.json)" echo "Publication response: $publication_response" @@ -195,7 +195,7 @@ jobs: echo "" echo "- **Version**: ${{ steps.version.outputs.version }}" echo "- **Status**: ${{ job.status }}" - if [ -n "$MCP_PUBLICATION_TIME" ]; then + if [ -n "${{ steps.submit-mcp.outputs.MCP_PUBLICATION_TIME }}" ]; then echo "- **Published At**: ${{ steps.submit-mcp.outputs.MCP_PUBLICATION_TIME }}" fi echo "" diff --git a/mise.toml b/mise.toml index 461ab8ac2..733e94d89 100644 --- a/mise.toml +++ b/mise.toml @@ -157,14 +157,14 @@ run = [ ". .venv/bin/activate 2>&1 || true", "mise x uv@latest -- uv sync --group dev --group test 2>&1", "git config include.path .gitconfig 2>&1 || true", - ''' + '''bash -c " ignore_files=('src/codeweaver/_version.py' 'coverage.xml' 'test-results.xml') - for file in "${ignore_files[@]}"; do - if ! grep -qx "$file" .git/info/exclude; then - echo "$file" >> .git/info/exclude 2>&1 + for file in \"\${ignore_files[@]}\"; do + if ! grep -qx \"\$file\" .git/info/exclude; then + echo \"\$file\" >> .git/info/exclude 2>&1 fi done - ''', + "''', "echo \"[codeweaver] Cloud development environment setup complete!\"", ] From 7a6fe77a270c1843fefb0f2261ec8c6f266e1ae0 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> Date: Sun, 7 Dec 2025 14:42:55 -0500 Subject: [PATCH 31/61] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> --- .github/actions/setup-mise-env/action.yml | 4 ++-- .github/workflows/mcp-registry-submit.yml | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index d3d6e2238..08459ebf0 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -60,7 +60,7 @@ runs: - name: Install system dependencies shell: bash run: | - sudo apt-get update && sudo apt-get install -y curl git readline-common lzma bzip2 + sudo apt-get update && sudo apt-get install -y curl git readline-common lzma bzip2 libbz2-dev - name: Free up disk space shell: bash run: ./scripts/dev-env/ci-free-disk-space.sh @@ -129,7 +129,7 @@ runs: MISE_YES: 1 MISE_GITHUB_TOKEN: ${{ inputs.github-token }} run: | - mise ://setup + mise //:setup - name: Set outputs shell: bash diff --git a/.github/workflows/mcp-registry-submit.yml b/.github/workflows/mcp-registry-submit.yml index aff670d88..0d0352b97 100644 --- a/.github/workflows/mcp-registry-submit.yml +++ b/.github/workflows/mcp-registry-submit.yml @@ -147,7 +147,6 @@ jobs: umask 077 key_file="$(mktemp)" echo "$MCP_REGISTRY_KEY" > "$key_file" - chmod 600 "$key_file" outfile="$(mktemp)" openssl pkeyutl -sign -inkey "$key_file" -out "$outfile" -rawin -in "$indata" From 6e93e42837177fc923d6902364eba53c8410a9fe Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 7 Dec 2025 20:58:34 +0000 Subject: [PATCH 32/61] fix: add missing outputs to actions and simplify CI workflows Root cause: Custom actions were missing `outputs:` sections in action.yml. Steps wrote to $GITHUB_OUTPUT but outputs weren't exposed to callers. Changes: - Add outputs section to setup-mise-env action (MISE_PATH, PYTHON_PATH, etc.) - Add outputs section to setup-python-env action (PYTHON_PATH, UV_PATH) - Add outputs section to setup-uv-env action (uv-path, uvx-path) - Simplify reusable workflows to use `mise run task` directly - Remove complex $MISE_PATH variable usage (mise is already in PATH) - Fix experimental Python tests: remove --frozen flag that fails with prereleases - Clean up redundant env vars (move to job level) - Remove duplicate disk space cleanup in copilot-setup-steps --- .github/actions/setup-mise-env/action.yml | 17 +++++++++++ .github/actions/setup-python-env/action.yml | 11 +++++++ .github/actions/setup-uv-env/action.yml | 14 +++++---- .github/workflows/_reusable-lint.yml | 25 +++------------ .github/workflows/_reusable-test.yml | 34 +++++---------------- .github/workflows/copilot-setup-steps.yml | 15 ++++----- 6 files changed, 55 insertions(+), 61 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 386b88f9b..08fe6a8f1 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -28,6 +28,23 @@ inputs: required: true default: 'minimal' +outputs: + MISE_PATH: + description: Path to mise executable + value: ${{ steps.mise-outputs.outputs.MISE_PATH }} + MISE_ENV: + description: Mise environment name + value: ${{ steps.mise-outputs.outputs.MISE_ENV }} + PROFILE: + description: Profile used for setup + value: ${{ steps.mise-outputs.outputs.PROFILE }} + PYTHON_VERSION: + description: Python version installed + value: ${{ steps.mise-outputs.outputs.PYTHON_VERSION }} + PYTHON_PATH: + description: Path to Python executable + value: ${{ steps.mise-outputs.outputs.PYTHON_PATH }} + runs: using: composite steps: diff --git a/.github/actions/setup-python-env/action.yml b/.github/actions/setup-python-env/action.yml index c90a79aad..4ab05b65c 100644 --- a/.github/actions/setup-python-env/action.yml +++ b/.github/actions/setup-python-env/action.yml @@ -24,6 +24,14 @@ inputs: required: false default: '' +outputs: + PYTHON_PATH: + description: Path to the Python executable + value: ${{ steps.python-setup.outputs.PYTHON_PATH }} + UV_PATH: + description: Path to uv executable + value: ${{ steps.python-setup.outputs.UV_PATH }} + runs: using: composite steps: @@ -45,7 +53,10 @@ runs: allow-prereleases: true - name: Install pip packages shell: bash + id: python-setup run: | python -m pip install --upgrade pip setuptools wheel python -m pip install uv + echo "PYTHON_PATH=$(which python)" >> "$GITHUB_OUTPUT" + echo "UV_PATH=$(which uv)" >> "$GITHUB_OUTPUT" diff --git a/.github/actions/setup-uv-env/action.yml b/.github/actions/setup-uv-env/action.yml index 918113526..077e44b26 100644 --- a/.github/actions/setup-uv-env/action.yml +++ b/.github/actions/setup-uv-env/action.yml @@ -28,6 +28,14 @@ inputs: required: false default: 'false' +outputs: + uv-path: + description: Path to uv executable + value: ${{ steps.setup-uv.outputs.uv-path }} + uvx-path: + description: Path to uvx executable + value: ${{ steps.setup-uv.outputs.uvx-path }} + runs: using: composite steps: @@ -54,10 +62,4 @@ runs: prune-cache: "true" add-problem-matchers: "true" id: setup-uv - - name: Export outputs - shell: bash - id: uv-outputs - run: | - echo "UV_PATH=${{ steps.setup-uv.outputs.uv-path }}" >> $GITHUB_OUTPUT - echo "UVX_PATH=${{ steps.setup-uv.outputs.uvx-path }}" >> $GITHUB_OUTPUT diff --git a/.github/workflows/_reusable-lint.yml b/.github/workflows/_reusable-lint.yml index 50e5299a3..071b69a96 100644 --- a/.github/workflows/_reusable-lint.yml +++ b/.github/workflows/_reusable-lint.yml @@ -28,8 +28,10 @@ jobs: name: Lint and Format runs-on: ubuntu-latest env: - MISE_ENV: ci MISE_EXPERIMENTAL: 1 + MISE_YES: 1 + MISE_PYTHON: ${{ inputs.python-version }} + UV_PYTHON: ${{ inputs.python-version }} steps: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 @@ -43,29 +45,12 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} profile: "reviewer" skip-checkout: true - id: mise-outputs - name: Check code style and linting - env: - MISE_YES: 1 - MISE_PYTHON: ${{ inputs.python-version }} - UV_PYTHON: ${{ inputs.python-version }} - MISE_EXPERIMENTAL: 1 - PYTHON_PATH: ${{ steps.mise-outputs.outputs.PYTHON_PATH }} - run: | - export PATH="$HOME/.local/bin:$PATH" - mise //:lint || echo "::warning::Lint checks failed but allowing workflow to continue" + run: mise run lint || echo "::warning::Lint checks failed but allowing workflow to continue" continue-on-error: true - name: Check formatting and licenses if: inputs.run-format-check - env: - MISE_YES: 1 - MISE_PYTHON: ${{ inputs.python-version }} - UV_PYTHON: ${{ inputs.python-version }} - MISE_EXPERIMENTAL: 1 - PYTHON_PATH: ${{ steps.mise-outputs.outputs.PYTHON_PATH }} - run: | - export PATH="$HOME/.local/bin:$PATH" - mise //:format || echo "::warning::License checks or formatting checks failed but allowing workflow to continue" + run: mise run format || echo "::warning::License checks or formatting checks failed but allowing workflow to continue" continue-on-error: true diff --git a/.github/workflows/_reusable-test.yml b/.github/workflows/_reusable-test.yml index b3e78e042..4fe62d0a8 100644 --- a/.github/workflows/_reusable-test.yml +++ b/.github/workflows/_reusable-test.yml @@ -86,27 +86,12 @@ jobs: id: setup-mise - name: Run quality checks if: ${{ inputs.run-quality-checks && matrix.experimental == false }} - env: - MISE_YES: 1 - MISE_PYTHON: ${{ matrix.python-version }} - UV_PYTHON: ${{ matrix.python-version }} - MISE_EXPERIMENTAL: 1 - MISE_PATH: ${{ steps.setup-mise.outputs.MISE_PATH }} - run: | - export PATH="$HOME/.local/bin:$PATH" - "$MISE_PATH" //:check 2>&1 + run: mise run check 2>&1 continue-on-error: true + - name: Run tests with coverage if: ${{ matrix.experimental == false }} - env: - MISE_YES: 1 - MISE_PYTHON: ${{ matrix.python-version }} - UV_PYTHON: ${{ matrix.python-version }} - MISE_EXPERIMENTAL: 1 - MISE_PATH: ${{ steps.setup-mise.outputs.MISE_PATH }} - run: | - export PATH="$HOME/.local/bin:$PATH" - "$MISE_PATH" //:test-cov -m "${{ inputs.test-markers }}" + run: mise run test-cov -m "${{ inputs.test-markers }}" - name: Upload coverage to Codecov if: ${{ inputs.upload-coverage && matrix.python-version == '3.12' }} uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 @@ -125,22 +110,19 @@ jobs: coverage.xml if-no-files-found: warn - # Run experimental last + # Experimental Python versions (free-threaded) - name: Setup Experimental Python environment if: ${{ matrix.experimental == true }} uses: ./.github/actions/setup-python-env with: python-version: ${{ matrix.python-version }} skip-checkout: true - - name: Setup Env for Experimental Python + + - name: Install test dependencies for Experimental Python if: ${{ matrix.experimental == true }} - shell: bash - run: | - uv sync --no-extra --group test --resolution highest --frozen 2>&1 + run: uv sync --group test --resolution highest - name: Run test coverage for experimental Python if: ${{ matrix.experimental == true }} - run: | - export PATH="$HOME/.local/bin:$PATH" - uv run -m pytest tests/ --cov=codeweaver --cov-report=xml --cov-report=term-missing --junit-xml=test-results.xml -v -m "${{ inputs.test-markers }}" + run: uv run pytest tests/ --cov=codeweaver --cov-report=xml --cov-report=term-missing --junit-xml=test-results.xml -v -m "${{ inputs.test-markers }}" diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index 5651e67fb..ca69e67f2 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -23,6 +23,7 @@ jobs: VOYAGE_API_KEY: ${{ secrets.VOYAGE_API_KEY }} CODEWEAVER_PROJECT_PATH: ${{ github.workspace }} MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + MISE_EXPERIMENTAL: 1 MISE_YES: 1 # Limit CodeQL memory usage to prevent OOM kills on standard runners (7GB total RAM) # Note: Standard runners have ~7GB, so limit to 3GB to leave headroom for system @@ -32,23 +33,15 @@ jobs: CODEQL_EXTRACTOR_PYTHON_RAM: 2048 CODEQL_EVALUATOR_RAM: 2048 runs-on: ubuntu-latest - # Alternative: Use ubuntu-latest-4-cores (16GB RAM) if OOM issues persist - # Requires GitHub Team/Enterprise plan - # runs-on: ubuntu-latest-4-cores - # Add an overall job timeout so we don't let runaway installs exhaust the runner indefinitely timeout-minutes: 50 - # Set the permissions to the lowest permissions possible needed for your steps. - # Copilot will be given its own token for its operations. permissions: - # If you want to clone the repository as part of your setup steps, for example to install dependencies, you'll need the `contents: read` permission. contents: write steps: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 with: fetch-depth: 2 - - name: Free up disk space - run: ./scripts/dev-env/ci-free-disk-space.sh + - name: Setup Mise Environment uses: ./.github/actions/setup-mise-env with: @@ -56,7 +49,11 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} profile: "dev" skip-checkout: "true" + - name: Make scripts executable run: | chmod -R +x scripts chmod -R +x mise-tasks + + - name: Verify mise setup + run: mise --version From 3e7dd135642417d58712c397ad624ebffdf8aa8f Mon Sep 17 00:00:00 2001 From: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> Date: Sun, 7 Dec 2025 19:02:45 -0500 Subject: [PATCH 33/61] Fix: Add missing 'runs-on' specification for lint job Signed-off-by: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> --- .github/workflows/_reusable-lint.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/_reusable-lint.yml b/.github/workflows/_reusable-lint.yml index 96c1f8f36..8f569c458 100644 --- a/.github/workflows/_reusable-lint.yml +++ b/.github/workflows/_reusable-lint.yml @@ -31,6 +31,7 @@ jobs: permissions: contents: read name: Lint and Format + runs-on: ubuntu-latest env: MISE_EXPERIMENTAL: 1 MISE_YES: 1 From 3983e83e5dcffa997abe783140a7ba0a42f9df13 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> Date: Sun, 7 Dec 2025 19:21:14 -0500 Subject: [PATCH 34/61] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> --- .github/workflows/_reusable-lint.yml | 4 +--- .github/workflows/copilot-setup-steps.yml | 1 - .github/workflows/mcp-registry-submit.yml | 4 ++-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/_reusable-lint.yml b/.github/workflows/_reusable-lint.yml index 8f569c458..33b84031a 100644 --- a/.github/workflows/_reusable-lint.yml +++ b/.github/workflows/_reusable-lint.yml @@ -33,8 +33,6 @@ jobs: name: Lint and Format runs-on: ubuntu-latest env: - MISE_EXPERIMENTAL: 1 - MISE_YES: 1 MISE_PYTHON: ${{ inputs.python-version }} UV_PYTHON: ${{ inputs.python-version }} steps: @@ -46,7 +44,7 @@ jobs: - name: Setup Python environment uses: ./.github/actions/setup-mise-env with: - python-version: ${{ env.python-version }} + python-version: ${{ inputs.python-version }} github-token: ${{ secrets.GITHUB_TOKEN }} profile: "${{ env.PROFILE }}" skip-checkout: true diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index e4dd81533..cd919b4ac 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -29,7 +29,6 @@ jobs: MISE_ENV: dev MISE_EXPERIMENTAL: 1 MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - MISE_EXPERIMENTAL: 1 MISE_YES: 1 # Limit CodeQL memory usage to prevent OOM kills on standard runners (7GB total RAM) # Note: Standard runners have ~7GB, so limit to 3GB to leave headroom for system diff --git a/.github/workflows/mcp-registry-submit.yml b/.github/workflows/mcp-registry-submit.yml index 0d0352b97..173780479 100644 --- a/.github/workflows/mcp-registry-submit.yml +++ b/.github/workflows/mcp-registry-submit.yml @@ -33,7 +33,7 @@ jobs: ref: ${{ github.event.release.tag_name || github.ref }} fetch-depth: 1 - - name: Install uv + - name: Setup UV and Python environment uses: ./.github/actions/setup-uv-env with: python-version: "3.12" @@ -149,7 +149,7 @@ jobs: echo "$MCP_REGISTRY_KEY" > "$key_file" outfile="$(mktemp)" - openssl pkeyutl -sign -inkey "$key_file" -out "$outfile" -rawin -in "$indata" + openssl pkeyutl -sign -inkey "$key_file" -out "$outfile" -rawin -in "$indata" || { echo "ERROR: Failed to sign timestamp"; exit 1; } signed_timestamp_hex="$(xxd -p "$outfile" | tr -d '\n')" request_body="$(mktemp)" { From d95e9de1144bce2758481410da13de39b2199617 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sun, 7 Dec 2025 22:32:13 -0500 Subject: [PATCH 35/61] fix: update CI workflows and environment setup for consistency --- .github/actions/setup-mise-env/action.yml | 40 +++++--- .github/actions/setup-python-env/action.yml | 6 +- .github/workflows/_reusable-lint.yml | 2 +- .github/workflows/_reusable-test.yml | 28 ++---- .github/workflows/copilot-setup-steps.yml | 3 - .github/workflows/mcp-registry-submit.yml | 27 +++--- .github/workflows/stale.yml | 30 ++++++ .vscode/terminal.extra.zsh | 12 +-- .vscode/zsh/.zshrc | 39 +++++++- mise.dev.toml | 66 +++++++++++-- mise.toml | 101 +++++++------------- scripts/dev-env/dev-shell-init.zsh | 19 +--- 12 files changed, 218 insertions(+), 155 deletions(-) create mode 100644 .github/workflows/stale.yml diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 5a2e8e9a7..6149103a0 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -29,18 +29,19 @@ inputs: default: 'minimal' outputs: + # MISE_PATH, MISE_ENV, and PYTHON_PATH are typically in uppercase and may be case sensitive in some environments MISE_PATH: description: Path to mise executable value: ${{ steps.mise-outputs.outputs.MISE_PATH }} MISE_ENV: description: Mise environment name value: ${{ steps.mise-outputs.outputs.MISE_ENV }} - PROFILE: + profile: description: Profile used for setup - value: ${{ steps.mise-outputs.outputs.PROFILE }} - PYTHON_VERSION: + value: ${{ steps.mise-outputs.outputs.profile }} + python_version: description: Python version installed - value: ${{ steps.mise-outputs.outputs.PYTHON_VERSION }} + value: ${{ steps.mise-outputs.outputs.python_version }} PYTHON_PATH: description: Path to Python executable value: ${{ steps.mise-outputs.outputs.PYTHON_PATH }} @@ -61,13 +62,32 @@ runs: shell: bash run: ./scripts/dev-env/ci-free-disk-space.sh + - name: Set up Environment for Free-Threaded Python + shell: bash + run: | + # We need to do this for all python versions so that the environment variable is set + # Because we can't use inputs.python-version after this step + if [[ "${{ inputs.python-version }}" == *"t" ]]; then + echo "Setting up environment for free-threaded Python version '${{ inputs.python-version }}'..." + echo "MISE_PYTHON_PRECOMPILED_FLAVOR=freethreaded+pgo-full" >> $GITHUB_ENV + echo "MISE_PYTHON_COMPILE=0" >> $GITHUB_ENV + python_version_clean="${{ inputs.python-version::-1 }}" + echo "MISE_PYTHON_VERSION=${python_version_clean}" >> $GITHUB_ENV + echo "python_version=${python_version_clean}" >> $GITHUB_ENV + uv_python_version="cpython-${python_version_clean}+freethreaded" + echo "UV_PYTHON=${uv_python_version}" >> $GITHUB_ENV + else + echo "python_version=${{ inputs.python-version }}" >> $GITHUB_ENV + echo "UV_PYTHON=${{ inputs.python-version }}" >> $GITHUB_ENV + fi + - name: Setup Mise for Minimal Profile if: inputs.profile == 'minimal' uses: jdx/mise-action@eb508e65f0eb73d4fc9fc9505569833136217cc9 env: MISE_YES: 1 MISE_EXPERIMENTAL: 1 - UV_PYTHON: ${{ inputs.python-version }} + UV_PYTHON: ${{ env.UV_PYTHON }} with: github_token: ${{ inputs.github-token }} experimental: true @@ -83,7 +103,7 @@ runs: MISE_YES: 1 MISE_EXPERIMENTAL: 1 MISE_ENV: dev - UV_PYTHON: ${{ inputs.python-version }} + UV_PYTHON: ${{ env.UV_PYTHON }} with: github_token: ${{ inputs.github-token }} experimental: true @@ -106,7 +126,7 @@ runs: MISE_YES: 1 MISE_EXPERIMENTAL: 1 MISE_ENV: dev - UV_PYTHON: ${{ inputs.python-version }} + UV_PYTHON: ${{ env.UV_PYTHON }} with: github_token: ${{ inputs.github-token }} experimental: true @@ -144,8 +164,6 @@ runs: mise_bin_dir="$(dirname "$MISE_PATH")" python_path="$(which python)" python_bin_dir="$(dirname "$python_path")" - NEWPATH="$mise_bin_dir:$python_bin_dir:$PATH" - echo "NEWPATH=${NEWPATH}" >> "$GITHUB_OUTPUT" - echo "PROFILE=${{ inputs.profile }}" >> "$GITHUB_OUTPUT" - echo "PYTHON_VERSION=$(python --version | awk '{print $2}')" >> "$GITHUB_OUTPUT" + echo "profile=${{ inputs.profile }}" >> "$GITHUB_OUTPUT" + echo "python_version=$(python --version | awk '{print $2}')" >> "$GITHUB_OUTPUT" echo "PYTHON_PATH=$python_path" >> "$GITHUB_OUTPUT" diff --git a/.github/actions/setup-python-env/action.yml b/.github/actions/setup-python-env/action.yml index 4ab05b65c..8ad9b8db6 100644 --- a/.github/actions/setup-python-env/action.yml +++ b/.github/actions/setup-python-env/action.yml @@ -28,9 +28,9 @@ outputs: PYTHON_PATH: description: Path to the Python executable value: ${{ steps.python-setup.outputs.PYTHON_PATH }} - UV_PATH: + uv_path: description: Path to uv executable - value: ${{ steps.python-setup.outputs.UV_PATH }} + value: ${{ steps.python-setup.outputs.uv_path }} runs: using: composite @@ -58,5 +58,5 @@ runs: python -m pip install --upgrade pip setuptools wheel python -m pip install uv echo "PYTHON_PATH=$(which python)" >> "$GITHUB_OUTPUT" - echo "UV_PATH=$(which uv)" >> "$GITHUB_OUTPUT" + echo "uv_path=$(which uv)" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/_reusable-lint.yml b/.github/workflows/_reusable-lint.yml index 33b84031a..2904934df 100644 --- a/.github/workflows/_reusable-lint.yml +++ b/.github/workflows/_reusable-lint.yml @@ -33,7 +33,7 @@ jobs: name: Lint and Format runs-on: ubuntu-latest env: - MISE_PYTHON: ${{ inputs.python-version }} + MISE_PYTHON_VERSION: ${{ inputs.python-version }} UV_PYTHON: ${{ inputs.python-version }} steps: - name: Checkout code diff --git a/.github/workflows/_reusable-test.yml b/.github/workflows/_reusable-test.yml index 23c402b6c..e24505a9c 100644 --- a/.github/workflows/_reusable-test.yml +++ b/.github/workflows/_reusable-test.yml @@ -69,7 +69,7 @@ jobs: - python-version: "3.14t" experimental: true env: - MISE_PYTHON: ${{ matrix.python-version }} + MISE_PYTHON_VERSION: ${{ matrix.python-version }} UV_PYTHON: ${{ matrix.python-version }} steps: - name: Checkout code @@ -78,7 +78,6 @@ jobs: fetch-depth: 3 - name: Setup Python environment with Mise - if: ${{ matrix.experimental == false }} uses: ./.github/actions/setup-mise-env with: python-version: ${{ matrix.python-version }} @@ -87,12 +86,14 @@ jobs: skip-checkout: true id: setup-mise - name: Run quality checks - if: ${{ inputs.run-quality-checks && matrix.experimental == false }} - run: mise run check 2>&1 + if: ${{ inputs.run-quality-checks }} + run: | + doctor_output="$(mise doctor)" + echo "$doctor_output" + mise run check 2>&1 continue-on-error: true - name: Run tests with coverage - if: ${{ matrix.experimental == false }} run: mise run test-cov -m "${{ inputs.test-markers }}" - name: Upload coverage to Codecov if: ${{ inputs.upload-coverage && matrix.python-version == '3.12' }} @@ -111,20 +112,3 @@ jobs: test-results.xml coverage.xml if-no-files-found: warn - - # Experimental Python versions (free-threaded) - - name: Setup Experimental Python environment - if: ${{ matrix.experimental == true }} - uses: ./.github/actions/setup-python-env - with: - python-version: ${{ matrix.python-version }} - skip-checkout: true - - - name: Install test dependencies for Experimental Python - if: ${{ matrix.experimental == true }} - run: uv sync --group test --resolution highest - - - name: Run test coverage for experimental Python - if: ${{ matrix.experimental == true }} - run: uv run pytest tests/ --cov=codeweaver --cov-report=xml --cov-report=term-missing --junit-xml=test-results.xml -v -m "${{ inputs.test-markers }}" - diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index cd919b4ac..3e96fff14 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -18,9 +18,6 @@ on: jobs: # The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot. copilot-setup-steps: - outputs: - MISE_PATH: ${{ steps.setup-mise.outputs.MISE_PATH }} - env: CODEWEAVER_VECTOR_STORE_URL: ${{ secrets.CODEWEAVER_VECTOR_STORE_URL }} QDRANT__SERVICE__API_KEY: ${{ secrets.QDRANT__SERVICE__API_KEY }} diff --git a/.github/workflows/mcp-registry-submit.yml b/.github/workflows/mcp-registry-submit.yml index 173780479..9a0d49477 100644 --- a/.github/workflows/mcp-registry-submit.yml +++ b/.github/workflows/mcp-registry-submit.yml @@ -127,35 +127,34 @@ jobs: # we need to sign the timestamp with the private key, which is in MCP_REGISTRY_KEY # MCP_REGISTRY_KEY is expected to be in PEM format, and it uses ed25519 algorithm # unfortunately, pkeyutl can only work with files because of how it has to buffer the input for signing - # shellcheck disable=SC2329 - indata="" - key_file="" - outfile="" - request_body="" + + # setup temporary files and cleanup + umask 077 + indata="$(mktemp)" + key_file="$(mktemp)" + outfile="$(mktemp)" + request_body="$(mktemp)" # shellcheck disable=SC2329 cleanup() { + # ensure sensitive files are securely deleted -- on ubuntu, shred should be available shred -u "$key_file" "$outfile" || rm -f "$key_file" "$outfile" - # these aren't sensitive, but let's keep things tidy + # these aren't sensitive, but let's keep things tidy: rm -f "$indata" "$request_body" } trap cleanup EXIT domain="knitli.com" - indata="$(mktemp)" - echo -n "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" > "$indata" + timestamp="$(date -u +"%Y-%m-%dT%H:%M:%SZ")" + echo -n "$timestamp" > "$indata" - umask 077 - key_file="$(mktemp)" echo "$MCP_REGISTRY_KEY" > "$key_file" - outfile="$(mktemp)" - + # it wasn't easy to figure out how to do ed25519 signing with openssl, but this is the correct incantation with recent versions: openssl pkeyutl -sign -inkey "$key_file" -out "$outfile" -rawin -in "$indata" || { echo "ERROR: Failed to sign timestamp"; exit 1; } signed_timestamp_hex="$(xxd -p "$outfile" | tr -d '\n')" - request_body="$(mktemp)" { echo -n '{"domain":"'"$domain"'",' echo -n '"signed_timestamp":"'"$signed_timestamp_hex"'",' - echo -n '"timestamp":"'"$(cat "$indata")"'"}' + echo -n '"timestamp":"'"$timestamp"'"}' } > "$request_body" echo "Logging in to MCP Registry..." response="$(curl --request POST \ diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 000000000..b9793da1c --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,30 @@ +# SPDX-FileCopyrightText: 2025 Knitli Inc. +# SPDX-FileContributor: Adam Poulemanos +# +# SPDX-License-Identifier: MIT OR Apache-2.0 + +name: "Stale Issues and PRs" +on: + schedule: + - cron: "0 11 * * *" + +permissions: + issues: write + pull-requests: write + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@997185467fa4f803885201cee163a9f38240193d + with: + days-before-stale: 7 + days-before-close: 3 + + any-of-issue-labels: "question,more info" + stale-issue-message: "This issue is stale, we will close it in 3 days if you don't reply." + close-issue-message: "This issue hasn't been active for 10 days, closing." + + any-of-pr-labels: "needs revision" + stale-pr-message: "This PR is stale, we will close it in 3 days if you don't reply." + close-pr-message: "This PR hasn't been active for 10 days, closing." diff --git a/.vscode/terminal.extra.zsh b/.vscode/terminal.extra.zsh index 97524ea97..35f2cbd01 100755 --- a/.vscode/terminal.extra.zsh +++ b/.vscode/terminal.extra.zsh @@ -14,21 +14,21 @@ full_setup() { print -P "%F{209}[codeweaver]%f %F{red}Failed to trust the Mise environment!%f" } mise run setup - # Skip 'mise run setup' to avoid circular activation } # Make sure Mise is installed and available print -P "%F{209}[codeweaver]%f Welcome to the%f %F{209}CodeWeaver%f development environment!" print -P "%F{209}[codeweaver]%f If you run into any issues, please visit %F{cyan}https://github.com/knitli/codeweaver/issues%f for assistance." -print -P "%F{209}[codeweaver]%f We're going to set up your environment now..." -REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")" -cd "$REPO_ROOT" || { - print -P "%F{209}[codeweaver]%f %F{red}Failed to change directory to the repository root!%f" -} + +# set a few aliases for convenience +alias mx='mise exec' +alias mr='mise run' + if command -v mise >/dev/null 2>&1; then # We have Mise installed, check if it's initialized for this workspace print -P "%F{209}[codeweaver]%f You're all set!" else + REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo "${PWD}")" # Mise is not installed, run the install script chmod -R +x "${REPO_ROOT}/scripts" || { print -P "%F{209}[codeweaver]%f %F{red}Failed to make install scripts executable!%f" diff --git a/.vscode/zsh/.zshrc b/.vscode/zsh/.zshrc index 340ba7799..5d1d62b3a 100644 --- a/.vscode/zsh/.zshrc +++ b/.vscode/zsh/.zshrc @@ -6,6 +6,27 @@ # VS Code workspace-local zshrc # Loaded because VS Code sets ZDOTDIR to this directory for integrated terminals. +typeset -i _mise_updated + +# replace default mise hook +function _mise_hook { + local diff=${__MISE_DIFF} + source <(command mise hook-env -s zsh) + [[ ${diff} == ${__MISE_DIFF} ]] + _mise_updated=$? +} + +_PROMPT="❱ " # or _PROMPT=${PROMPT} to keep the default + +function _prompt { + if (( ${_mise_updated} )); then + PROMPT='%F{blue}${_PROMPT}%f' + else + PROMPT='%(?.%F{green}${_PROMPT}%f.%F{red}${_PROMPT}%f)' + fi +} + + # Source repo dev shell init (idempotent), then hand off to user's normal zshrc. REPO_ROOT="${PWD}" if [[ -n "${VSCODE_CWD:-}" ]]; then @@ -17,6 +38,17 @@ if [[ -f "${REPO_ROOT}/scripts/dev-env/dev-shell-init.zsh" ]]; then source "${REPO_ROOT}/scripts/dev-env/dev-shell-init.zsh" fi +if [[ -f "${ZDOTDIR:-${HOME}}/.vscode/terminal.extra.zsh" ]]; then + source "${ZDOTDIR:-${HOME}}/.vscode/terminal.extra.zsh" +fi + +# PERSONALIZE: You can add more *local* customizations in .vscode/terminal.local.zsh +# (This file is gitignored so it won't be checked in.) +if [[ -f "${ZDOTDIR:-${HOME}}/.vscode/terminal.local.zsh" ]]; then + source "${ZDOTDIR:-${HOME}}/.vscode/terminal.local.zsh" +fi + + # After workspace init, source the user's real ~/.zshrc if it exists if [[ -f "${HOME}/.zshrc" ]]; then # Avoid infinite loop if ZDOTDIR points here @@ -27,8 +59,5 @@ if [[ -f "${HOME}/.zshrc" ]]; then source "${HOME}/.zshrc" fi -# PERSONALIZE: You can add more *local* customizations in .vscode/terminal.local.zsh -# (This file is gitignored so it won't be checked in.) -if [[ -f "${ZDOTDIR:-${HOME}}/.vscode/terminal.local.zsh" ]]; then - source "${ZDOTDIR:-${HOME}}/.vscode/terminal.local.zsh" -fi \ No newline at end of file +add-zsh-hook precmd _prompt + diff --git a/mise.dev.toml b/mise.dev.toml index 2aee2d484..08781f0c6 100644 --- a/mise.dev.toml +++ b/mise.dev.toml @@ -8,24 +8,29 @@ uv_venv_auto = true compile = true [tools] -hk = "latest" +hk = { version = "latest", postinstall = "hk install --mise" } pkl = "latest" usage = "latest" uv = "latest" # Quality & validation tools "pipx:reuse" = "latest" # License validation -"pipx:tombi" = "latest" +"aqua:tombi-toml/tombi" = "latest" "pipx:ty" = "latest" # Type checking ruff = "latest" # Python linting/formatting +[env] +_.python.venv = { path = ".venv", create = true, uv_create_args = [ + "--seed", + "--keyring-provider", + "subprocess", + "--python", + '{{ get_env(name="MISE_PYTHON_VERSION", default="3.13") }}' +] } + [hooks] [hooks.enter] env.MISE_EXPERIMENTAL = "1" script = ''' -# PROFILE is set to 'dev' in a cloud CI environment for cloud agents. 'enter' tends to break there. -if [ "$PROFILE" != "dev" ]; then - mise //:enter -fi ''' [tasks] @@ -33,6 +38,11 @@ fi silent = "stdout" tools.uv = "latest" run = ''' +# profile is set to 'dev' in a cloud CI environment for cloud agents. 'enter' tends to break there. +if [ "$profile" != "dev" ] && [ "$CI" != "true" ]; then + # don't run + exit 0 +fi case "$python_path" in *.venv/bin/python*) # Already in venv, do nothing @@ -46,6 +56,10 @@ esac run_windows = ''' @echo off set "pythonPath=%python_path%" +if not %profile%==dev if not "%CI%"=="true" ( + rem don't run + exit /b 0 +) if not "%pythonPath%"=="%pythonPath:.venv\Scripts\python=%" ( rem Already in venv, do nothing ) else ( @@ -61,6 +75,44 @@ ACTIVE_SHELL = '''{{ exec(command='basename "$SHELL" 2>/dev/null || echo zsh') } python_path = '''{{ exec(command='command -v python 2>/dev/null || echo ""') }}''' MISE_EXPERIMENTAL = "1" +[tasks.cloud-setup] +run = [ + "echo \"[codeweaver] Setting up cloud development environment...\"", + "ln -sf AGENTS.md CLAUDE.md", + '''if ! command -v mise &>/dev/null; then + if [ -d "$HOME/.local/share/mise" ] || [ -d "$HOME/.mise" ] || [ -f "$HOME/.local/bin/mise" ]; then + export PATH="$HOME/.local/bin:$HOME/.mise/bin:$HOME/.local/share/mise/bin:$PATH" + if [ "ACTIVE_SHELL" = "bash" ] || [ "ACTIVE_SHELL" = "zsh" ] && ! grep -q "mise activate" "$HOME/.${ACTIVE_SHELL}rc"; then + echo "eval \"$(mise activate \"${ACTIVE_SHELL}\")\" 2>&1 || true" >> "$HOME/.${ACTIVE_SHELL}rc" + fi + else + chmod +x scripts/dev-env/install-mise.sh 2>&1 || true + ./scripts/dev-env/install-mise.sh 2>&1 || true + fi + fi''', + '''mise trust --all 2>&1 || { echo "[WARNING] mise trust --all failed during cloud-setup" >&2; }''', + '''mise install 2>&1 || { echo "[WARNING] mise install failed during cloud-setup" >&2; }''', + "mise x uv@latest -- uv venv --allow-existing --seed --keyring-provider subprocess --python {{ get_env(name='MISE_PYTHON_VERSION', default='3.13') }} .venv 2>&1", + ". .venv/bin/activate 2>&1 || true", + "mise x uv@latest -- uv sync --extra full --group dev --group test 2>&1", + "git config include.path .gitconfig 2>&1 || true", + '''bash -c " + ignore_files=('src/codeweaver/_version.py' 'coverage.xml' 'test-results.xml') + for file in \"\${ignore_files[@]}\"; do + if ! grep -qx \"\$file\" .git/info/exclude; then + echo \"\$file\" >> .git/info/exclude 2>&1 + fi + done + "''', + "echo \"[codeweaver] Cloud development environment setup complete!\"", +] + +[tasks.cloud-setup.env] +ACTIVE_SHELL = '''{{ exec(command='basename "$SHELL" 2>/dev/null || echo bash') }}''' +MISE_EXPERIMENTAL = "1" +MISE_ENV = "dev" +MISE_YES = "1" + [tasks.update-dependencies] tools.uv = "latest" depends = ["source"] @@ -110,7 +162,7 @@ uv run pytest tests/ -f --tb=short # Building and packaging run = ''' echo "${CW_PREFIX} Building package..." -uv build && +uv build 2>&1 && echo "${CW_PREFIX} ✅ Package built successfully!" ''' run_windows = ''' diff --git a/mise.toml b/mise.toml index 733e94d89..b258571c0 100644 --- a/mise.toml +++ b/mise.toml @@ -28,6 +28,8 @@ _.path = [ ] MISE_ENV = '''{% if get_env(name="CI", default="") == "true" %}""{% else %}dev{% endif %}''' CW_PREFIX = '''{% if get_env(name="CI", default="") == "true" %}[codeweaver]{% elif get_env(name="TERM", default="xterm-256color") == "*truecolor*" %}\033[38;2;181;108;48;m[codeweaver]\033[0m{% else %}\033[38;5;131m[codeweaver]\033[0m{% endif %}''' +# this is a bit redundant but it makes it easier to override in CI environments +MISE_PYTHON_VERSION = '''{{ get_env(name="MISE_PYTHON_VERSION", default="3.13") }}''' [settings] idiomatic_version_file_enable_tools = [] @@ -40,12 +42,19 @@ uv_venv_create_args = [ "--keyring-provider", "subprocess", "--python", - "{{ get_env(name='MISE_PYTHON', default='3.13') }}", + "{{ get_env(name='MISE_PYTHON_VERSION', default='3.13') }}", ] [tools] # most tools are defined in mise.dev.toml to keep CI workflows lightweight -python = "3.13" +# Where needed, tools are defined at the task level here, which allows for more granular control +python = '''{{ get_env(name="MISE_PYTHON_VERSION", default="3.13") }}''' +uv = "latest" + +# Quick note for those unfamiliar with mise: +# - depite the namespace, tools prefixed with "pipx:" are installed via "uv" (I assume once upon a time they were installed with pipx before uv came along) +# - some tools have no prefix -- these are defined in mise's internal registry directly +# - The prefix refers to the "backend" used to install the tool -- most of the no-prefix tools are installed through `aqua` or github/gitlab releases, and failing that, `ubi`. Language-specific package managers (cargo/npm/go) are also used where appropriate. [tasks.info] description = "Print project information" @@ -82,7 +91,11 @@ run = ''' # Source the virtual environment echo "${CW_PREFIX} Sourcing virtual environment..." git rev-parse --show-toplevel || true -source .venv/bin/activate +if [ ! -d ".venv" ]; then + echo "${CW_PREFIX} ⚠️ \033[0;31mVirtual environment not found. We'll try to proceed, but things may break!\033[0m" + uvx venv --seed --keyring-provider subprocess --python {{ get_env(name='MISE_PYTHON_VERSION', default='3.13') }} .venv +fi +. .venv/bin/activate || echo "${CW_PREFIX} ⚠️ \033[0;31mFailed to source virtual environment.\033[0m" ''' run_windows = ''' echo [codeweaver] Sourcing virtual environment... @@ -95,12 +108,10 @@ git rev-parse --show-toplevel run = [ "echo \"${CW_PREFIX} Setting up development environment for the first time...\"", "mise set &>/dev/null", - "mise trust &>/dev/null", - "mise install &>/dev/null || true", - "hk install --mise &>/dev/null || true", + "mise trust --all &>/dev/null", + "mise install &>/dev/null || echo \"${CW_PREFIX} ⚠️ WARNING: mise install failed during setup.\"", "mise //:venv &>/dev/null", "mise //:sync &>/dev/null", - "mise env &>/dev/null || true", "git config include.path .gitconfig &>/dev/null || true", "echo 'src/codeweaver/_version.py' >> .git/info/exclude", "echo 'coverage.xml' >> .git/info/exclude", @@ -111,9 +122,8 @@ run = [ run_windows = [ "echo [codeweaver] Setting up development environment for the first time...", "mise set > NUL 2>&1", - "mise trust > NUL 2>&1", - "mise install > NUL 2>&1 || echo.", - "hk install --mise > NUL 2>&1 || echo.", + "mise trust --all > NUL 2>&1", + "mise install > NUL 2>&1 || echo \"[codeweaver] WARNING: mise install failed during setup.\"", "mise //:venv > NUL 2>&1", "mise //:sync > NUL 2>&1", "mise env > NUL 2>&1", @@ -135,45 +145,6 @@ ACTIVE_SHELL = '''{{ exec(command='basename "$SHELL" 2>/dev/null || echo zsh') } [tasks.setup.tools] uv = "latest" -[tasks.cloud-setup] -run = [ - "echo \"[codeweaver] Setting up cloud development environment...\"", - "ln -sf AGENTS.md CLAUDE.md", - '''if ! command -v mise &>/dev/null; then - if [ -d "$HOME/.local/share/mise" ] || [ -d "$HOME/.mise" ] || [ -f "$HOME/.local/bin/mise" ]; then - export PATH="$HOME/.local/bin:$HOME/.mise/bin:$HOME/.local/share/mise/bin:$PATH" - if ! grep -q "mise activate" "$HOME/.bashrc"; then - echo "eval \"$(mise activate \"${ACTIVE_SHELL:-bash}\")\" 2>&1 || true" >> "$HOME/.bashrc" - fi - else - chmod +x scripts/dev-env/install-mise.sh 2>&1 || true - ./scripts/dev-env/install-mise.sh 2>&1 || true - fi - fi''', - '''mise -y trust --all 2>&1 || { echo "[WARNING] mise -y trust --all failed during cloud-setup" >&2; }''', - '''mise install 2>&1 || { echo "[WARNING] mise install failed during cloud-setup" >&2; }''', - "hk install --mise 2>&1 || mise x hk@latest -- hk install --mise 2>&1 || true", - "mise x uv@latest -- uv venv --allow-existing --seed --keyring-provider subprocess --python {{ get_env(name='MISE_PYTHON', default='3.13') }} .venv 2>&1", - ". .venv/bin/activate 2>&1 || true", - "mise x uv@latest -- uv sync --group dev --group test 2>&1", - "git config include.path .gitconfig 2>&1 || true", - '''bash -c " - ignore_files=('src/codeweaver/_version.py' 'coverage.xml' 'test-results.xml') - for file in \"\${ignore_files[@]}\"; do - if ! grep -qx \"\$file\" .git/info/exclude; then - echo \"\$file\" >> .git/info/exclude 2>&1 - fi - done - "''', - "echo \"[codeweaver] Cloud development environment setup complete!\"", -] - -[tasks.cloud-setup.env] -ACTIVE_SHELL = '''{{ exec(command='basename "$SHELL" 2>/dev/null || echo bash') }}''' -MISE_EXPERIMENTAL = "1" -MISE_ENV = "dev" -MISE_YES = "1" - [tasks.fix-python] tools.uv = "latest" tools.ast-grep = "latest" @@ -210,7 +181,7 @@ hk check tools.uv = "latest" run = ''' echo "Running linting checks..." -if [[ "$CI" == "true" ]]; then +if [ "$CI" = "true" ]; then uv run ruff check . --output-format=github else uv run ruff check . @@ -236,10 +207,9 @@ hk fix ''' [tasks.format.tools] -"cargo:rust-parallel" = "latest" -"cargo:typos" = "latest" +"aqua:crates-ci/typos" = "latest" "pipx:reuse" = "latest" -"pipx:tombi" = "latest" +"aqua:tombi-toml/tombi" = "latest" "pipx:ty" = "latest" actionlint = "latest" hk = "latest" @@ -254,13 +224,13 @@ echo "${CW_PREFIX} Applying formatting...hold onto your butts 🚬...🦖 " # mise -y //:fix-ruff-patterns || { # there are some bugs to work out # echo "${CW_PREFIX} ⚠️ \033[0;32mRuff pattern fixer encountered issues.\033[0m"} uv run ruff format . -files="$(git ls-files "*.yaml" "*.yml" "*.json" 2>/dev/null)" -if [ -n "$files" ]; then - echo "$files" | rust-parallel -d stderr -i - --no-run-if-empty yq -iP --indent=2 "." || true +yaml_files="$(git ls-files "*.yaml" "*.yml" "*.json" 2>/dev/null)" +if [ -n "$yaml_files" ]; then + printf '%s\n' $yaml_files | xargs -n1 yq -iP --indent=2 eval "." 2>/dev/null || true fi -files="$(git ls-files "*.toml" 2>/dev/null)" -if [ -n "$files" ]; then - tombi format $files 2>/dev/null || true +toml_files="$(git ls-files "*.toml" 2>/dev/null)" +if [ -n "$toml_files" ]; then + tombi format $toml_files 2>/dev/null || true fi ''' run_windows = ''' @@ -275,9 +245,8 @@ for /f "delims=" %%f in ('git ls-files "*.toml" 2^>NUL') do ( ''' [tasks.format-fix.tools] -"cargo:rust-parallel" = "latest" -"pipx:tombi" = "latest" -"yq" = "latest" +"aqua:tombi-toml/tombi" = "latest" +yq = "latest" uv = "latest" [tasks.graph] @@ -296,7 +265,7 @@ env.MISE_EXPERIMENTAL = "1" tools.uv = "latest" run = ''' echo "${CW_PREFIX} Setting up Python virtual environment..." -uv venv --allow-existing --seed --keyring-provider subprocess --python 3.13 --refresh .venv && +uv venv --allow-existing --seed --keyring-provider subprocess --python {{ get_env(name="MISE_PYTHON_VERSION", default="3.13") }} --refresh .venv && echo "${CW_PREFIX} ✅ Virtual environment is ready!" source .venv/bin/activate || echo "${CW_PREFIX} ⚠️ \033[0;31mFailed to source virtual environment.\033[0m" echo "${CW_PREFIX} Running dependency sync..." @@ -304,7 +273,7 @@ mise //:sync & ''' run_windows = ''' echo [codeweaver] Setting up Python virtual environment... -uv venv --allow-existing --seed --keyring-provider subprocess --python 3.13 --refresh .venv +uv venv --allow-existing --seed --keyring-provider subprocess --python {{ get_env(name="MISE_PYTHON_VERSION", default="3.13") }} --refresh .venv if %ERRORLEVEL% equ 0 ( echo [codeweaver] Virtual environment is ready! call .venv\Scripts\activate.bat @@ -318,7 +287,7 @@ start /b mise //:sync [tasks.test] # Testing -tools.python = '''{{ get_env(name="MISE_PYTHON", default="3.13") }}''' +tools.python = '''{{ get_env(name="MISE_PYTHON_VERSION", default="3.13") }}''' tools.uv = "latest" usage = ''' args "[dir]" help="directory to test" default="tests/" @@ -335,7 +304,7 @@ uv run pytest "%usage_dir%" %usage_marks:~-3% -v %* [tasks.test-cov] tools.uv = "latest" -tools.python = '''{{ get_env(name="MISE_PYTHON", default="3.13") }}''' +tools.python = '''{{ get_env(name="MISE_PYTHON_VERSION", default="3.13") }}''' run = ''' echo "${CW_PREFIX} Running tests with coverage..." uv sync --group test --inexact diff --git a/scripts/dev-env/dev-shell-init.zsh b/scripts/dev-env/dev-shell-init.zsh index ef978827e..f2174345a 100755 --- a/scripts/dev-env/dev-shell-init.zsh +++ b/scripts/dev-env/dev-shell-init.zsh @@ -18,7 +18,7 @@ __cw_this_file="${(%):-%N}" __cw_dirname() { builtin cd -- "${1%/*}" 2>/dev/null && pwd; } __cw_script_dir="$(__cw_dirname "$__cw_this_file")" -# Compute repo root (script lives in /scripts) +# Compute repo root (script lives in /scripts/dev-env/) if [[ -n "$__cw_script_dir" ]]; then REPO_ROOT="$(builtin cd "${__cw_script_dir}/../.." 2>/dev/null && pwd)" fi @@ -44,19 +44,4 @@ if [[ ! -f "${_cw_venv_activate}" && -z "${CODEWEAVER_SILENT_SHELL:-}" ]]; then print -P "%F{yellow}[codeweaver]%f Create it with: %F{green}mise run venv "$REPO_ROOT/.venv" %f" fi -# Source optional workspace extras if provided -_cw_extras="${REPO_ROOT}/.vscode/terminal.extra.zsh" -if [[ -f "${_cw_extras}" ]]; then - # shellcheck disable=SC1090 - source "${_cw_extras}" -fi - -# source optional (per-user) local workspace extras if provided -# this file is gitignored -_cw_local="${REPO_ROOT}/.vscode/terminal.local.zsh" -if [[ -f "${_cw_local}" ]]; then - # shellcheck disable=SC1090 - source "${_cw_local}" -fi - -unset __cw_this_file __cw_script_dir _cw_repo_venv_path _cw_venv_activate _cw_extras +unset __cw_this_file __cw_script_dir _cw_repo_venv_path _cw_venv_activate From 3dfa0bde7b7d40717c2d02c4bd694ebf96313476 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sun, 7 Dec 2025 22:54:45 -0500 Subject: [PATCH 36/61] fix: fixed a malformed block in setup-mise-env, consolidated freethreaded handling into normal workflows using environment variables --- .github/actions/setup-mise-env/action.yml | 41 +++++++++++++++-------- .github/workflows/_reusable-test.yml | 8 +++++ 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 6149103a0..0ffd0b5a5 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -45,6 +45,12 @@ outputs: PYTHON_PATH: description: Path to Python executable value: ${{ steps.mise-outputs.outputs.PYTHON_PATH }} + MISE_PYTHON_VERSION: + description: Python version used by mise + value: ${{ steps.mise-outputs.outputs.MISE_PYTHON_VERSION }} + MISE_PYTHON_PRECOMPILED_FLAVOR: + description: Precompiled flavor used by mise (if any) + value: ${{ steps.mise-outputs.outputs.MISE_PYTHON_PRECOMPILED_FLAVOR }} runs: using: composite @@ -67,18 +73,19 @@ runs: run: | # We need to do this for all python versions so that the environment variable is set # Because we can't use inputs.python-version after this step - if [[ "${{ inputs.python-version }}" == *"t" ]]; then - echo "Setting up environment for free-threaded Python version '${{ inputs.python-version }}'..." + python_version="${{ inputs.python-version }}" + if [[ "$python_version" == *"t" ]]; then + echo "Setting up environment for free-threaded Python version '${python_version}'..." echo "MISE_PYTHON_PRECOMPILED_FLAVOR=freethreaded+pgo-full" >> $GITHUB_ENV echo "MISE_PYTHON_COMPILE=0" >> $GITHUB_ENV - python_version_clean="${{ inputs.python-version::-1 }}" + python_version_clean="${python_version:0:-1}" echo "MISE_PYTHON_VERSION=${python_version_clean}" >> $GITHUB_ENV echo "python_version=${python_version_clean}" >> $GITHUB_ENV uv_python_version="cpython-${python_version_clean}+freethreaded" echo "UV_PYTHON=${uv_python_version}" >> $GITHUB_ENV else - echo "python_version=${{ inputs.python-version }}" >> $GITHUB_ENV - echo "UV_PYTHON=${{ inputs.python-version }}" >> $GITHUB_ENV + echo "python_version=$python_version" >> $GITHUB_ENV + echo "UV_PYTHON=$python_version" >> $GITHUB_ENV fi - name: Setup Mise for Minimal Profile @@ -104,6 +111,9 @@ runs: MISE_EXPERIMENTAL: 1 MISE_ENV: dev UV_PYTHON: ${{ env.UV_PYTHON }} + MISE_PYTHON_COMPILE: 0 + MISE_PYTHON_PRECOMPILED_FLAVOR: ${{ env.MISE_PYTHON_PRECOMPILED_FLAVOR || '' }} + MISE_PYTHON_VERSION: ${{ env.python_version }} with: github_token: ${{ inputs.github-token }} experimental: true @@ -127,6 +137,8 @@ runs: MISE_EXPERIMENTAL: 1 MISE_ENV: dev UV_PYTHON: ${{ env.UV_PYTHON }} + MISE_PYTHON_COMPILE: 0 + MISE_PYTHON_PRECOMPILED_FLAVOR: ${{ env.MISE_PYTHON_PRECOMPILED_FLAVOR || '' }} with: github_token: ${{ inputs.github-token }} experimental: true @@ -144,21 +156,20 @@ runs: MISE_EXPERIMENTAL: 1 MISE_YES: 1 MISE_GITHUB_TOKEN: ${{ inputs.github-token }} + MISE_PYTHON_COMPILE: 0 + MISE_PYTHON_PRECOMPILED_FLAVOR: ${{ env.MISE_PYTHON_PRECOMPILED_FLAVOR || '' }} + MISE_PYTHON_VERSION: ${{ env.python_version }} run: | - mise //:setup + + mise //:cloud-setup 2>&1 - name: Set outputs shell: bash id: mise-outputs + env: + MISE_PYTHON_VERSION: ${{ env.python_version }} + MISE_PYTHON_PRECOMPILED_FLAVOR: ${{ env.MISE_PYTHON_PRECOMPILED_FLAVOR || '' }} run: | - # Add mise to PATH since env export is disabled - if [ "${{ inputs.profile }}" = "dev" ]; then - echo "MISE_ENV=dev" >> "$GITHUB_OUTPUT" - mise //:cloud-setup 2>&1 - else - echo "MISE_ENV=" >> "$GITHUB_OUTPUT" - fi - # setup PATH MISE_PATH="$(which mise)" echo "MISE_PATH=$MISE_PATH" >> "$GITHUB_OUTPUT" mise_bin_dir="$(dirname "$MISE_PATH")" @@ -167,3 +178,5 @@ runs: echo "profile=${{ inputs.profile }}" >> "$GITHUB_OUTPUT" echo "python_version=$(python --version | awk '{print $2}')" >> "$GITHUB_OUTPUT" echo "PYTHON_PATH=$python_path" >> "$GITHUB_OUTPUT" + echo "MISE_PYTHON_VERSION=${MISE_PYTHON_VERSION}" >> "$GITHUB_OUTPUT" + echo "MISE_PYTHON_PRECOMPILED_FLAVOR=${MISE_PYTHON_PRECOMPILED_FLAVOR}" >> "$GITHUB_OUTPUT" \ No newline at end of file diff --git a/.github/workflows/_reusable-test.yml b/.github/workflows/_reusable-test.yml index e24505a9c..3c6232d96 100644 --- a/.github/workflows/_reusable-test.yml +++ b/.github/workflows/_reusable-test.yml @@ -87,6 +87,10 @@ jobs: id: setup-mise - name: Run quality checks if: ${{ inputs.run-quality-checks }} + env: + MISE_PYTHON_VERSION: ${{ steps.setup-mise.outputs.MISE_PYTHON_VERSION }} + MISE_PYTHON_PRECOMPILED_FLAVOR: ${{ steps.setup-mise.outputs.MISE_PYTHON_PRECOMPILED_FLAVOR }} + MISE_PYTHON_COMPILE: 0 run: | doctor_output="$(mise doctor)" echo "$doctor_output" @@ -94,6 +98,10 @@ jobs: continue-on-error: true - name: Run tests with coverage + env: + MISE_PYTHON_VERSION: ${{ steps.setup-mise.outputs.MISE_PYTHON_VERSION }} + MISE_PYTHON_PRECOMPILED_FLAVOR: ${{ steps.setup-mise.outputs.MISE_PYTHON_PRECOMPILED_FLAVOR }} + MISE_PYTHON_COMPILE: 0 run: mise run test-cov -m "${{ inputs.test-markers }}" - name: Upload coverage to Codecov if: ${{ inputs.upload-coverage && matrix.python-version == '3.12' }} From 0a594b3a609147d6d1091233d190b34e3191707d Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Sun, 7 Dec 2025 23:04:48 -0500 Subject: [PATCH 37/61] fix: update hk installation in CI setup and add HK_MISE environment variable --- mise.dev.toml | 3 ++- mise.toml | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mise.dev.toml b/mise.dev.toml index 08781f0c6..747528de8 100644 --- a/mise.dev.toml +++ b/mise.dev.toml @@ -8,7 +8,7 @@ uv_venv_auto = true compile = true [tools] -hk = { version = "latest", postinstall = "hk install --mise" } +hk = { version = "latest" } pkl = "latest" usage = "latest" uv = "latest" @@ -92,6 +92,7 @@ run = [ fi''', '''mise trust --all 2>&1 || { echo "[WARNING] mise trust --all failed during cloud-setup" >&2; }''', '''mise install 2>&1 || { echo "[WARNING] mise install failed during cloud-setup" >&2; }''', + '''mise x hk@latest -- hk install --mise 2>&1 || { echo "[WARNING] hk install failed during cloud-setup" >&2; }''', "mise x uv@latest -- uv venv --allow-existing --seed --keyring-provider subprocess --python {{ get_env(name='MISE_PYTHON_VERSION', default='3.13') }} .venv 2>&1", ". .venv/bin/activate 2>&1 || true", "mise x uv@latest -- uv sync --extra full --group dev --group test 2>&1", diff --git a/mise.toml b/mise.toml index b258571c0..0cd50b351 100644 --- a/mise.toml +++ b/mise.toml @@ -30,6 +30,7 @@ MISE_ENV = '''{% if get_env(name="CI", default="") == "true" %}""{% else %}dev{% CW_PREFIX = '''{% if get_env(name="CI", default="") == "true" %}[codeweaver]{% elif get_env(name="TERM", default="xterm-256color") == "*truecolor*" %}\033[38;2;181;108;48;m[codeweaver]\033[0m{% else %}\033[38;5;131m[codeweaver]\033[0m{% endif %}''' # this is a bit redundant but it makes it easier to override in CI environments MISE_PYTHON_VERSION = '''{{ get_env(name="MISE_PYTHON_VERSION", default="3.13") }}''' +HK_MISE = "1" [settings] idiomatic_version_file_enable_tools = [] From 2988ad7333f3d9b68946b5d3ecdce1d2d606b599 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Mon, 8 Dec 2025 13:32:07 -0500 Subject: [PATCH 38/61] fix: update CI workflows and environment setup, remove unused variables --- .github/actions/setup-mise-env/action.yml | 67 ++++++++++++----------- .github/workflows/_reusable-test.yml | 4 -- mise.toml | 2 +- pyproject.toml | 2 +- uv.lock | 8 +-- 5 files changed, 42 insertions(+), 41 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 0ffd0b5a5..7c697e726 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -48,9 +48,6 @@ outputs: MISE_PYTHON_VERSION: description: Python version used by mise value: ${{ steps.mise-outputs.outputs.MISE_PYTHON_VERSION }} - MISE_PYTHON_PRECOMPILED_FLAVOR: - description: Precompiled flavor used by mise (if any) - value: ${{ steps.mise-outputs.outputs.MISE_PYTHON_PRECOMPILED_FLAVOR }} runs: using: composite @@ -63,7 +60,10 @@ runs: - name: Install system dependencies shell: bash run: | - sudo apt-get update && sudo apt-get install -y curl git readline-common lzma bzip2 libbz2-dev + # ensure build-python dependencies are installed + sudo apt-get update && sudo apt-get install -y curl git build-essential libssl-dev zlib1g-dev \ + libbz2-dev libreadline-dev libsqlite3-dev libncursesw5-dev xz-utils tk-dev libxml2-dev \ + libxmlsec1-dev libffi-dev liblzma-dev libzstd-dev - name: Free up disk space shell: bash run: ./scripts/dev-env/ci-free-disk-space.sh @@ -71,22 +71,21 @@ runs: - name: Set up Environment for Free-Threaded Python shell: bash run: | - # We need to do this for all python versions so that the environment variable is set - # Because we can't use inputs.python-version after this step - python_version="${{ inputs.python-version }}" - if [[ "$python_version" == *"t" ]]; then - echo "Setting up environment for free-threaded Python version '${python_version}'..." - echo "MISE_PYTHON_PRECOMPILED_FLAVOR=freethreaded+pgo-full" >> $GITHUB_ENV - echo "MISE_PYTHON_COMPILE=0" >> $GITHUB_ENV - python_version_clean="${python_version:0:-1}" - echo "MISE_PYTHON_VERSION=${python_version_clean}" >> $GITHUB_ENV - echo "python_version=${python_version_clean}" >> $GITHUB_ENV - uv_python_version="cpython-${python_version_clean}+freethreaded" - echo "UV_PYTHON=${uv_python_version}" >> $GITHUB_ENV - else - echo "python_version=$python_version" >> $GITHUB_ENV - echo "UV_PYTHON=$python_version" >> $GITHUB_ENV + if [[ "${inputs.python-version}" != *t ]]; then + echo "Using standard Python version ${inputs.python-version}..." + echo "MISE_PYTHON_VERSION=${inputs.python-version}" >> "$GITHUB_ENV" + echo "UV_PYTHON=${inputs.python-version}" >> "$GITHUB_ENV" + exit 0 fi + echo "Setting up environment for free-threaded Python ${inputs.python-version}..." + python_version="${inputs.python-version}" + base_version="${python_version%t}" + echo "Base version: ${base_version}" + # I couldn't get Mise's handling of free-threaded Python versions to work correctly... + # So, instead, we'll let mise install the base version, and use uv to get the free-threaded version + # and then sync uv and mise and tell mise to use that version + echo "MISE_PYTHON_VERSION=${base_version}" >> "$GITHUB_ENV" + echo "UV_PYTHON=${base_version}+freethreaded" >> "$GITHUB_ENV" - name: Setup Mise for Minimal Profile if: inputs.profile == 'minimal' @@ -111,8 +110,6 @@ runs: MISE_EXPERIMENTAL: 1 MISE_ENV: dev UV_PYTHON: ${{ env.UV_PYTHON }} - MISE_PYTHON_COMPILE: 0 - MISE_PYTHON_PRECOMPILED_FLAVOR: ${{ env.MISE_PYTHON_PRECOMPILED_FLAVOR || '' }} MISE_PYTHON_VERSION: ${{ env.python_version }} with: github_token: ${{ inputs.github-token }} @@ -137,8 +134,6 @@ runs: MISE_EXPERIMENTAL: 1 MISE_ENV: dev UV_PYTHON: ${{ env.UV_PYTHON }} - MISE_PYTHON_COMPILE: 0 - MISE_PYTHON_PRECOMPILED_FLAVOR: ${{ env.MISE_PYTHON_PRECOMPILED_FLAVOR || '' }} with: github_token: ${{ inputs.github-token }} experimental: true @@ -147,6 +142,21 @@ runs: cache_key_prefix: ${{ inputs.profile }} env: false id: mise-setup-dev + - name: Insert Free-Threaded Python into Dev Profile + if: inputs.profile == 'dev' && startsWith(inputs.python-version, '3.') && endsWith(inputs.python-version, 't') + shell: bash + id: mise-setup-dev-insert + env: + MISE_PYTHON_VERSION: ${{ env.python_version }} + UV_PYTHON: ${{ env.UV_PYTHON }} + run: | + echo "Inserting free-threaded Python version $UV_PYTHON into dev profile..." + mise x uv@latest -- uv python install -U --default "cpython-${UV_PYTHON}" 2>&1 + minor_version="$(mise x uv@latest -- uv run -p "$UV_PYTHON" --no-config python -c 'import sys; print(sys.version_info.minor)' 2>/dev/null)" + mise sync python --uv + new_mise_python_version="${MISE_PYTHON_VERSION}.${minor_version}+freethreaded" + mise use "python@${new_mise_python_version}" 2>&1 + echo "MISE_PYTHON_VERSION=${new_mise_python_version}" >> "$GITHUB_ENV" - name: Activate Dev Profile Environment if: inputs.profile == 'dev' shell: bash @@ -156,19 +166,15 @@ runs: MISE_EXPERIMENTAL: 1 MISE_YES: 1 MISE_GITHUB_TOKEN: ${{ inputs.github-token }} - MISE_PYTHON_COMPILE: 0 - MISE_PYTHON_PRECOMPILED_FLAVOR: ${{ env.MISE_PYTHON_PRECOMPILED_FLAVOR || '' }} - MISE_PYTHON_VERSION: ${{ env.python_version }} + MISE_PYTHON_VERSION: ${{ env.MISE_PYTHON_VERSION }} run: | - mise //:cloud-setup 2>&1 - name: Set outputs shell: bash id: mise-outputs env: - MISE_PYTHON_VERSION: ${{ env.python_version }} - MISE_PYTHON_PRECOMPILED_FLAVOR: ${{ env.MISE_PYTHON_PRECOMPILED_FLAVOR || '' }} + MISE_PYTHON_VERSION: ${{ env.MISE_PYTHON_VERSION }} run: | MISE_PATH="$(which mise)" echo "MISE_PATH=$MISE_PATH" >> "$GITHUB_OUTPUT" @@ -178,5 +184,4 @@ runs: echo "profile=${{ inputs.profile }}" >> "$GITHUB_OUTPUT" echo "python_version=$(python --version | awk '{print $2}')" >> "$GITHUB_OUTPUT" echo "PYTHON_PATH=$python_path" >> "$GITHUB_OUTPUT" - echo "MISE_PYTHON_VERSION=${MISE_PYTHON_VERSION}" >> "$GITHUB_OUTPUT" - echo "MISE_PYTHON_PRECOMPILED_FLAVOR=${MISE_PYTHON_PRECOMPILED_FLAVOR}" >> "$GITHUB_OUTPUT" \ No newline at end of file + echo "MISE_PYTHON_VERSION=$MISE_PYTHON_VERSION" >> "$GITHUB_OUTPUT" \ No newline at end of file diff --git a/.github/workflows/_reusable-test.yml b/.github/workflows/_reusable-test.yml index 3c6232d96..d3fc82151 100644 --- a/.github/workflows/_reusable-test.yml +++ b/.github/workflows/_reusable-test.yml @@ -89,8 +89,6 @@ jobs: if: ${{ inputs.run-quality-checks }} env: MISE_PYTHON_VERSION: ${{ steps.setup-mise.outputs.MISE_PYTHON_VERSION }} - MISE_PYTHON_PRECOMPILED_FLAVOR: ${{ steps.setup-mise.outputs.MISE_PYTHON_PRECOMPILED_FLAVOR }} - MISE_PYTHON_COMPILE: 0 run: | doctor_output="$(mise doctor)" echo "$doctor_output" @@ -100,8 +98,6 @@ jobs: - name: Run tests with coverage env: MISE_PYTHON_VERSION: ${{ steps.setup-mise.outputs.MISE_PYTHON_VERSION }} - MISE_PYTHON_PRECOMPILED_FLAVOR: ${{ steps.setup-mise.outputs.MISE_PYTHON_PRECOMPILED_FLAVOR }} - MISE_PYTHON_COMPILE: 0 run: mise run test-cov -m "${{ inputs.test-markers }}" - name: Upload coverage to Codecov if: ${{ inputs.upload-coverage && matrix.python-version == '3.12' }} diff --git a/mise.toml b/mise.toml index 0cd50b351..3a8f65c86 100644 --- a/mise.toml +++ b/mise.toml @@ -268,7 +268,7 @@ run = ''' echo "${CW_PREFIX} Setting up Python virtual environment..." uv venv --allow-existing --seed --keyring-provider subprocess --python {{ get_env(name="MISE_PYTHON_VERSION", default="3.13") }} --refresh .venv && echo "${CW_PREFIX} ✅ Virtual environment is ready!" -source .venv/bin/activate || echo "${CW_PREFIX} ⚠️ \033[0;31mFailed to source virtual environment.\033[0m" +. .venv/bin/activate || echo "${CW_PREFIX} ⚠️ \033[0;31mFailed to source virtual environment.\033[0m" echo "${CW_PREFIX} Running dependency sync..." mise //:sync & ''' diff --git a/pyproject.toml b/pyproject.toml index eb002feff..eb55ff631 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -120,7 +120,7 @@ dependencies = [ "psutil>=7.1.3", # Core data models and validation "py-cpuinfo>=9.0.0", - "pydantic>=2.12.4", + "pydantic>=2.12.5", "pydantic-ai>=1.27.0", "pydantic-graph>=1.27.0", "pydantic-settings[toml,yaml]>=2.12.0", # Pulls: tomli>=2.0.1, pyyaml>=6.0.1 diff --git a/uv.lock b/uv.lock index c27da6f7a..4e86b8268 100644 --- a/uv.lock +++ b/uv.lock @@ -858,7 +858,7 @@ requires-dist = [ { name = "py-cpuinfo", marker = "extra == 'provider-fastembed'" }, { name = "py-cpuinfo", marker = "extra == 'provider-fastembed-gpu'" }, { name = "py-cpuinfo", marker = "extra == 'provider-sentence-transformers'" }, - { name = "pydantic", specifier = ">=2.12.4" }, + { name = "pydantic", specifier = ">=2.12.5" }, { name = "pydantic-ai", specifier = ">=1.27.0" }, { name = "pydantic-ai-slim", extras = ["anthropic"], marker = "extra == 'provider-anthropic'" }, { name = "pydantic-ai-slim", extras = ["bedrock"], marker = "extra == 'provider-bedrock'" }, @@ -3847,7 +3847,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.12.4" +version = "2.12.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -3855,9 +3855,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/96/ad/a17bc283d7d81837c061c49e3eaa27a45991759a1b7eae1031921c6bd924/pydantic-2.12.4.tar.gz", hash = "sha256:0f8cb9555000a4b5b617f66bfd2566264c4984b27589d3b845685983e8ea85ac", size = 821038, upload-time = "2025-11-05T10:50:08.59Z" } +sdist = { url = "https://files.pythonhosted.org/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/82/2f/e68750da9b04856e2a7ec56fc6f034a5a79775e9b9a81882252789873798/pydantic-2.12.4-py3-none-any.whl", hash = "sha256:92d3d202a745d46f9be6df459ac5a064fdaa3c1c4cd8adcfa332ccf3c05f871e", size = 463400, upload-time = "2025-11-05T10:50:06.732Z" }, + { url = "https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d", size = 463580, upload-time = "2025-11-26T15:11:44.605Z" }, ] [package.optional-dependencies] From d4eb4aaaea3d1fd3d8e3aa893c9f6baf2d60fca5 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> Date: Mon, 8 Dec 2025 13:49:47 -0500 Subject: [PATCH 39/61] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> --- .github/actions/setup-mise-env/action.yml | 4 ++-- .github/workflows/release.yml | 3 --- .vscode/terminal.extra.zsh | 2 +- .vscode/zsh/.zshrc | 5 ++++- mise.dev.toml | 10 ++++++---- mise.toml | 9 +++------ 6 files changed, 16 insertions(+), 17 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 7c697e726..3d54fd001 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -110,7 +110,7 @@ runs: MISE_EXPERIMENTAL: 1 MISE_ENV: dev UV_PYTHON: ${{ env.UV_PYTHON }} - MISE_PYTHON_VERSION: ${{ env.python_version }} + MISE_PYTHON_VERSION: ${{ env.MISE_PYTHON_VERSION }} with: github_token: ${{ inputs.github-token }} experimental: true @@ -147,7 +147,7 @@ runs: shell: bash id: mise-setup-dev-insert env: - MISE_PYTHON_VERSION: ${{ env.python_version }} + MISE_PYTHON_VERSION: ${{ env.MISE_PYTHON_VERSION }} UV_PYTHON: ${{ env.UV_PYTHON }} run: | echo "Inserting free-threaded Python version $UV_PYTHON into dev profile..." diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c5bc8bedc..5bdf2c626 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,9 +6,6 @@ name: Release on: push: - branches: - - main - - staging tags: - v* workflow_dispatch: diff --git a/.vscode/terminal.extra.zsh b/.vscode/terminal.extra.zsh index 35f2cbd01..7260c7eec 100755 --- a/.vscode/terminal.extra.zsh +++ b/.vscode/terminal.extra.zsh @@ -30,7 +30,7 @@ if command -v mise >/dev/null 2>&1; then else REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo "${PWD}")" # Mise is not installed, run the install script - chmod -R +x "${REPO_ROOT}/scripts" || { + chmod -R +x "${REPO_ROOT}/scripts" || { print -P "%F{209}[codeweaver]%f %F{red}Failed to make install scripts executable!%f" } print -P "%F{209}[codeweaver]%f Installing Mise for the first time..." diff --git a/.vscode/zsh/.zshrc b/.vscode/zsh/.zshrc index 5d1d62b3a..1a2c10edb 100644 --- a/.vscode/zsh/.zshrc +++ b/.vscode/zsh/.zshrc @@ -59,5 +59,8 @@ if [[ -f "${HOME}/.zshrc" ]]; then source "${HOME}/.zshrc" fi -add-zsh-hook precmd _prompt +autoload -Uz add-zsh-hook 2>/dev/null +if (( $+functions[add-zsh-hook] )); then + add-zsh-hook precmd _prompt +fi diff --git a/mise.dev.toml b/mise.dev.toml index 747528de8..17b9346ae 100644 --- a/mise.dev.toml +++ b/mise.dev.toml @@ -56,9 +56,11 @@ esac run_windows = ''' @echo off set "pythonPath=%python_path%" -if not %profile%==dev if not "%CI%"=="true" ( - rem don't run - exit /b 0 +if not "%profile%"=="dev" ( + if not "%CI%"=="true" ( + rem don't run + exit /b 0 + ) ) if not "%pythonPath%"=="%pythonPath:.venv\Scripts\python=%" ( rem Already in venv, do nothing @@ -82,7 +84,7 @@ run = [ '''if ! command -v mise &>/dev/null; then if [ -d "$HOME/.local/share/mise" ] || [ -d "$HOME/.mise" ] || [ -f "$HOME/.local/bin/mise" ]; then export PATH="$HOME/.local/bin:$HOME/.mise/bin:$HOME/.local/share/mise/bin:$PATH" - if [ "ACTIVE_SHELL" = "bash" ] || [ "ACTIVE_SHELL" = "zsh" ] && ! grep -q "mise activate" "$HOME/.${ACTIVE_SHELL}rc"; then + if [ "$ACTIVE_SHELL" = "bash" ] || [ "$ACTIVE_SHELL" = "zsh" ] && ! grep -q "mise activate" "$HOME/.${ACTIVE_SHELL}rc"; then echo "eval \"$(mise activate \"${ACTIVE_SHELL}\")\" 2>&1 || true" >> "$HOME/.${ACTIVE_SHELL}rc" fi else diff --git a/mise.toml b/mise.toml index 3a8f65c86..bddd9e3fe 100644 --- a/mise.toml +++ b/mise.toml @@ -53,7 +53,7 @@ python = '''{{ get_env(name="MISE_PYTHON_VERSION", default="3.13") }}''' uv = "latest" # Quick note for those unfamiliar with mise: -# - depite the namespace, tools prefixed with "pipx:" are installed via "uv" (I assume once upon a time they were installed with pipx before uv came along) +# - despite the namespace, tools prefixed with "pipx:" are installed via "uv" (I assume once upon a time they were installed with pipx before uv came along) # - some tools have no prefix -- these are defined in mise's internal registry directly # - The prefix refers to the "backend" used to install the tool -- most of the no-prefix tools are installed through `aqua` or github/gitlab releases, and failing that, `ubi`. Language-specific package managers (cargo/npm/go) are also used where appropriate. @@ -225,13 +225,10 @@ echo "${CW_PREFIX} Applying formatting...hold onto your butts 🚬...🦖 " # mise -y //:fix-ruff-patterns || { # there are some bugs to work out # echo "${CW_PREFIX} ⚠️ \033[0;32mRuff pattern fixer encountered issues.\033[0m"} uv run ruff format . -yaml_files="$(git ls-files "*.yaml" "*.yml" "*.json" 2>/dev/null)" -if [ -n "$yaml_files" ]; then - printf '%s\n' $yaml_files | xargs -n1 yq -iP --indent=2 eval "." 2>/dev/null || true -fi +git ls-files "*.yaml" "*.yml" "*.json" 2>/dev/null | xargs -n1 yq -iP --indent=2 eval "." 2>/dev/null || true toml_files="$(git ls-files "*.toml" 2>/dev/null)" if [ -n "$toml_files" ]; then - tombi format $toml_files 2>/dev/null || true + printf '%s\n' "$toml_files" | xargs -n1 tombi format 2>/dev/null || true fi ''' run_windows = ''' From c2505a6728ae325fa3e53497ec103ab55338f2f3 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Mon, 8 Dec 2025 14:01:03 -0500 Subject: [PATCH 40/61] fix: update setup-mise-env and reusable-lint workflows for consistency and improved output handling --- .github/actions/setup-mise-env/action.yml | 32 +++++++++++------------ .github/workflows/_reusable-lint.yml | 5 ++++ 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 3d54fd001..2dfc07a8e 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -36,12 +36,9 @@ outputs: MISE_ENV: description: Mise environment name value: ${{ steps.mise-outputs.outputs.MISE_ENV }} - profile: + PROFILE: description: Profile used for setup - value: ${{ steps.mise-outputs.outputs.profile }} - python_version: - description: Python version installed - value: ${{ steps.mise-outputs.outputs.python_version }} + value: ${{ steps.mise-outputs.outputs.PROFILE }} PYTHON_PATH: description: Path to Python executable value: ${{ steps.mise-outputs.outputs.PYTHON_PATH }} @@ -57,6 +54,9 @@ runs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 with: fetch-depth: ${{ inputs.fetch-depth }} + - name: Free up disk space + shell: bash + run: ./scripts/dev-env/ci-free-disk-space.sh - name: Install system dependencies shell: bash run: | @@ -64,21 +64,22 @@ runs: sudo apt-get update && sudo apt-get install -y curl git build-essential libssl-dev zlib1g-dev \ libbz2-dev libreadline-dev libsqlite3-dev libncursesw5-dev xz-utils tk-dev libxml2-dev \ libxmlsec1-dev libffi-dev liblzma-dev libzstd-dev - - name: Free up disk space - shell: bash - run: ./scripts/dev-env/ci-free-disk-space.sh - name: Set up Environment for Free-Threaded Python shell: bash + env: + MISE_PYTHON_VERSION: ${{ inputs.python-version }} + UV_PYTHON: ${{ inputs.python-version }} + PYTHON_VERSION: ${{ inputs.python-version }} run: | - if [[ "${inputs.python-version}" != *t ]]; then - echo "Using standard Python version ${inputs.python-version}..." - echo "MISE_PYTHON_VERSION=${inputs.python-version}" >> "$GITHUB_ENV" - echo "UV_PYTHON=${inputs.python-version}" >> "$GITHUB_ENV" + if [[ "${PYTHON_VERSION}" != *t ]]; then + echo "Using standard Python version ${PYTHON_VERSION}..." + echo "MISE_PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV" + echo "UV_PYTHON=${PYTHON_VERSION}" >> "$GITHUB_ENV" exit 0 fi - echo "Setting up environment for free-threaded Python ${inputs.python-version}..." - python_version="${inputs.python-version}" + echo "Setting up environment for free-threaded Python ${PYTHON_VERSION}..." + python_version="${PYTHON_VERSION}" base_version="${python_version%t}" echo "Base version: ${base_version}" # I couldn't get Mise's handling of free-threaded Python versions to work correctly... @@ -181,7 +182,6 @@ runs: mise_bin_dir="$(dirname "$MISE_PATH")" python_path="$(which python)" python_bin_dir="$(dirname "$python_path")" - echo "profile=${{ inputs.profile }}" >> "$GITHUB_OUTPUT" - echo "python_version=$(python --version | awk '{print $2}')" >> "$GITHUB_OUTPUT" + echo "PROFILE=${{ inputs.profile }}" >> "$GITHUB_OUTPUT" echo "PYTHON_PATH=$python_path" >> "$GITHUB_OUTPUT" echo "MISE_PYTHON_VERSION=$MISE_PYTHON_VERSION" >> "$GITHUB_OUTPUT" \ No newline at end of file diff --git a/.github/workflows/_reusable-lint.yml b/.github/workflows/_reusable-lint.yml index 2904934df..e4a061416 100644 --- a/.github/workflows/_reusable-lint.yml +++ b/.github/workflows/_reusable-lint.yml @@ -48,12 +48,17 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} profile: "${{ env.PROFILE }}" skip-checkout: true + id: mise-setup - name: Check code style and linting + env: + MISE_PYTHON_VERSION: ${{ steps.mise-setup.outputs.MISE_PYTHON_VERSION }} run: mise run lint || echo "::warning::Lint checks failed but allowing workflow to continue" continue-on-error: true - name: Check formatting and licenses if: inputs.run-format-check + env: + MISE_PYTHON_VERSION: ${{ steps.mise-setup.outputs.MISE_PYTHON_VERSION }} run: mise run format || echo "::warning::License checks or formatting checks failed but allowing workflow to continue" continue-on-error: true From f82fd3881eb416c21ff5b8956d12612a5bd8c171 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> Date: Mon, 8 Dec 2025 14:08:31 -0500 Subject: [PATCH 41/61] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> --- .github/actions/setup-mise-env/action.yml | 2 ++ mise.dev.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 2dfc07a8e..cbb110268 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -182,6 +182,8 @@ runs: mise_bin_dir="$(dirname "$MISE_PATH")" python_path="$(which python)" python_bin_dir="$(dirname "$python_path")" + echo "MISE_BIN_DIR=$mise_bin_dir" >> "$GITHUB_OUTPUT" + echo "PYTHON_BIN_DIR=$python_bin_dir" >> "$GITHUB_OUTPUT" echo "PROFILE=${{ inputs.profile }}" >> "$GITHUB_OUTPUT" echo "PYTHON_PATH=$python_path" >> "$GITHUB_OUTPUT" echo "MISE_PYTHON_VERSION=$MISE_PYTHON_VERSION" >> "$GITHUB_OUTPUT" \ No newline at end of file diff --git a/mise.dev.toml b/mise.dev.toml index 17b9346ae..ae170c332 100644 --- a/mise.dev.toml +++ b/mise.dev.toml @@ -84,7 +84,7 @@ run = [ '''if ! command -v mise &>/dev/null; then if [ -d "$HOME/.local/share/mise" ] || [ -d "$HOME/.mise" ] || [ -f "$HOME/.local/bin/mise" ]; then export PATH="$HOME/.local/bin:$HOME/.mise/bin:$HOME/.local/share/mise/bin:$PATH" - if [ "$ACTIVE_SHELL" = "bash" ] || [ "$ACTIVE_SHELL" = "zsh" ] && ! grep -q "mise activate" "$HOME/.${ACTIVE_SHELL}rc"; then + if ( [ "$ACTIVE_SHELL" = "bash" ] || [ "$ACTIVE_SHELL" = "zsh" ] ) && ! grep -q "mise activate" "$HOME/.${ACTIVE_SHELL}rc"; then echo "eval \"$(mise activate \"${ACTIVE_SHELL}\")\" 2>&1 || true" >> "$HOME/.${ACTIVE_SHELL}rc" fi else From 9c14d525bb5c1dc385daace63ebcedf2a7705eb8 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Mon, 8 Dec 2025 14:52:06 -0500 Subject: [PATCH 42/61] fix: streamline mise configuration by consolidating tool definitions and removing unused venv creation arguments --- mise.dev.toml | 14 ++++---------- mise.toml | 11 ++--------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/mise.dev.toml b/mise.dev.toml index ae170c332..4ec5d2373 100644 --- a/mise.dev.toml +++ b/mise.dev.toml @@ -8,24 +8,18 @@ uv_venv_auto = true compile = true [tools] -hk = { version = "latest" } +hk = "latest" pkl = "latest" usage = "latest" uv = "latest" # Quality & validation tools "pipx:reuse" = "latest" # License validation -"aqua:tombi-toml/tombi" = "latest" -"pipx:ty" = "latest" # Type checking +"aqua:tombi" = "latest" +"github:astral-sh/ty" = "ty@0.0.1-alpha.32" # Type checking ruff = "latest" # Python linting/formatting [env] -_.python.venv = { path = ".venv", create = true, uv_create_args = [ - "--seed", - "--keyring-provider", - "subprocess", - "--python", - '{{ get_env(name="MISE_PYTHON_VERSION", default="3.13") }}' -] } +_.python.venv = { path = ".venv" } [hooks] [hooks.enter] diff --git a/mise.toml b/mise.toml index bddd9e3fe..2c3ccb65b 100644 --- a/mise.toml +++ b/mise.toml @@ -38,13 +38,6 @@ experimental = true [settings.python] compile = true -uv_venv_create_args = [ - "--seed", - "--keyring-provider", - "subprocess", - "--python", - "{{ get_env(name='MISE_PYTHON_VERSION', default='3.13') }}", -] [tools] # most tools are defined in mise.dev.toml to keep CI workflows lightweight @@ -208,10 +201,10 @@ hk fix ''' [tasks.format.tools] -"aqua:crates-ci/typos" = "latest" +"aqua:typos" = "latest" "pipx:reuse" = "latest" "aqua:tombi-toml/tombi" = "latest" -"pipx:ty" = "latest" +"github:astral-sh/ty" = "0.0.1-alpha.32" actionlint = "latest" hk = "latest" pkl = "latest" From 582f1c9836c09aec63f0f5212b263b2145220078 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Mon, 8 Dec 2025 14:53:02 -0500 Subject: [PATCH 43/61] fix: incorrect-tool references in mise.toml --- mise.dev.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mise.dev.toml b/mise.dev.toml index 4ec5d2373..004559a11 100644 --- a/mise.dev.toml +++ b/mise.dev.toml @@ -14,8 +14,8 @@ usage = "latest" uv = "latest" # Quality & validation tools "pipx:reuse" = "latest" # License validation -"aqua:tombi" = "latest" -"github:astral-sh/ty" = "ty@0.0.1-alpha.32" # Type checking +"aqua:tombi-toml/tombi" = "latest" +"github:astral-sh/ty" = "0.0.1-alpha.32" # Type checking ruff = "latest" # Python linting/formatting [env] From 1b079c0b1cfea6097f43ec17d309753e8bdeb37b Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Mon, 8 Dec 2025 15:07:02 -0500 Subject: [PATCH 44/61] fix: add mise-debug input for enhanced output in setup-mise-env action and update reusable test workflow --- .github/actions/setup-mise-env/action.yml | 15 +++++++++++++-- .github/workflows/_reusable-test.yml | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index cbb110268..0167e974a 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -27,6 +27,10 @@ inputs: description: Task profile to use for mise setup one of 'minimal', 'reviewer', 'dev' required: true default: 'minimal' + mise-debug: + description: Enable debug output for mise commands + required: false + default: 'false' outputs: # MISE_PATH, MISE_ENV, and PYTHON_PATH are typically in uppercase and may be case sensitive in some environments @@ -71,6 +75,7 @@ runs: MISE_PYTHON_VERSION: ${{ inputs.python-version }} UV_PYTHON: ${{ inputs.python-version }} PYTHON_VERSION: ${{ inputs.python-version }} + MISE_VERBOSE: ${{ inputs.mise-debug }} run: | if [[ "${PYTHON_VERSION}" != *t ]]; then echo "Using standard Python version ${PYTHON_VERSION}..." @@ -95,6 +100,7 @@ runs: MISE_YES: 1 MISE_EXPERIMENTAL: 1 UV_PYTHON: ${{ env.UV_PYTHON }} + MISE_VERBOSE: ${{ inputs.mise-debug }} with: github_token: ${{ inputs.github-token }} experimental: true @@ -111,7 +117,7 @@ runs: MISE_EXPERIMENTAL: 1 MISE_ENV: dev UV_PYTHON: ${{ env.UV_PYTHON }} - MISE_PYTHON_VERSION: ${{ env.MISE_PYTHON_VERSION }} + MISE_VERBOSE: ${{ inputs.mise-debug }} with: github_token: ${{ inputs.github-token }} experimental: true @@ -124,6 +130,7 @@ runs: shell: bash env: MISE_GITHUB_TOKEN: ${{ inputs.github-token }} + MISE_VERBOSE: ${{ inputs.mise-debug }} id: mise-setup-reviewer run: | uv sync @@ -134,6 +141,7 @@ runs: MISE_YES: 1 MISE_EXPERIMENTAL: 1 MISE_ENV: dev + MISE_VERBOSE: ${{ inputs.mise-debug }} UV_PYTHON: ${{ env.UV_PYTHON }} with: github_token: ${{ inputs.github-token }} @@ -150,9 +158,10 @@ runs: env: MISE_PYTHON_VERSION: ${{ env.MISE_PYTHON_VERSION }} UV_PYTHON: ${{ env.UV_PYTHON }} + MISE_VERBOSE: ${{ inputs.mise-debug }} run: | echo "Inserting free-threaded Python version $UV_PYTHON into dev profile..." - mise x uv@latest -- uv python install -U --default "cpython-${UV_PYTHON}" 2>&1 + mise x uv@latest -- uv python install -U "cpython-${UV_PYTHON}" 2>&1 minor_version="$(mise x uv@latest -- uv run -p "$UV_PYTHON" --no-config python -c 'import sys; print(sys.version_info.minor)' 2>/dev/null)" mise sync python --uv new_mise_python_version="${MISE_PYTHON_VERSION}.${minor_version}+freethreaded" @@ -168,6 +177,7 @@ runs: MISE_YES: 1 MISE_GITHUB_TOKEN: ${{ inputs.github-token }} MISE_PYTHON_VERSION: ${{ env.MISE_PYTHON_VERSION }} + MISE_VERBOSE: ${{ inputs.mise-debug }} run: | mise //:cloud-setup 2>&1 @@ -176,6 +186,7 @@ runs: id: mise-outputs env: MISE_PYTHON_VERSION: ${{ env.MISE_PYTHON_VERSION }} + MISE_VERBOSE: ${{ inputs.mise-debug }} run: | MISE_PATH="$(which mise)" echo "MISE_PATH=$MISE_PATH" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/_reusable-test.yml b/.github/workflows/_reusable-test.yml index d3fc82151..ea90d0176 100644 --- a/.github/workflows/_reusable-test.yml +++ b/.github/workflows/_reusable-test.yml @@ -84,6 +84,7 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} profile: "dev" skip-checkout: true + mise-debug: true id: setup-mise - name: Run quality checks if: ${{ inputs.run-quality-checks }} From e448519a042da3fe1425d4c850e6a6df0a2be8b7 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> Date: Mon, 8 Dec 2025 15:25:57 -0500 Subject: [PATCH 45/61] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> --- .github/actions/setup-mise-env/action.yml | 6 +++++- .github/workflows/mcp-registry-submit.yml | 10 ++++++++++ mise.dev.toml | 2 +- mise.toml | 4 ++-- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 0167e974a..213baef42 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -152,7 +152,7 @@ runs: env: false id: mise-setup-dev - name: Insert Free-Threaded Python into Dev Profile - if: inputs.profile == 'dev' && startsWith(inputs.python-version, '3.') && endsWith(inputs.python-version, 't') + if: inputs.profile == 'dev' && matches(inputs.python-version, '^3\.\d+t$') shell: bash id: mise-setup-dev-insert env: @@ -163,6 +163,10 @@ runs: echo "Inserting free-threaded Python version $UV_PYTHON into dev profile..." mise x uv@latest -- uv python install -U "cpython-${UV_PYTHON}" 2>&1 minor_version="$(mise x uv@latest -- uv run -p "$UV_PYTHON" --no-config python -c 'import sys; print(sys.version_info.minor)' 2>/dev/null)" + if [ -z "$minor_version" ]; then + echo "ERROR: Failed to determine Python minor version for $UV_PYTHON" + exit 1 + fi mise sync python --uv new_mise_python_version="${MISE_PYTHON_VERSION}.${minor_version}+freethreaded" mise use "python@${new_mise_python_version}" 2>&1 diff --git a/.github/workflows/mcp-registry-submit.yml b/.github/workflows/mcp-registry-submit.yml index 9a0d49477..47a68234c 100644 --- a/.github/workflows/mcp-registry-submit.yml +++ b/.github/workflows/mcp-registry-submit.yml @@ -179,6 +179,16 @@ jobs: publication_time="$(echo "$publication_response" | jq -r '._meta."io.modelcontextprotocol.registry/official".published_at')" if [ -z "$publication_time" ] || [ "$publication_time" = "null" ]; then echo "ERROR: Submission to MCP Registry failed" + # Try to extract error details from the publication response + error_message="$(echo "$publication_response" | jq -r '.error // .message // .detail // empty')" + validation_errors="$(echo "$publication_response" | jq -r '.validation_errors // empty')" + if [ -n "$error_message" ]; then + echo "Error message: $error_message" + fi + if [ -n "$validation_errors" ] && [ "$validation_errors" != "null" ]; then + echo "Validation errors: $validation_errors" + fi + echo "Raw response: $publication_response" exit 1 fi echo "✓ Successfully submitted to MCP Registry at $publication_time" diff --git a/mise.dev.toml b/mise.dev.toml index 004559a11..8f4d87e8c 100644 --- a/mise.dev.toml +++ b/mise.dev.toml @@ -33,7 +33,7 @@ silent = "stdout" tools.uv = "latest" run = ''' # profile is set to 'dev' in a cloud CI environment for cloud agents. 'enter' tends to break there. -if [ "$profile" != "dev" ] && [ "$CI" != "true" ]; then +if [ "$profile" = "dev" ] && [ "$CI" = "true" ]; then # don't run exit 0 fi diff --git a/mise.toml b/mise.toml index 2c3ccb65b..78042c6be 100644 --- a/mise.toml +++ b/mise.toml @@ -218,10 +218,10 @@ echo "${CW_PREFIX} Applying formatting...hold onto your butts 🚬...🦖 " # mise -y //:fix-ruff-patterns || { # there are some bugs to work out # echo "${CW_PREFIX} ⚠️ \033[0;32mRuff pattern fixer encountered issues.\033[0m"} uv run ruff format . -git ls-files "*.yaml" "*.yml" "*.json" 2>/dev/null | xargs -n1 yq -iP --indent=2 eval "." 2>/dev/null || true +git ls-files "*.yaml" "*.yml" "*.json" 2>/dev/null | xargs -r yq -iP --indent=2 eval "." 2>/dev/null || true toml_files="$(git ls-files "*.toml" 2>/dev/null)" if [ -n "$toml_files" ]; then - printf '%s\n' "$toml_files" | xargs -n1 tombi format 2>/dev/null || true + printf '%s\n' "$toml_files" | xargs -r tombi format 2>/dev/null || true fi ''' run_windows = ''' From f82e80221d4286af2aed81875f0b315e57a68485 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> Date: Mon, 8 Dec 2025 15:36:00 -0500 Subject: [PATCH 46/61] Change condition for inserting Free-Threaded Python correct use of nonexistent 'matches' Signed-off-by: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> --- .github/actions/setup-mise-env/action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 213baef42..a3893ea75 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -152,7 +152,7 @@ runs: env: false id: mise-setup-dev - name: Insert Free-Threaded Python into Dev Profile - if: inputs.profile == 'dev' && matches(inputs.python-version, '^3\.\d+t$') + if: inputs.profile == 'dev' && endsWith(inputs.python-version, 't') shell: bash id: mise-setup-dev-insert env: @@ -201,4 +201,4 @@ runs: echo "PYTHON_BIN_DIR=$python_bin_dir" >> "$GITHUB_OUTPUT" echo "PROFILE=${{ inputs.profile }}" >> "$GITHUB_OUTPUT" echo "PYTHON_PATH=$python_path" >> "$GITHUB_OUTPUT" - echo "MISE_PYTHON_VERSION=$MISE_PYTHON_VERSION" >> "$GITHUB_OUTPUT" \ No newline at end of file + echo "MISE_PYTHON_VERSION=$MISE_PYTHON_VERSION" >> "$GITHUB_OUTPUT" From 3733e414a6138f1c4545c219d7f0485d67caf170 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> Date: Mon, 8 Dec 2025 15:46:52 -0500 Subject: [PATCH 47/61] Add MISE_PYTHON_COMPILE variable to action.yml Signed-off-by: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> --- .github/actions/setup-mise-env/action.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index a3893ea75..21a2724d1 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -101,6 +101,7 @@ runs: MISE_EXPERIMENTAL: 1 UV_PYTHON: ${{ env.UV_PYTHON }} MISE_VERBOSE: ${{ inputs.mise-debug }} + MISE_PYTHON_COMPILE: 0 with: github_token: ${{ inputs.github-token }} experimental: true @@ -118,6 +119,7 @@ runs: MISE_ENV: dev UV_PYTHON: ${{ env.UV_PYTHON }} MISE_VERBOSE: ${{ inputs.mise-debug }} + MISE_PYTHON_COMPILE: 0 with: github_token: ${{ inputs.github-token }} experimental: true @@ -143,6 +145,7 @@ runs: MISE_ENV: dev MISE_VERBOSE: ${{ inputs.mise-debug }} UV_PYTHON: ${{ env.UV_PYTHON }} + MISE_PYTHON_COMPILE: 0 with: github_token: ${{ inputs.github-token }} experimental: true @@ -169,6 +172,7 @@ runs: fi mise sync python --uv new_mise_python_version="${MISE_PYTHON_VERSION}.${minor_version}+freethreaded" + echo "Telling mise to use $new_mise_python_version" mise use "python@${new_mise_python_version}" 2>&1 echo "MISE_PYTHON_VERSION=${new_mise_python_version}" >> "$GITHUB_ENV" - name: Activate Dev Profile Environment @@ -183,6 +187,7 @@ runs: MISE_PYTHON_VERSION: ${{ env.MISE_PYTHON_VERSION }} MISE_VERBOSE: ${{ inputs.mise-debug }} run: | + echo "starting cloud setup for $MISE_PYTHON_VERSION" mise //:cloud-setup 2>&1 - name: Set outputs From 63949f2e8e28d0612af95596e3bc366ccf5a1654 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Mon, 8 Dec 2025 15:55:25 -0500 Subject: [PATCH 48/61] fix: remove minor version check for uv --- .github/actions/setup-mise-env/action.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 21a2724d1..beafe5db7 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -165,13 +165,8 @@ runs: run: | echo "Inserting free-threaded Python version $UV_PYTHON into dev profile..." mise x uv@latest -- uv python install -U "cpython-${UV_PYTHON}" 2>&1 - minor_version="$(mise x uv@latest -- uv run -p "$UV_PYTHON" --no-config python -c 'import sys; print(sys.version_info.minor)' 2>/dev/null)" - if [ -z "$minor_version" ]; then - echo "ERROR: Failed to determine Python minor version for $UV_PYTHON" - exit 1 - fi mise sync python --uv - new_mise_python_version="${MISE_PYTHON_VERSION}.${minor_version}+freethreaded" + new_mise_python_version="${MISE_PYTHON_VERSION}+freethreaded" echo "Telling mise to use $new_mise_python_version" mise use "python@${new_mise_python_version}" 2>&1 echo "MISE_PYTHON_VERSION=${new_mise_python_version}" >> "$GITHUB_ENV" From 108b400003baf6d33d2479ec87552c301a14a1bd Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Mon, 8 Dec 2025 16:00:20 -0500 Subject: [PATCH 49/61] fix: update dependency references for type checking to use latest version --- .github/actions/setup-mise-env/action.yml | 2 +- mise.dev.toml | 2 +- mise.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index beafe5db7..22408c4ec 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -182,7 +182,7 @@ runs: MISE_PYTHON_VERSION: ${{ env.MISE_PYTHON_VERSION }} MISE_VERBOSE: ${{ inputs.mise-debug }} run: | - echo "starting cloud setup for $MISE_PYTHON_VERSION" + echo "starting cloud setup for $MISE_PYTHON_VERSION" mise //:cloud-setup 2>&1 - name: Set outputs diff --git a/mise.dev.toml b/mise.dev.toml index 8f4d87e8c..9da3720d1 100644 --- a/mise.dev.toml +++ b/mise.dev.toml @@ -15,7 +15,7 @@ uv = "latest" # Quality & validation tools "pipx:reuse" = "latest" # License validation "aqua:tombi-toml/tombi" = "latest" -"github:astral-sh/ty" = "0.0.1-alpha.32" # Type checking +"ubi:astral-sh/ty" = "latest" ruff = "latest" # Python linting/formatting [env] diff --git a/mise.toml b/mise.toml index 78042c6be..811887ee3 100644 --- a/mise.toml +++ b/mise.toml @@ -204,7 +204,7 @@ hk fix "aqua:typos" = "latest" "pipx:reuse" = "latest" "aqua:tombi-toml/tombi" = "latest" -"github:astral-sh/ty" = "0.0.1-alpha.32" +"ubi:astral-sh/ty" = "latest" actionlint = "latest" hk = "latest" pkl = "latest" From a069b525a56d005b40331dec3f6663586707e962 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Mon, 8 Dec 2025 16:40:12 -0500 Subject: [PATCH 50/61] fix: streamline system dependency installation and update free-threaded Python setup --- .github/actions/setup-mise-env/action.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 22408c4ec..5d3214b25 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -65,9 +65,8 @@ runs: shell: bash run: | # ensure build-python dependencies are installed - sudo apt-get update && sudo apt-get install -y curl git build-essential libssl-dev zlib1g-dev \ - libbz2-dev libreadline-dev libsqlite3-dev libncursesw5-dev xz-utils tk-dev libxml2-dev \ - libxmlsec1-dev libffi-dev liblzma-dev libzstd-dev + sudo mkdir -p /etc/apt/apt.conf.d/ && echo 'DPkg::Post-Invoke {"/bin/rm -f /var/cache/apt/archives/*.deb || true";};' | sudo tee /etc/apt/apt.conf.d/99-local-cleanup + sudo apt-get update && sudo apt-get install -y curl git libreadline-dev libbz2-dev zlib1g-dev - name: Set up Environment for Free-Threaded Python shell: bash @@ -164,7 +163,8 @@ runs: MISE_VERBOSE: ${{ inputs.mise-debug }} run: | echo "Inserting free-threaded Python version $UV_PYTHON into dev profile..." - mise x uv@latest -- uv python install -U "cpython-${UV_PYTHON}" 2>&1 + mise use -g uv@latest + uv python install -U "cpython-${UV_PYTHON}" 2>&1 mise sync python --uv new_mise_python_version="${MISE_PYTHON_VERSION}+freethreaded" echo "Telling mise to use $new_mise_python_version" From c1d1caec7c724bf21bfb9995b8c7980d60ef419a Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Mon, 8 Dec 2025 16:52:54 -0500 Subject: [PATCH 51/61] fix: add command to list available Python versions in mise setup --- .github/actions/setup-mise-env/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 5d3214b25..1eaf66c66 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -166,6 +166,7 @@ runs: mise use -g uv@latest uv python install -U "cpython-${UV_PYTHON}" 2>&1 mise sync python --uv + mise list python 2>&1 new_mise_python_version="${MISE_PYTHON_VERSION}+freethreaded" echo "Telling mise to use $new_mise_python_version" mise use "python@${new_mise_python_version}" 2>&1 From 53f5b2e34d408d0351e09e46fa0c9f3157b8d43e Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Mon, 8 Dec 2025 16:55:10 -0500 Subject: [PATCH 52/61] fix: correct command for creating virtual environment in mise.toml --- mise.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mise.toml b/mise.toml index 811887ee3..d2a9ee21f 100644 --- a/mise.toml +++ b/mise.toml @@ -87,7 +87,7 @@ echo "${CW_PREFIX} Sourcing virtual environment..." git rev-parse --show-toplevel || true if [ ! -d ".venv" ]; then echo "${CW_PREFIX} ⚠️ \033[0;31mVirtual environment not found. We'll try to proceed, but things may break!\033[0m" - uvx venv --seed --keyring-provider subprocess --python {{ get_env(name='MISE_PYTHON_VERSION', default='3.13') }} .venv + uv venv --seed --keyring-provider subprocess --python {{ get_env(name='MISE_PYTHON_VERSION', default='3.13') }} .venv fi . .venv/bin/activate || echo "${CW_PREFIX} ⚠️ \033[0;31mFailed to source virtual environment.\033[0m" ''' From 6c9750355eb8fb96633a57e5de9219a898abe491 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Mon, 8 Dec 2025 16:56:49 -0500 Subject: [PATCH 53/61] fix: remove compile settings to experiment if cause of a CI failure. --- mise.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/mise.toml b/mise.toml index d2a9ee21f..6c1f5694e 100644 --- a/mise.toml +++ b/mise.toml @@ -37,7 +37,6 @@ idiomatic_version_file_enable_tools = [] experimental = true [settings.python] -compile = true [tools] # most tools are defined in mise.dev.toml to keep CI workflows lightweight From bb6d19beec7572b5543b3279a1b536683f118bcf Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Mon, 8 Dec 2025 17:02:46 -0500 Subject: [PATCH 54/61] fix: refine free-threaded Python installation process in CI setup --- .github/actions/setup-mise-env/action.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 1eaf66c66..9d2ffb001 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -165,12 +165,10 @@ runs: echo "Inserting free-threaded Python version $UV_PYTHON into dev profile..." mise use -g uv@latest uv python install -U "cpython-${UV_PYTHON}" 2>&1 + # after a lot of trial and error, it seems that combined with setting MISE_PYTHON_VERSION to the base version, and using uv to install the free-threaded version, and syncing uv and mise, this works + # the favored version is now the free-threaded version -- as mise list python will show: mise sync python --uv mise list python 2>&1 - new_mise_python_version="${MISE_PYTHON_VERSION}+freethreaded" - echo "Telling mise to use $new_mise_python_version" - mise use "python@${new_mise_python_version}" 2>&1 - echo "MISE_PYTHON_VERSION=${new_mise_python_version}" >> "$GITHUB_ENV" - name: Activate Dev Profile Environment if: inputs.profile == 'dev' shell: bash From 724798256de63772994962936e8a02b82b939b65 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Mon, 8 Dec 2025 17:08:17 -0500 Subject: [PATCH 55/61] fix: enhance cloud setup script with informative messages and streamline mise commands --- mise.dev.toml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mise.dev.toml b/mise.dev.toml index 9da3720d1..b2a851484 100644 --- a/mise.dev.toml +++ b/mise.dev.toml @@ -76,6 +76,7 @@ run = [ "echo \"[codeweaver] Setting up cloud development environment...\"", "ln -sf AGENTS.md CLAUDE.md", '''if ! command -v mise &>/dev/null; then + echo "[codeweaver] We couldn't find mise in your PATH. We'll try to install it for you." if [ -d "$HOME/.local/share/mise" ] || [ -d "$HOME/.mise" ] || [ -f "$HOME/.local/bin/mise" ]; then export PATH="$HOME/.local/bin:$HOME/.mise/bin:$HOME/.local/share/mise/bin:$PATH" if ( [ "$ACTIVE_SHELL" = "bash" ] || [ "$ACTIVE_SHELL" = "zsh" ] ) && ! grep -q "mise activate" "$HOME/.${ACTIVE_SHELL}rc"; then @@ -86,12 +87,14 @@ run = [ ./scripts/dev-env/install-mise.sh 2>&1 || true fi fi''', + "echo \"[codeweaver] Using mise...\"", '''mise trust --all 2>&1 || { echo "[WARNING] mise trust --all failed during cloud-setup" >&2; }''', '''mise install 2>&1 || { echo "[WARNING] mise install failed during cloud-setup" >&2; }''', '''mise x hk@latest -- hk install --mise 2>&1 || { echo "[WARNING] hk install failed during cloud-setup" >&2; }''', - "mise x uv@latest -- uv venv --allow-existing --seed --keyring-provider subprocess --python {{ get_env(name='MISE_PYTHON_VERSION', default='3.13') }} .venv 2>&1", + '''mise use -g uv@latest 2>&1 || { echo "[WARNING] mise use -g uv@latest failed during cloud-setup" >&2; }''', + "uv venv --allow-existing --seed --keyring-provider subprocess --python {{ get_env(name='MISE_PYTHON_VERSION', default='3.13') }} .venv 2>&1", ". .venv/bin/activate 2>&1 || true", - "mise x uv@latest -- uv sync --extra full --group dev --group test 2>&1", + "uv sync --extra full --group dev --group test 2>&1", "git config include.path .gitconfig 2>&1 || true", '''bash -c " ignore_files=('src/codeweaver/_version.py' 'coverage.xml' 'test-results.xml') @@ -105,6 +108,7 @@ run = [ ] [tasks.cloud-setup.env] +MISE_PYTHON_VERSION = "{{ get_env(name='MISE_PYTHON_VERSION', default='3.13') }}" ACTIVE_SHELL = '''{{ exec(command='basename "$SHELL" 2>/dev/null || echo bash') }}''' MISE_EXPERIMENTAL = "1" MISE_ENV = "dev" From 6ba86ed4f96fe8d8d259e49ca07fa06d7693bb3d Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Mon, 8 Dec 2025 20:30:34 -0500 Subject: [PATCH 56/61] fix: add message to ensure Python version is installed during cloud setup --- mise.dev.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/mise.dev.toml b/mise.dev.toml index b2a851484..0064d4d48 100644 --- a/mise.dev.toml +++ b/mise.dev.toml @@ -92,6 +92,7 @@ run = [ '''mise install 2>&1 || { echo "[WARNING] mise install failed during cloud-setup" >&2; }''', '''mise x hk@latest -- hk install --mise 2>&1 || { echo "[WARNING] hk install failed during cloud-setup" >&2; }''', '''mise use -g uv@latest 2>&1 || { echo "[WARNING] mise use -g uv@latest failed during cloud-setup" >&2; }''', + '''echo "[codeweaver] Ensuring Python version {{ get_env(name='MISE_PYTHON_VERSION', default='3.13') }} is installed..."''', "uv venv --allow-existing --seed --keyring-provider subprocess --python {{ get_env(name='MISE_PYTHON_VERSION', default='3.13') }} .venv 2>&1", ". .venv/bin/activate 2>&1 || true", "uv sync --extra full --group dev --group test 2>&1", From 0d22f2ebfa645c4c18398396b436cb61ca488203 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Mon, 8 Dec 2025 20:48:33 -0500 Subject: [PATCH 57/61] fix: improve cloud setup script to ensure mise activation and Python version installation --- mise.dev.toml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mise.dev.toml b/mise.dev.toml index 0064d4d48..c356b3f99 100644 --- a/mise.dev.toml +++ b/mise.dev.toml @@ -79,8 +79,8 @@ run = [ echo "[codeweaver] We couldn't find mise in your PATH. We'll try to install it for you." if [ -d "$HOME/.local/share/mise" ] || [ -d "$HOME/.mise" ] || [ -f "$HOME/.local/bin/mise" ]; then export PATH="$HOME/.local/bin:$HOME/.mise/bin:$HOME/.local/share/mise/bin:$PATH" - if ( [ "$ACTIVE_SHELL" = "bash" ] || [ "$ACTIVE_SHELL" = "zsh" ] ) && ! grep -q "mise activate" "$HOME/.${ACTIVE_SHELL}rc"; then - echo "eval \"$(mise activate \"${ACTIVE_SHELL}\")\" 2>&1 || true" >> "$HOME/.${ACTIVE_SHELL}rc" + if command -v mise &>/dev/null && ! grep -q "mise activate" "$HOME/.bashrc"; then + echo "eval \"$(mise activate bash)\" 2>&1 || true" >> "$HOME/.bashrc" fi else chmod +x scripts/dev-env/install-mise.sh 2>&1 || true @@ -89,11 +89,12 @@ run = [ fi''', "echo \"[codeweaver] Using mise...\"", '''mise trust --all 2>&1 || { echo "[WARNING] mise trust --all failed during cloud-setup" >&2; }''', - '''mise install 2>&1 || { echo "[WARNING] mise install failed during cloud-setup" >&2; }''', + '''mise -vv install 2>&1''', + '''mise tool ''', '''mise x hk@latest -- hk install --mise 2>&1 || { echo "[WARNING] hk install failed during cloud-setup" >&2; }''', - '''mise use -g uv@latest 2>&1 || { echo "[WARNING] mise use -g uv@latest failed during cloud-setup" >&2; }''', - '''echo "[codeweaver] Ensuring Python version {{ get_env(name='MISE_PYTHON_VERSION', default='3.13') }} is installed..."''', - "uv venv --allow-existing --seed --keyring-provider subprocess --python {{ get_env(name='MISE_PYTHON_VERSION', default='3.13') }} .venv 2>&1", + '''echo "[codeweaver] Ensuring Python version "$MISE_PYTHON_VERSION" is installed..."''', + '''echo "$(mise doctor)" 2>&1''', + "uv venv --allow-existing --seed --keyring-provider subprocess --python $MISE_PYTHON_VERSION .venv 2>&1", ". .venv/bin/activate 2>&1 || true", "uv sync --extra full --group dev --group test 2>&1", "git config include.path .gitconfig 2>&1 || true", @@ -110,7 +111,6 @@ run = [ [tasks.cloud-setup.env] MISE_PYTHON_VERSION = "{{ get_env(name='MISE_PYTHON_VERSION', default='3.13') }}" -ACTIVE_SHELL = '''{{ exec(command='basename "$SHELL" 2>/dev/null || echo bash') }}''' MISE_EXPERIMENTAL = "1" MISE_ENV = "dev" MISE_YES = "1" From 7612f130cddf30e4173debad6682305ccf84673b Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Mon, 8 Dec 2025 21:00:54 -0500 Subject: [PATCH 58/61] fix: enhance cloud setup with mise doctor output and ensure latest uv installation --- .github/actions/setup-mise-env/action.yml | 10 +++++++++- mise.dev.toml | 3 +-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index 9d2ffb001..ced491d0a 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -182,6 +182,11 @@ runs: MISE_VERBOSE: ${{ inputs.mise-debug }} run: | echo "starting cloud setup for $MISE_PYTHON_VERSION" + echo "Mise doctor output:" + echo "$(mise doctor)" 2>&1 + echo "Ensuring uv is set to latest..." + mise use -g uv@latest + echo "Starting cloud-setup task..." mise //:cloud-setup 2>&1 - name: Set outputs @@ -189,7 +194,9 @@ runs: id: mise-outputs env: MISE_PYTHON_VERSION: ${{ env.MISE_PYTHON_VERSION }} + MISE_ENV: ${{ env.MISE_ENV }} MISE_VERBOSE: ${{ inputs.mise-debug }} + PROFILE: ${{ inputs.profile }} run: | MISE_PATH="$(which mise)" echo "MISE_PATH=$MISE_PATH" >> "$GITHUB_OUTPUT" @@ -198,6 +205,7 @@ runs: python_bin_dir="$(dirname "$python_path")" echo "MISE_BIN_DIR=$mise_bin_dir" >> "$GITHUB_OUTPUT" echo "PYTHON_BIN_DIR=$python_bin_dir" >> "$GITHUB_OUTPUT" - echo "PROFILE=${{ inputs.profile }}" >> "$GITHUB_OUTPUT" + echo "PROFILE=$PROFILE" >> "$GITHUB_OUTPUT" echo "PYTHON_PATH=$python_path" >> "$GITHUB_OUTPUT" echo "MISE_PYTHON_VERSION=$MISE_PYTHON_VERSION" >> "$GITHUB_OUTPUT" + echo "MISE_ENV=${MISE_ENV:-}" >> "$GITHUB_OUTPUT" diff --git a/mise.dev.toml b/mise.dev.toml index c356b3f99..8335ee666 100644 --- a/mise.dev.toml +++ b/mise.dev.toml @@ -88,9 +88,8 @@ run = [ fi fi''', "echo \"[codeweaver] Using mise...\"", - '''mise trust --all 2>&1 || { echo "[WARNING] mise trust --all failed during cloud-setup" >&2; }''', + '''mise trust --all 2>&1''', '''mise -vv install 2>&1''', - '''mise tool ''', '''mise x hk@latest -- hk install --mise 2>&1 || { echo "[WARNING] hk install failed during cloud-setup" >&2; }''', '''echo "[codeweaver] Ensuring Python version "$MISE_PYTHON_VERSION" is installed..."''', '''echo "$(mise doctor)" 2>&1''', From d40d78eab13b04873909d54bcb932298d3677956 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Mon, 8 Dec 2025 21:22:40 -0500 Subject: [PATCH 59/61] fix: enhance cloud setup with improved mise activation and debugging output --- .github/actions/setup-mise-env/action.yml | 4 +++- mise.dev.toml | 12 ++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.github/actions/setup-mise-env/action.yml b/.github/actions/setup-mise-env/action.yml index ced491d0a..d913a282d 100644 --- a/.github/actions/setup-mise-env/action.yml +++ b/.github/actions/setup-mise-env/action.yml @@ -181,9 +181,11 @@ runs: MISE_PYTHON_VERSION: ${{ env.MISE_PYTHON_VERSION }} MISE_VERBOSE: ${{ inputs.mise-debug }} run: | + echo "Activating shims" + eval "$(mise activate bash --shims)" 2>&1 || true echo "starting cloud setup for $MISE_PYTHON_VERSION" echo "Mise doctor output:" - echo "$(mise doctor)" 2>&1 + mise doctor 2>&1 echo "Ensuring uv is set to latest..." mise use -g uv@latest echo "Starting cloud-setup task..." diff --git a/mise.dev.toml b/mise.dev.toml index 8335ee666..8e61107cb 100644 --- a/mise.dev.toml +++ b/mise.dev.toml @@ -73,26 +73,30 @@ MISE_EXPERIMENTAL = "1" [tasks.cloud-setup] run = [ + # This setup only runs in cloud environments, and for cloud agents or complex tasks. + # For cloud agents, the shell is *always* bash and may or may not be interactive. "echo \"[codeweaver] Setting up cloud development environment...\"", "ln -sf AGENTS.md CLAUDE.md", '''if ! command -v mise &>/dev/null; then echo "[codeweaver] We couldn't find mise in your PATH. We'll try to install it for you." if [ -d "$HOME/.local/share/mise" ] || [ -d "$HOME/.mise" ] || [ -f "$HOME/.local/bin/mise" ]; then export PATH="$HOME/.local/bin:$HOME/.mise/bin:$HOME/.local/share/mise/bin:$PATH" - if command -v mise &>/dev/null && ! grep -q "mise activate" "$HOME/.bashrc"; then - echo "eval \"$(mise activate bash)\" 2>&1 || true" >> "$HOME/.bashrc" - fi else chmod +x scripts/dev-env/install-mise.sh 2>&1 || true ./scripts/dev-env/install-mise.sh 2>&1 || true fi fi''', "echo \"[codeweaver] Using mise...\"", + '''if command -v mise &>/dev/null && ! grep -q "mise activate" "$HOME/.bashrc"; then + echo "eval \"$(mise activate bash)\" 2>&1 || true" >> "$HOME/.bashrc" + fi''', + '''if command -v mise &>/dev/null && ! grep -q "mise activate" "$HOME/.bash_profile"; then + echo "eval \"$(mise activate bash --shims)\" 2>&1 || true" >> "$HOME/.bash_profile" + fi''', '''mise trust --all 2>&1''', '''mise -vv install 2>&1''', '''mise x hk@latest -- hk install --mise 2>&1 || { echo "[WARNING] hk install failed during cloud-setup" >&2; }''', '''echo "[codeweaver] Ensuring Python version "$MISE_PYTHON_VERSION" is installed..."''', - '''echo "$(mise doctor)" 2>&1''', "uv venv --allow-existing --seed --keyring-provider subprocess --python $MISE_PYTHON_VERSION .venv 2>&1", ". .venv/bin/activate 2>&1 || true", "uv sync --extra full --group dev --group test 2>&1", From 4ed9426f28f515175ddd662a607cc0eb0fee03bd Mon Sep 17 00:00:00 2001 From: Adam Poulemanos Date: Mon, 8 Dec 2025 21:26:58 -0500 Subject: [PATCH 60/61] fix: remove auto-venv to debug CI issue --- mise.dev.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/mise.dev.toml b/mise.dev.toml index 8e61107cb..6770647ce 100644 --- a/mise.dev.toml +++ b/mise.dev.toml @@ -4,8 +4,6 @@ # SPDX-License-Identifier: MIT OR Apache-2.0 [settings.python] -uv_venv_auto = true -compile = true [tools] hk = "latest" From d4f45d3d288cec629ad74bdb8b98914239f3de34 Mon Sep 17 00:00:00 2001 From: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> Date: Mon, 8 Dec 2025 21:58:33 -0500 Subject: [PATCH 61/61] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Adam Poulemanos <89049923+bashandbone@users.noreply.github.com> --- mise.dev.toml | 8 +++----- mise.toml | 1 - 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/mise.dev.toml b/mise.dev.toml index 6770647ce..81a13eaee 100644 --- a/mise.dev.toml +++ b/mise.dev.toml @@ -48,11 +48,9 @@ esac run_windows = ''' @echo off set "pythonPath=%python_path%" -if not "%profile%"=="dev" ( - if not "%CI%"=="true" ( - rem don't run - exit /b 0 - ) +if "%profile%"=="dev" if "%CI%"=="true" ( + rem don't run + exit /b 0 ) if not "%pythonPath%"=="%pythonPath:.venv\Scripts\python=%" ( rem Already in venv, do nothing diff --git a/mise.toml b/mise.toml index 6c1f5694e..cef3a6423 100644 --- a/mise.toml +++ b/mise.toml @@ -119,7 +119,6 @@ run_windows = [ "mise install > NUL 2>&1 || echo \"[codeweaver] WARNING: mise install failed during setup.\"", "mise //:venv > NUL 2>&1", "mise //:sync > NUL 2>&1", - "mise env > NUL 2>&1", "git config include.path .gitconfig > NUL 2>&1", "echo src/codeweaver/_version.py >> .git\\info\\exclude", "echo coverage.xml >> .git\\info\\exclude",