fastmcp-extensions 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fastmcp_extensions-0.1.0/.github/dependabot.yml +35 -0
- fastmcp_extensions-0.1.0/.github/pr-welcome-message.md +32 -0
- fastmcp_extensions-0.1.0/.github/release-drafter.yml +81 -0
- fastmcp_extensions-0.1.0/.github/workflows/autofix-command.yml +37 -0
- fastmcp_extensions-0.1.0/.github/workflows/format-check.yml +31 -0
- fastmcp_extensions-0.1.0/.github/workflows/lint-check.yml +54 -0
- fastmcp_extensions-0.1.0/.github/workflows/lock-command.yml +37 -0
- fastmcp_extensions-0.1.0/.github/workflows/poe-command.yml +34 -0
- fastmcp_extensions-0.1.0/.github/workflows/pr-welcome.yml +23 -0
- fastmcp_extensions-0.1.0/.github/workflows/prerelease-command.yml +117 -0
- fastmcp_extensions-0.1.0/.github/workflows/publish.yml +199 -0
- fastmcp_extensions-0.1.0/.github/workflows/pytest-fast.yml +69 -0
- fastmcp_extensions-0.1.0/.github/workflows/pytest-matrix.yml +52 -0
- fastmcp_extensions-0.1.0/.github/workflows/release-drafter.yml +90 -0
- fastmcp_extensions-0.1.0/.github/workflows/semantic-pr-check.yml +112 -0
- fastmcp_extensions-0.1.0/.github/workflows/slash-command-dispatch.yml +53 -0
- fastmcp_extensions-0.1.0/.github/workflows/tk-todo-check.yml +45 -0
- fastmcp_extensions-0.1.0/.gitignore +210 -0
- fastmcp_extensions-0.1.0/.python-version +1 -0
- fastmcp_extensions-0.1.0/CONTRIBUTING.md +23 -0
- fastmcp_extensions-0.1.0/LICENSE +201 -0
- fastmcp_extensions-0.1.0/PKG-INFO +423 -0
- fastmcp_extensions-0.1.0/README.md +192 -0
- fastmcp_extensions-0.1.0/poe_tasks.toml +49 -0
- fastmcp_extensions-0.1.0/pyproject.toml +99 -0
- fastmcp_extensions-0.1.0/pytest.ini +26 -0
- fastmcp_extensions-0.1.0/ruff.toml +57 -0
- fastmcp_extensions-0.1.0/src/fastmcp_extensions/__init__.py +54 -0
- fastmcp_extensions-0.1.0/src/fastmcp_extensions/annotations.py +51 -0
- fastmcp_extensions-0.1.0/src/fastmcp_extensions/decorators.py +223 -0
- fastmcp_extensions-0.1.0/src/fastmcp_extensions/prompts.py +87 -0
- fastmcp_extensions-0.1.0/src/fastmcp_extensions/py.typed +0 -0
- fastmcp_extensions-0.1.0/src/fastmcp_extensions/registration.py +220 -0
- fastmcp_extensions-0.1.0/src/fastmcp_extensions/utils/__init__.py +40 -0
- fastmcp_extensions-0.1.0/src/fastmcp_extensions/utils/_http.py +32 -0
- fastmcp_extensions-0.1.0/src/fastmcp_extensions/utils/describe_server.py +192 -0
- fastmcp_extensions-0.1.0/src/fastmcp_extensions/utils/test_tool.py +211 -0
- fastmcp_extensions-0.1.0/tests/__init__.py +1 -0
- fastmcp_extensions-0.1.0/tests/test_fastmcp_extensions.py +126 -0
- fastmcp_extensions-0.1.0/uv.lock +2217 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# To get started with Dependabot version updates, you'll need to specify which
|
|
2
|
+
# package ecosystems to update and where the package manifests are located.
|
|
3
|
+
# Please see the documentation for all configuration options:
|
|
4
|
+
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
|
5
|
+
|
|
6
|
+
version: 2
|
|
7
|
+
updates:
|
|
8
|
+
- package-ecosystem: pip
|
|
9
|
+
directory: "/" # Location of package manifests
|
|
10
|
+
commit-message:
|
|
11
|
+
prefix: "chore(deps): "
|
|
12
|
+
schedule:
|
|
13
|
+
interval: daily
|
|
14
|
+
labels:
|
|
15
|
+
- chore
|
|
16
|
+
- dependencies
|
|
17
|
+
open-pull-requests-limit: 8 # default is 5
|
|
18
|
+
|
|
19
|
+
- package-ecosystem: github-actions
|
|
20
|
+
open-pull-requests-limit: 5 # default is 5
|
|
21
|
+
directory: "/"
|
|
22
|
+
commit-message:
|
|
23
|
+
prefix: "ci(deps): "
|
|
24
|
+
schedule:
|
|
25
|
+
interval: monthly
|
|
26
|
+
labels:
|
|
27
|
+
- ci
|
|
28
|
+
- dependencies
|
|
29
|
+
groups:
|
|
30
|
+
# allow combining github-actions updates into a single PR
|
|
31
|
+
minor-and-patch:
|
|
32
|
+
applies-to: version-updates
|
|
33
|
+
update-types:
|
|
34
|
+
- patch
|
|
35
|
+
- minor
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
🎉 **Thanks for opening this pull request!**
|
|
2
|
+
|
|
3
|
+
Your contribution is appreciated. Here are some helpful commands you can use:
|
|
4
|
+
|
|
5
|
+
## Quick Commands
|
|
6
|
+
- `/autofix` - Auto-format and fix linting issues (ruff format + ruff check --fix)
|
|
7
|
+
- `/lock` - Update the uv.lock file with latest dependencies
|
|
8
|
+
|
|
9
|
+
## Available Poe Tasks
|
|
10
|
+
You can run any of these tasks using the slash command: `/poe <task-name>`
|
|
11
|
+
|
|
12
|
+
### Core Tasks
|
|
13
|
+
- `/poe test` - Run all tests
|
|
14
|
+
- `/poe test-fast` - Run tests with fast exit on first failure
|
|
15
|
+
- `/poe lint` - Check code style and quality
|
|
16
|
+
- `/poe format` - Format code with ruff
|
|
17
|
+
- `/poe deps` - Check for unused and missing dependencies
|
|
18
|
+
- `/poe check` - Run format check, linting, dependency check, and tests
|
|
19
|
+
|
|
20
|
+
### Quick Fixes
|
|
21
|
+
- `/poe fix` - Auto-format and fix linting issues
|
|
22
|
+
- `/poe clean` - Clean up build artifacts and cache
|
|
23
|
+
|
|
24
|
+
### Build & Install
|
|
25
|
+
- `/poe build` - Build the package
|
|
26
|
+
- `/poe install` - Install with development dependencies
|
|
27
|
+
|
|
28
|
+
### Other Commands
|
|
29
|
+
- `/poe version` - Show package version
|
|
30
|
+
- `/poe pre-commit` - Run pre-commit style checks
|
|
31
|
+
|
|
32
|
+
The CI will automatically run tests when you push commits. Happy coding! 🚀
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
name-template: "v$RESOLVED_VERSION"
|
|
2
|
+
tag-template: "v$RESOLVED_VERSION"
|
|
3
|
+
categories:
|
|
4
|
+
- title: "New Features ✨"
|
|
5
|
+
labels:
|
|
6
|
+
- "feature"
|
|
7
|
+
- "enhancement"
|
|
8
|
+
- title: "Bug Fixes 🐛"
|
|
9
|
+
labels:
|
|
10
|
+
- "fix"
|
|
11
|
+
- "bugfix"
|
|
12
|
+
- "bug"
|
|
13
|
+
- title: "Under the Hood ⚙️"
|
|
14
|
+
labels:
|
|
15
|
+
- "chore"
|
|
16
|
+
- "ci"
|
|
17
|
+
- "refactor"
|
|
18
|
+
- "testing"
|
|
19
|
+
- title: "Documentation 📖"
|
|
20
|
+
label: "docs"
|
|
21
|
+
change-template: "- $TITLE (#$NUMBER)"
|
|
22
|
+
change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
|
|
23
|
+
version-resolver:
|
|
24
|
+
minor:
|
|
25
|
+
labels:
|
|
26
|
+
- "enhancement"
|
|
27
|
+
- "feature"
|
|
28
|
+
- "breaking"
|
|
29
|
+
# Semver rules are different before "1.0" If your project is v0.x, you
|
|
30
|
+
# don't want to auto-bump to 1.0.
|
|
31
|
+
# Uncomment and dedent if when/if you want to auto-select a major version
|
|
32
|
+
# bump.
|
|
33
|
+
# major:
|
|
34
|
+
# labels:
|
|
35
|
+
# - "breaking"
|
|
36
|
+
patch:
|
|
37
|
+
labels:
|
|
38
|
+
- "bug"
|
|
39
|
+
- "bugfix"
|
|
40
|
+
- "fix"
|
|
41
|
+
- "chore"
|
|
42
|
+
- "ci"
|
|
43
|
+
- "docs"
|
|
44
|
+
- "refactor"
|
|
45
|
+
- "testing"
|
|
46
|
+
- "dependencies"
|
|
47
|
+
- "security"
|
|
48
|
+
default: patch
|
|
49
|
+
template: |
|
|
50
|
+
$CHANGES
|
|
51
|
+
autolabeler:
|
|
52
|
+
- label: "chore"
|
|
53
|
+
title:
|
|
54
|
+
- '/^chore(\(.*\))?\:/i'
|
|
55
|
+
- label: "testing"
|
|
56
|
+
title:
|
|
57
|
+
- '/^tests(\(.*\))?\:/i'
|
|
58
|
+
- label: "ci"
|
|
59
|
+
title:
|
|
60
|
+
- '/^ci(\(.*\))?\:/i'
|
|
61
|
+
- label: "bug"
|
|
62
|
+
title:
|
|
63
|
+
- '/^fix(\(.*\))?\:/i'
|
|
64
|
+
- label: "enhancement"
|
|
65
|
+
title:
|
|
66
|
+
- '/^feat(\(.*\))?/i'
|
|
67
|
+
- label: "docs"
|
|
68
|
+
title:
|
|
69
|
+
- '/^docs(\(.*\))?\:/i'
|
|
70
|
+
- label: "security"
|
|
71
|
+
title:
|
|
72
|
+
- '/^security(\(.*\))?\:/i'
|
|
73
|
+
- '/^fix(\(security\))?\:/i'
|
|
74
|
+
- label: "dependencies"
|
|
75
|
+
title:
|
|
76
|
+
- '/^chore\(deps\)\:/i'
|
|
77
|
+
- '/^build\(deps\)\:/i'
|
|
78
|
+
- label: "breaking"
|
|
79
|
+
title:
|
|
80
|
+
# Match conventional commit breaking change syntax: feat!: or fix!: etc.
|
|
81
|
+
- '/^[a-z]+(\([^)]+\))?!:/i'
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: On-Demand Fix
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
pr:
|
|
7
|
+
description: "PR Number"
|
|
8
|
+
type: string
|
|
9
|
+
required: false
|
|
10
|
+
comment-id:
|
|
11
|
+
description: "Comment ID (Optional)"
|
|
12
|
+
type: string
|
|
13
|
+
required: false
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: write
|
|
17
|
+
pull-requests: write
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
run-autofix-command:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
steps:
|
|
23
|
+
- name: Authenticate as GitHub App (if available)
|
|
24
|
+
uses: actions/create-github-app-token@v2
|
|
25
|
+
id: get-app-token
|
|
26
|
+
continue-on-error: true
|
|
27
|
+
with:
|
|
28
|
+
app-id: ${{ secrets.OCTAVIA_BOT_APP_ID }}
|
|
29
|
+
private-key: ${{ secrets.OCTAVIA_BOT_PRIVATE_KEY }}
|
|
30
|
+
|
|
31
|
+
- name: Run Poe Autofix Command
|
|
32
|
+
uses: aaronsteers/poe-command-processor@v1.3.3
|
|
33
|
+
with:
|
|
34
|
+
pr: ${{ github.event.inputs.pr }}
|
|
35
|
+
comment-id: ${{ github.event.inputs.comment-id }}
|
|
36
|
+
github-token: ${{ steps.get-app-token.outputs.token || secrets.GITHUB_TOKEN }}
|
|
37
|
+
command: autofix
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: Format Check
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
pull_request: {}
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
ruff-format-check:
|
|
11
|
+
name: Ruff Format Check
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- name: Checkout code
|
|
15
|
+
uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Install uv
|
|
18
|
+
uses: astral-sh/setup-uv@v2
|
|
19
|
+
with:
|
|
20
|
+
version: "latest"
|
|
21
|
+
|
|
22
|
+
- name: Set up Python
|
|
23
|
+
uses: actions/setup-python@v5
|
|
24
|
+
with:
|
|
25
|
+
python-version: "3.10"
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: uv sync --extra dev
|
|
29
|
+
|
|
30
|
+
- name: Check code format
|
|
31
|
+
run: uv run ruff format --diff .
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: Lint Check
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
pull_request: {}
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
ruff-lint-check:
|
|
11
|
+
name: Ruff Lint Check
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- name: Checkout code
|
|
15
|
+
uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Install uv
|
|
18
|
+
uses: astral-sh/setup-uv@v2
|
|
19
|
+
with:
|
|
20
|
+
version: "latest"
|
|
21
|
+
|
|
22
|
+
- name: Set up Python
|
|
23
|
+
uses: actions/setup-python@v5
|
|
24
|
+
with:
|
|
25
|
+
python-version: "3.10"
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: uv sync --extra dev
|
|
29
|
+
|
|
30
|
+
- name: Run lint check
|
|
31
|
+
run: uv run ruff check .
|
|
32
|
+
|
|
33
|
+
deptry-check:
|
|
34
|
+
name: Dependency Analysis
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
steps:
|
|
37
|
+
- name: Checkout code
|
|
38
|
+
uses: actions/checkout@v4
|
|
39
|
+
|
|
40
|
+
- name: Install uv
|
|
41
|
+
uses: astral-sh/setup-uv@v2
|
|
42
|
+
with:
|
|
43
|
+
version: "latest"
|
|
44
|
+
|
|
45
|
+
- name: Set up Python
|
|
46
|
+
uses: actions/setup-python@v5
|
|
47
|
+
with:
|
|
48
|
+
python-version: "3.10"
|
|
49
|
+
|
|
50
|
+
- name: Install dependencies
|
|
51
|
+
run: uv sync --extra dev
|
|
52
|
+
|
|
53
|
+
- name: Run dependency analysis
|
|
54
|
+
run: uv run deptry .
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: On-Demand Lock
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
pr:
|
|
7
|
+
description: "PR Number"
|
|
8
|
+
type: string
|
|
9
|
+
required: false
|
|
10
|
+
comment-id:
|
|
11
|
+
description: "Comment ID (Optional)"
|
|
12
|
+
type: string
|
|
13
|
+
required: false
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: write
|
|
17
|
+
pull-requests: write
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
run-lock-command:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
steps:
|
|
23
|
+
- name: Authenticate as GitHub App (if available)
|
|
24
|
+
uses: actions/create-github-app-token@v2
|
|
25
|
+
id: get-app-token
|
|
26
|
+
continue-on-error: true
|
|
27
|
+
with:
|
|
28
|
+
app-id: ${{ secrets.OCTAVIA_BOT_APP_ID }}
|
|
29
|
+
private-key: ${{ secrets.OCTAVIA_BOT_PRIVATE_KEY }}
|
|
30
|
+
|
|
31
|
+
- name: Run Poe Lock Command
|
|
32
|
+
uses: aaronsteers/poe-command-processor@v1.3.3
|
|
33
|
+
with:
|
|
34
|
+
pr: ${{ github.event.inputs.pr }}
|
|
35
|
+
comment-id: ${{ github.event.inputs.comment-id }}
|
|
36
|
+
github-token: ${{ steps.get-app-token.outputs.token || secrets.GITHUB_TOKEN }}
|
|
37
|
+
command: lock
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: On-Demand Poe Task
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
comment-id:
|
|
7
|
+
description: "Optional comment-id of the slash command. Ignore if not applicable."
|
|
8
|
+
required: false
|
|
9
|
+
pr:
|
|
10
|
+
description: "PR Number"
|
|
11
|
+
required: false
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: write
|
|
15
|
+
pull-requests: write
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
run-poe-command:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- name: Authenticate as GitHub App (if available)
|
|
22
|
+
uses: actions/create-github-app-token@v2
|
|
23
|
+
id: get-app-token
|
|
24
|
+
continue-on-error: true
|
|
25
|
+
with:
|
|
26
|
+
app-id: ${{ secrets.OCTAVIA_BOT_APP_ID }}
|
|
27
|
+
private-key: ${{ secrets.OCTAVIA_BOT_PRIVATE_KEY }}
|
|
28
|
+
|
|
29
|
+
- name: Run Poe Slash Command Processor
|
|
30
|
+
uses: aaronsteers/poe-command-processor@v1.3.3
|
|
31
|
+
with:
|
|
32
|
+
pr: ${{ github.event.inputs.pr }}
|
|
33
|
+
comment-id: ${{ github.event.inputs.comment-id }}
|
|
34
|
+
github-token: ${{ steps.get-app-token.outputs.token || secrets.GITHUB_TOKEN }}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: PR Welcome
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, reopened]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
issues: write
|
|
10
|
+
pull-requests: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
welcome:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout repository
|
|
17
|
+
uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Create welcome comment
|
|
20
|
+
uses: peter-evans/create-or-update-comment@v5
|
|
21
|
+
with:
|
|
22
|
+
issue-number: ${{ github.event.pull_request.number }}
|
|
23
|
+
body-file: .github/pr-welcome-message.md
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Prerelease Command Workflow
|
|
2
|
+
#
|
|
3
|
+
# This workflow is triggered by the /prerelease slash command on a PR.
|
|
4
|
+
# It dispatches the publish workflow to build and publish a prerelease version.
|
|
5
|
+
#
|
|
6
|
+
# Usage: Comment `/prerelease` on a PR to trigger this workflow.
|
|
7
|
+
#
|
|
8
|
+
# Requirements:
|
|
9
|
+
# - PyPI Trusted Publisher configured for publish.yml (see publish.yml header for setup)
|
|
10
|
+
|
|
11
|
+
name: On-Demand Prerelease
|
|
12
|
+
|
|
13
|
+
on:
|
|
14
|
+
workflow_dispatch:
|
|
15
|
+
inputs:
|
|
16
|
+
pr:
|
|
17
|
+
description: "PR Number"
|
|
18
|
+
type: string
|
|
19
|
+
required: true
|
|
20
|
+
comment-id:
|
|
21
|
+
description: "Comment ID (Optional)"
|
|
22
|
+
type: string
|
|
23
|
+
required: false
|
|
24
|
+
|
|
25
|
+
permissions:
|
|
26
|
+
contents: read
|
|
27
|
+
pull-requests: write
|
|
28
|
+
issues: write
|
|
29
|
+
actions: write
|
|
30
|
+
|
|
31
|
+
jobs:
|
|
32
|
+
prerelease:
|
|
33
|
+
name: Trigger Prerelease Publish
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
steps:
|
|
36
|
+
- name: Create URL to the run output
|
|
37
|
+
id: vars
|
|
38
|
+
run: echo "run-url=https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" >> $GITHUB_OUTPUT
|
|
39
|
+
|
|
40
|
+
- name: Append comment with job run link
|
|
41
|
+
id: first-comment-action
|
|
42
|
+
if: github.event.inputs.comment-id
|
|
43
|
+
uses: peter-evans/create-or-update-comment@v4
|
|
44
|
+
with:
|
|
45
|
+
comment-id: ${{ github.event.inputs.comment-id }}
|
|
46
|
+
issue-number: ${{ github.event.inputs.pr }}
|
|
47
|
+
body: |
|
|
48
|
+
> **Prerelease Build Started**
|
|
49
|
+
>
|
|
50
|
+
> Building and publishing prerelease package from this PR...
|
|
51
|
+
> [Check job output.](${{ steps.vars.outputs.run-url }})
|
|
52
|
+
|
|
53
|
+
- name: Checkout to get latest tag
|
|
54
|
+
uses: actions/checkout@v4
|
|
55
|
+
with:
|
|
56
|
+
fetch-depth: 0
|
|
57
|
+
|
|
58
|
+
- name: Compute prerelease version
|
|
59
|
+
id: version
|
|
60
|
+
run: |
|
|
61
|
+
# Get the latest tag version (strip 'v' prefix if present)
|
|
62
|
+
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
|
|
63
|
+
BASE_VERSION=${LATEST_TAG#v}
|
|
64
|
+
# Create a unique prerelease version using PR number and run ID
|
|
65
|
+
# Format: {base}.dev{pr_number}{run_id} (e.g., 0.2.0.dev26123456789)
|
|
66
|
+
PRERELEASE_VERSION="${BASE_VERSION}.dev${{ github.event.inputs.pr }}${{ github.run_id }}"
|
|
67
|
+
echo "version=$PRERELEASE_VERSION" >> $GITHUB_OUTPUT
|
|
68
|
+
echo "Computed prerelease version: $PRERELEASE_VERSION"
|
|
69
|
+
|
|
70
|
+
- name: Trigger publish workflow
|
|
71
|
+
id: trigger-publish
|
|
72
|
+
uses: the-actions-org/workflow-dispatch@v4
|
|
73
|
+
with:
|
|
74
|
+
workflow: publish.yml
|
|
75
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
76
|
+
# Use refs/pull/<PR>/head for fork compatibility
|
|
77
|
+
ref: refs/pull/${{ github.event.inputs.pr }}/head
|
|
78
|
+
wait-for-completion: true
|
|
79
|
+
wait-for-completion-timeout: 10m
|
|
80
|
+
display-workflow-run-url: false
|
|
81
|
+
inputs: >-
|
|
82
|
+
{
|
|
83
|
+
"version": "${{ steps.version.outputs.version }}",
|
|
84
|
+
"publish_to_pypi": "true"
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
- name: Append success comment
|
|
88
|
+
if: success() && github.event.inputs.comment-id
|
|
89
|
+
uses: peter-evans/create-or-update-comment@v4
|
|
90
|
+
with:
|
|
91
|
+
comment-id: ${{ steps.first-comment-action.outputs.comment-id }}
|
|
92
|
+
issue-number: ${{ github.event.inputs.pr }}
|
|
93
|
+
reactions: rocket
|
|
94
|
+
body: |
|
|
95
|
+
> **Prerelease Published to TestPyPI**
|
|
96
|
+
>
|
|
97
|
+
> Version: `${{ steps.version.outputs.version }}`
|
|
98
|
+
> [View publish workflow](${{ steps.trigger-publish.outputs.workflow-url }})
|
|
99
|
+
>
|
|
100
|
+
> Install and test with any of the following:
|
|
101
|
+
> ```bash
|
|
102
|
+
> uv tool install fastmcp-extensions==${{ steps.version.outputs.version }} --index-url https://test.pypi.org/simple/
|
|
103
|
+
> uv add fastmcp-extensions==${{ steps.version.outputs.version }} --index-url https://test.pypi.org/simple/
|
|
104
|
+
> ```
|
|
105
|
+
|
|
106
|
+
- name: Append failure comment
|
|
107
|
+
if: failure() && github.event.inputs.comment-id
|
|
108
|
+
uses: peter-evans/create-or-update-comment@v4
|
|
109
|
+
with:
|
|
110
|
+
comment-id: ${{ steps.first-comment-action.outputs.comment-id }}
|
|
111
|
+
issue-number: ${{ github.event.inputs.pr }}
|
|
112
|
+
reactions: confused
|
|
113
|
+
body: |
|
|
114
|
+
> **Prerelease Build/Publish Failed**
|
|
115
|
+
>
|
|
116
|
+
> The prerelease encountered an error.
|
|
117
|
+
> [Check job output](${{ steps.vars.outputs.run-url }}) for details.
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# This workflow builds the python package and publishes to PyPI.
|
|
2
|
+
#
|
|
3
|
+
# Triggers:
|
|
4
|
+
# - release: published - When user clicks "Publish" on a draft release (downloads pre-built assets)
|
|
5
|
+
# - workflow_dispatch - Manual trigger for prereleases (builds fresh)
|
|
6
|
+
#
|
|
7
|
+
# Authentication: This workflow expects GitHub OIDC for passwordless PyPI publishing.
|
|
8
|
+
# For more info: https://docs.pypi.org/trusted-publishers/
|
|
9
|
+
|
|
10
|
+
name: Publish Package
|
|
11
|
+
|
|
12
|
+
on:
|
|
13
|
+
release:
|
|
14
|
+
types: [published]
|
|
15
|
+
workflow_dispatch:
|
|
16
|
+
inputs:
|
|
17
|
+
version:
|
|
18
|
+
description: >
|
|
19
|
+
Note that this workflow is intended for prereleases. For public-facing stable releases,
|
|
20
|
+
please use the GitHub Releases workflow instead.
|
|
21
|
+
For prereleases, please leave the version blank to use the detected version. Alternatively,
|
|
22
|
+
you can override the dynamic versioning for special use cases.
|
|
23
|
+
required: false
|
|
24
|
+
publish_to_pypi:
|
|
25
|
+
description: "Publish to PyPI. If true, the workflow will publish to PyPI."
|
|
26
|
+
type: boolean
|
|
27
|
+
required: true
|
|
28
|
+
default: true
|
|
29
|
+
|
|
30
|
+
jobs:
|
|
31
|
+
# Download pre-built assets from the release (only on release: published)
|
|
32
|
+
download_release_assets:
|
|
33
|
+
name: Download Release Assets
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
if: github.event_name == 'release'
|
|
36
|
+
steps:
|
|
37
|
+
- name: Download wheel and sdist from release
|
|
38
|
+
env:
|
|
39
|
+
GH_TOKEN: ${{ github.token }}
|
|
40
|
+
run: |
|
|
41
|
+
mkdir -p dist
|
|
42
|
+
gh release download "${{ github.event.release.tag_name }}" \
|
|
43
|
+
--repo "${{ github.repository }}" \
|
|
44
|
+
--pattern "*.whl" \
|
|
45
|
+
--pattern "*.tar.gz" \
|
|
46
|
+
--dir dist
|
|
47
|
+
echo "Downloaded assets:"
|
|
48
|
+
ls -la dist/
|
|
49
|
+
|
|
50
|
+
- name: Verify assets were downloaded
|
|
51
|
+
run: |
|
|
52
|
+
if [ ! -f dist/*.whl ]; then
|
|
53
|
+
echo "Error: No wheel file found in release assets"
|
|
54
|
+
exit 1
|
|
55
|
+
fi
|
|
56
|
+
if [ ! -f dist/*.tar.gz ]; then
|
|
57
|
+
echo "Error: No sdist file found in release assets"
|
|
58
|
+
exit 1
|
|
59
|
+
fi
|
|
60
|
+
echo "Assets verified successfully"
|
|
61
|
+
|
|
62
|
+
- uses: actions/upload-artifact@v5
|
|
63
|
+
with:
|
|
64
|
+
name: Packages-${{ github.run_id }}
|
|
65
|
+
path: |
|
|
66
|
+
dist/*.whl
|
|
67
|
+
dist/*.tar.gz
|
|
68
|
+
|
|
69
|
+
outputs:
|
|
70
|
+
VERSION: ${{ github.event.release.tag_name }}
|
|
71
|
+
|
|
72
|
+
# Build fresh package (only on workflow_dispatch, NOT on release)
|
|
73
|
+
build:
|
|
74
|
+
name: Build Python Package
|
|
75
|
+
runs-on: ubuntu-latest
|
|
76
|
+
if: github.event_name != 'release'
|
|
77
|
+
steps:
|
|
78
|
+
- name: Checkout Repo
|
|
79
|
+
uses: actions/checkout@v4
|
|
80
|
+
with:
|
|
81
|
+
fetch-depth: 0
|
|
82
|
+
|
|
83
|
+
- name: Detect Prerelease Version using Dunamai
|
|
84
|
+
uses: mtkennerly/dunamai-action@v1
|
|
85
|
+
with:
|
|
86
|
+
args: --format "{base}.post{distance}.dev${{ github.run_id }}"
|
|
87
|
+
env-var: DETECTED_VERSION
|
|
88
|
+
|
|
89
|
+
- name: Detect Release Tag Version from git ref ('${{ github.ref_name }}')
|
|
90
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
91
|
+
run: |
|
|
92
|
+
echo "Overriding Dunamai detected version: '${{ env.DETECTED_VERSION || 'none' }}'"
|
|
93
|
+
# Extract the version from the git ref
|
|
94
|
+
DETECTED_VERSION=${{ github.ref_name }}
|
|
95
|
+
# Remove the 'v' prefix if it exists
|
|
96
|
+
DETECTED_VERSION="${DETECTED_VERSION#v}"
|
|
97
|
+
echo "Setting detected version to '$DETECTED_VERSION'"
|
|
98
|
+
echo "DETECTED_VERSION=${DETECTED_VERSION}" >> $GITHUB_ENV
|
|
99
|
+
|
|
100
|
+
- name: Validate and set VERSION (detected='${{ env.DETECTED_VERSION }}', input='${{ github.event.inputs.version || 'none' }}')
|
|
101
|
+
id: set_version
|
|
102
|
+
run: |
|
|
103
|
+
INPUT_VERSION=${{ github.event.inputs.version }}
|
|
104
|
+
echo "Version input set to '${INPUT_VERSION}'"
|
|
105
|
+
# Exit with success if both detected and input versions are empty
|
|
106
|
+
if [ -z "${DETECTED_VERSION:-}" ] && [ -z "${INPUT_VERSION:-}" ]; then
|
|
107
|
+
echo "No version detected or input. Will publish to SHA tag instead."
|
|
108
|
+
echo 'VERSION=' >> $GITHUB_ENV
|
|
109
|
+
exit 0
|
|
110
|
+
fi
|
|
111
|
+
# Remove the 'v' prefix if it exists
|
|
112
|
+
INPUT_VERSION="${INPUT_VERSION#v}"
|
|
113
|
+
# Fail if detected version is non-empty and different from the input version
|
|
114
|
+
if [ -n "${DETECTED_VERSION:-}" ] && [ -n "${INPUT_VERSION:-}" ] && [ "${DETECTED_VERSION}" != "${INPUT_VERSION}" ]; then
|
|
115
|
+
echo "Warning: Version input '${INPUT_VERSION}' does not match detected version '${DETECTED_VERSION}'."
|
|
116
|
+
echo "Using input version '${INPUT_VERSION}' instead."
|
|
117
|
+
fi
|
|
118
|
+
# Set the version to the input version if non-empty, otherwise the detected version
|
|
119
|
+
VERSION="${INPUT_VERSION:-$DETECTED_VERSION}"
|
|
120
|
+
# Fail if the version is still empty
|
|
121
|
+
if [ -z "$VERSION" ]; then
|
|
122
|
+
echo "Error: VERSION is not set. Ensure the tag follows the format 'refs/tags/vX.Y.Z'."
|
|
123
|
+
exit 1
|
|
124
|
+
fi
|
|
125
|
+
echo "Setting version to '$VERSION'"
|
|
126
|
+
echo "VERSION=${VERSION}" >> $GITHUB_ENV
|
|
127
|
+
echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
|
|
128
|
+
# Check if version is a prerelease version (will not tag 'latest')
|
|
129
|
+
if [[ "${VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
130
|
+
echo "IS_PRERELEASE=false" >> $GITHUB_ENV
|
|
131
|
+
echo "IS_PRERELEASE=false" >> $GITHUB_OUTPUT
|
|
132
|
+
else
|
|
133
|
+
echo "IS_PRERELEASE=true" >> $GITHUB_ENV
|
|
134
|
+
echo "IS_PRERELEASE=true" >> $GITHUB_OUTPUT
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
- name: Install uv
|
|
138
|
+
uses: astral-sh/setup-uv@v2
|
|
139
|
+
with:
|
|
140
|
+
version: "latest"
|
|
141
|
+
|
|
142
|
+
- name: Set up Python
|
|
143
|
+
uses: actions/setup-python@v5
|
|
144
|
+
with:
|
|
145
|
+
python-version: "3.12"
|
|
146
|
+
|
|
147
|
+
- name: Build package
|
|
148
|
+
env:
|
|
149
|
+
# Use UV_DYNAMIC_VERSIONING_BYPASS to override the version in pyproject.toml
|
|
150
|
+
# This ensures the build matches the detected/validated VERSION.
|
|
151
|
+
UV_DYNAMIC_VERSIONING_BYPASS: ${{ env.VERSION }}
|
|
152
|
+
run: uv build
|
|
153
|
+
|
|
154
|
+
- uses: actions/upload-artifact@v5
|
|
155
|
+
with:
|
|
156
|
+
name: Packages-${{ github.run_id }}
|
|
157
|
+
path: |
|
|
158
|
+
dist/*.whl
|
|
159
|
+
dist/*.tar.gz
|
|
160
|
+
|
|
161
|
+
outputs:
|
|
162
|
+
VERSION: ${{ steps.set_version.outputs.VERSION }}
|
|
163
|
+
IS_PRERELEASE: ${{ steps.set_version.outputs.IS_PRERELEASE }}
|
|
164
|
+
|
|
165
|
+
publish_to_pypi:
|
|
166
|
+
name: Publish Package to PyPI
|
|
167
|
+
runs-on: ubuntu-latest
|
|
168
|
+
# Depend on whichever job ran (build for dispatch, download for release)
|
|
169
|
+
needs: [build, download_release_assets]
|
|
170
|
+
# Always run if at least one of the needed jobs succeeded
|
|
171
|
+
if: |
|
|
172
|
+
always() &&
|
|
173
|
+
(needs.build.result == 'success' || needs.download_release_assets.result == 'success') &&
|
|
174
|
+
(
|
|
175
|
+
github.event_name == 'release' ||
|
|
176
|
+
(github.event_name == 'workflow_dispatch' && github.event.inputs.publish_to_pypi == 'true')
|
|
177
|
+
)
|
|
178
|
+
permissions:
|
|
179
|
+
id-token: write
|
|
180
|
+
contents: write
|
|
181
|
+
environment:
|
|
182
|
+
name: PyPI
|
|
183
|
+
url: https://pypi.org/p/fastmcp-extensions/
|
|
184
|
+
env:
|
|
185
|
+
VERSION: ${{ needs.build.outputs.VERSION || needs.download_release_assets.outputs.VERSION }}
|
|
186
|
+
IS_PRERELEASE: ${{ needs.build.outputs.IS_PRERELEASE || 'false' }}
|
|
187
|
+
steps:
|
|
188
|
+
- uses: actions/download-artifact@v6
|
|
189
|
+
with:
|
|
190
|
+
name: Packages-${{ github.run_id }}
|
|
191
|
+
path: dist
|
|
192
|
+
|
|
193
|
+
# Note: Wheel upload to GitHub release is handled by release-drafter.yml
|
|
194
|
+
# during the draft stage (before publish). This avoids the "immutable release"
|
|
195
|
+
# error that occurs when trying to upload assets after a release is published.
|
|
196
|
+
|
|
197
|
+
- name: Publish to PyPI
|
|
198
|
+
# Uses GitHub OIDC for passwordless authentication (see header comment)
|
|
199
|
+
uses: pypa/gh-action-pypi-publish@v1.13.0
|