graylog-mcp 0.3.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.
- graylog_mcp-0.3.0/.dockerignore +8 -0
- graylog_mcp-0.3.0/.editorconfig +12 -0
- graylog_mcp-0.3.0/.github/CODEOWNERS +1 -0
- graylog_mcp-0.3.0/.github/ISSUE_TEMPLATE/bug_report.yml +34 -0
- graylog_mcp-0.3.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- graylog_mcp-0.3.0/.github/ISSUE_TEMPLATE/feature_request.yml +16 -0
- graylog_mcp-0.3.0/.github/dependabot.yml +23 -0
- graylog_mcp-0.3.0/.github/pull_request_template.md +15 -0
- graylog_mcp-0.3.0/.github/workflows/ci.yml +156 -0
- graylog_mcp-0.3.0/.github/workflows/claude.yml +48 -0
- graylog_mcp-0.3.0/.github/workflows/codeql.yml +34 -0
- graylog_mcp-0.3.0/.github/workflows/integration.yml +53 -0
- graylog_mcp-0.3.0/.github/workflows/release.yml +96 -0
- graylog_mcp-0.3.0/.gitignore +9 -0
- graylog_mcp-0.3.0/.pre-commit-config.yaml +26 -0
- graylog_mcp-0.3.0/CHANGELOG.md +238 -0
- graylog_mcp-0.3.0/CLAUDE.md +27 -0
- graylog_mcp-0.3.0/CONTRIBUTING.md +46 -0
- graylog_mcp-0.3.0/Dockerfile +22 -0
- graylog_mcp-0.3.0/LICENSE +21 -0
- graylog_mcp-0.3.0/PKG-INFO +879 -0
- graylog_mcp-0.3.0/README.md +852 -0
- graylog_mcp-0.3.0/SECURITY.md +24 -0
- graylog_mcp-0.3.0/examples/config.toml +134 -0
- graylog_mcp-0.3.0/pyproject.toml +92 -0
- graylog_mcp-0.3.0/src/graylog_mcp/__init__.py +3 -0
- graylog_mcp-0.3.0/src/graylog_mcp/__main__.py +1246 -0
- graylog_mcp-0.3.0/src/graylog_mcp/admin/__init__.py +1 -0
- graylog_mcp-0.3.0/src/graylog_mcp/admin/app.py +948 -0
- graylog_mcp-0.3.0/src/graylog_mcp/admin/static/index.html +1758 -0
- graylog_mcp-0.3.0/src/graylog_mcp/ask/__init__.py +1 -0
- graylog_mcp-0.3.0/src/graylog_mcp/ask/flow.py +91 -0
- graylog_mcp-0.3.0/src/graylog_mcp/ask/jev.py +70 -0
- graylog_mcp-0.3.0/src/graylog_mcp/ask/pipeline.py +162 -0
- graylog_mcp-0.3.0/src/graylog_mcp/ask/render.py +59 -0
- graylog_mcp-0.3.0/src/graylog_mcp/ask/understand.py +90 -0
- graylog_mcp-0.3.0/src/graylog_mcp/backends/__init__.py +500 -0
- graylog_mcp-0.3.0/src/graylog_mcp/backends/base.py +89 -0
- graylog_mcp-0.3.0/src/graylog_mcp/backends/scripting.py +95 -0
- graylog_mcp-0.3.0/src/graylog_mcp/backends/universal.py +40 -0
- graylog_mcp-0.3.0/src/graylog_mcp/backends/views.py +180 -0
- graylog_mcp-0.3.0/src/graylog_mcp/client.py +302 -0
- graylog_mcp-0.3.0/src/graylog_mcp/config.py +1517 -0
- graylog_mcp-0.3.0/src/graylog_mcp/focus.py +59 -0
- graylog_mcp-0.3.0/src/graylog_mcp/operations.py +113 -0
- graylog_mcp-0.3.0/src/graylog_mcp/rca.py +870 -0
- graylog_mcp-0.3.0/src/graylog_mcp/recover.py +707 -0
- graylog_mcp-0.3.0/src/graylog_mcp/redact.py +447 -0
- graylog_mcp-0.3.0/src/graylog_mcp/scan.py +556 -0
- graylog_mcp-0.3.0/src/graylog_mcp/scanrules.py +93 -0
- graylog_mcp-0.3.0/src/graylog_mcp/secrets.py +96 -0
- graylog_mcp-0.3.0/src/graylog_mcp/server.py +221 -0
- graylog_mcp-0.3.0/src/graylog_mcp/setup/__init__.py +1 -0
- graylog_mcp-0.3.0/src/graylog_mcp/setup/clients.py +486 -0
- graylog_mcp-0.3.0/src/graylog_mcp/setup/configfile.py +502 -0
- graylog_mcp-0.3.0/src/graylog_mcp/setup/connect.py +55 -0
- graylog_mcp-0.3.0/src/graylog_mcp/setup/detect.py +220 -0
- graylog_mcp-0.3.0/src/graylog_mcp/setup/doctor.py +187 -0
- graylog_mcp-0.3.0/src/graylog_mcp/setup/remote.py +130 -0
- graylog_mcp-0.3.0/src/graylog_mcp/setup/service.py +642 -0
- graylog_mcp-0.3.0/src/graylog_mcp/setup/tomlwrite.py +69 -0
- graylog_mcp-0.3.0/src/graylog_mcp/setup/wizard.py +303 -0
- graylog_mcp-0.3.0/src/graylog_mcp/shaping.py +309 -0
- graylog_mcp-0.3.0/src/graylog_mcp/shared.py +208 -0
- graylog_mcp-0.3.0/src/graylog_mcp/timerange.py +215 -0
- graylog_mcp-0.3.0/src/graylog_mcp/tools.py +1198 -0
- graylog_mcp-0.3.0/src/graylog_mcp/toolspecs/__init__.py +23 -0
- graylog_mcp-0.3.0/src/graylog_mcp/toolspecs/discovery.py +62 -0
- graylog_mcp-0.3.0/src/graylog_mcp/toolspecs/investigate.py +120 -0
- graylog_mcp-0.3.0/src/graylog_mcp/toolspecs/scanning.py +74 -0
- graylog_mcp-0.3.0/src/graylog_mcp/toolspecs/search.py +145 -0
- graylog_mcp-0.3.0/src/graylog_mcp/toolspecs/spec.py +117 -0
- graylog_mcp-0.3.0/src/graylog_mcp/usage.py +220 -0
- graylog_mcp-0.3.0/tests/__init__.py +0 -0
- graylog_mcp-0.3.0/tests/conftest.py +78 -0
- graylog_mcp-0.3.0/tests/fake_claude.py +69 -0
- graylog_mcp-0.3.0/tests/fake_graylog.py +800 -0
- graylog_mcp-0.3.0/tests/fake_jev.py +56 -0
- graylog_mcp-0.3.0/tests/integration/docker-compose.yml +112 -0
- graylog_mcp-0.3.0/tests/integration/run.sh +16 -0
- graylog_mcp-0.3.0/tests/integration/seed.py +171 -0
- graylog_mcp-0.3.0/tests/integration/test_integration.py +204 -0
- graylog_mcp-0.3.0/tests/smoke_repo.py +181 -0
- graylog_mcp-0.3.0/tests/smoke_start.py +95 -0
- graylog_mcp-0.3.0/tests/snapshots/model_surface.json +1191 -0
- graylog_mcp-0.3.0/tests/test_ask.py +227 -0
- graylog_mcp-0.3.0/tests/test_cli.py +110 -0
- graylog_mcp-0.3.0/tests/test_client.py +120 -0
- graylog_mcp-0.3.0/tests/test_config.py +170 -0
- graylog_mcp-0.3.0/tests/test_config_writes.py +189 -0
- graylog_mcp-0.3.0/tests/test_connect.py +150 -0
- graylog_mcp-0.3.0/tests/test_focus.py +183 -0
- graylog_mcp-0.3.0/tests/test_groups.py +195 -0
- graylog_mcp-0.3.0/tests/test_http.py +35 -0
- graylog_mcp-0.3.0/tests/test_model_surface.py +26 -0
- graylog_mcp-0.3.0/tests/test_operations.py +65 -0
- graylog_mcp-0.3.0/tests/test_output_budget.py +265 -0
- graylog_mcp-0.3.0/tests/test_permissions_textfields.py +70 -0
- graylog_mcp-0.3.0/tests/test_rca.py +241 -0
- graylog_mcp-0.3.0/tests/test_recover.py +238 -0
- graylog_mcp-0.3.0/tests/test_redact.py +491 -0
- graylog_mcp-0.3.0/tests/test_regressions.py +191 -0
- graylog_mcp-0.3.0/tests/test_remote.py +101 -0
- graylog_mcp-0.3.0/tests/test_repos.py +309 -0
- graylog_mcp-0.3.0/tests/test_scan.py +184 -0
- graylog_mcp-0.3.0/tests/test_scan_scenarios.py +269 -0
- graylog_mcp-0.3.0/tests/test_service.py +718 -0
- graylog_mcp-0.3.0/tests/test_setup.py +524 -0
- graylog_mcp-0.3.0/tests/test_shaping.py +75 -0
- graylog_mcp-0.3.0/tests/test_shared.py +254 -0
- graylog_mcp-0.3.0/tests/test_stacktrace.py +132 -0
- graylog_mcp-0.3.0/tests/test_timerange.py +75 -0
- graylog_mcp-0.3.0/tests/test_tools_contract.py +375 -0
- graylog_mcp-0.3.0/tests/test_toolspecs.py +157 -0
- graylog_mcp-0.3.0/tests/test_usage.py +169 -0
- graylog_mcp-0.3.0/uv.lock +1364 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* @ntbang0901
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something does not work as documented
|
|
3
|
+
labels: [bug]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: "Do not paste log lines, tokens or URLs of private Graylog instances. For security problems (for example a value that should be masked but is not), see SECURITY.md instead."
|
|
8
|
+
- type: input
|
|
9
|
+
id: version
|
|
10
|
+
attributes:
|
|
11
|
+
label: graylog-mcp version
|
|
12
|
+
placeholder: "graylog-mcp --version"
|
|
13
|
+
validations:
|
|
14
|
+
required: true
|
|
15
|
+
- type: input
|
|
16
|
+
id: graylog
|
|
17
|
+
attributes:
|
|
18
|
+
label: Graylog version and search backend
|
|
19
|
+
placeholder: "6.1.16 with OpenSearch 2.15 (shown by list_instances)"
|
|
20
|
+
validations:
|
|
21
|
+
required: true
|
|
22
|
+
- type: textarea
|
|
23
|
+
id: what
|
|
24
|
+
attributes:
|
|
25
|
+
label: What happened and what you expected
|
|
26
|
+
description: The tool called, its arguments and the (redacted) result or error.
|
|
27
|
+
validations:
|
|
28
|
+
required: true
|
|
29
|
+
- type: textarea
|
|
30
|
+
id: config
|
|
31
|
+
attributes:
|
|
32
|
+
label: Relevant configuration
|
|
33
|
+
description: Remove secrets and hostnames.
|
|
34
|
+
render: toml
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: A tool, option or behaviour you would like
|
|
3
|
+
labels: [enhancement]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: Problem
|
|
9
|
+
description: What are you trying to investigate or automate, and what gets in the way today?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: proposal
|
|
14
|
+
attributes:
|
|
15
|
+
label: Proposal
|
|
16
|
+
description: How it could work. Note that the server must stay read-only towards Graylog.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: uv
|
|
4
|
+
directory: /
|
|
5
|
+
schedule:
|
|
6
|
+
interval: weekly
|
|
7
|
+
groups:
|
|
8
|
+
python:
|
|
9
|
+
patterns: ["*"]
|
|
10
|
+
open-pull-requests-limit: 5
|
|
11
|
+
|
|
12
|
+
- package-ecosystem: github-actions
|
|
13
|
+
directory: /
|
|
14
|
+
schedule:
|
|
15
|
+
interval: weekly
|
|
16
|
+
groups:
|
|
17
|
+
actions:
|
|
18
|
+
patterns: ["*"]
|
|
19
|
+
|
|
20
|
+
- package-ecosystem: docker
|
|
21
|
+
directory: /
|
|
22
|
+
schedule:
|
|
23
|
+
interval: weekly
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
## What and why
|
|
2
|
+
|
|
3
|
+
<!-- What does this change and which problem does it solve? Link the issue if there is one. -->
|
|
4
|
+
|
|
5
|
+
## How it was tested
|
|
6
|
+
|
|
7
|
+
- [ ] `uv run pytest` (unit + contract)
|
|
8
|
+
- [ ] `uv run ruff check && uv run ruff format --check && uv run mypy`
|
|
9
|
+
- [ ] Integration against real Graylog (`tests/integration/run.sh <v43|v50|v52|v61|v70>`) — needed for changes to `backends/`, `client.py` or query building
|
|
10
|
+
|
|
11
|
+
## Checklist
|
|
12
|
+
|
|
13
|
+
- [ ] The server still never writes to Graylog (only GET, and POST to the read-only search endpoints)
|
|
14
|
+
- [ ] New output goes through redaction and the size budget
|
|
15
|
+
- [ ] CHANGELOG.md updated under "Unreleased"
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ["**"]
|
|
6
|
+
tags-ignore: ["**"]
|
|
7
|
+
pull_request:
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: ci-${{ github.event.pull_request.number || github.ref }}
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
env:
|
|
18
|
+
FORCE_COLOR: "1"
|
|
19
|
+
UV_LOCKED: "1" # every uv command must match uv.lock
|
|
20
|
+
|
|
21
|
+
# Branch pushes run CI directly; pull requests run only when they come from a fork (a same-repo
|
|
22
|
+
# PR is already covered by the push of its branch). Each job repeats this condition.
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
lint:
|
|
26
|
+
name: Lint and type check
|
|
27
|
+
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
timeout-minutes: 10
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@v7
|
|
32
|
+
- uses: astral-sh/setup-uv@v7
|
|
33
|
+
with:
|
|
34
|
+
python-version: "3.13"
|
|
35
|
+
enable-cache: true
|
|
36
|
+
- run: uv sync
|
|
37
|
+
- name: Lockfile up to date
|
|
38
|
+
run: uv lock --check
|
|
39
|
+
- name: Ruff lint
|
|
40
|
+
run: uv run ruff check --output-format=github
|
|
41
|
+
- name: Ruff format
|
|
42
|
+
run: uv run ruff format --check
|
|
43
|
+
- name: Mypy
|
|
44
|
+
run: uv run mypy
|
|
45
|
+
|
|
46
|
+
test:
|
|
47
|
+
name: Test (${{ matrix.os }}, py${{ matrix.python }})
|
|
48
|
+
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository
|
|
49
|
+
runs-on: ${{ matrix.os }}
|
|
50
|
+
timeout-minutes: 15
|
|
51
|
+
strategy:
|
|
52
|
+
fail-fast: false
|
|
53
|
+
matrix:
|
|
54
|
+
os: [ubuntu-latest]
|
|
55
|
+
python: ["3.11", "3.12", "3.13"]
|
|
56
|
+
include:
|
|
57
|
+
- { os: windows-latest, python: "3.13" }
|
|
58
|
+
- { os: macos-latest, python: "3.13" }
|
|
59
|
+
steps:
|
|
60
|
+
- uses: actions/checkout@v7
|
|
61
|
+
- uses: astral-sh/setup-uv@v7
|
|
62
|
+
with:
|
|
63
|
+
python-version: ${{ matrix.python }}
|
|
64
|
+
enable-cache: true
|
|
65
|
+
- run: uv sync
|
|
66
|
+
- name: Unit and contract tests
|
|
67
|
+
run: uv run pytest -q --cov --cov-report=term --cov-report=xml
|
|
68
|
+
- uses: actions/upload-artifact@v7
|
|
69
|
+
if: matrix.os == 'ubuntu-latest' && matrix.python == '3.13'
|
|
70
|
+
with:
|
|
71
|
+
name: coverage
|
|
72
|
+
path: coverage.xml
|
|
73
|
+
|
|
74
|
+
build:
|
|
75
|
+
name: Build and check distribution
|
|
76
|
+
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository
|
|
77
|
+
runs-on: ubuntu-latest
|
|
78
|
+
timeout-minutes: 10
|
|
79
|
+
steps:
|
|
80
|
+
- uses: actions/checkout@v7
|
|
81
|
+
- uses: astral-sh/setup-uv@v7
|
|
82
|
+
with:
|
|
83
|
+
python-version: "3.13"
|
|
84
|
+
- run: uv build
|
|
85
|
+
- name: Check metadata
|
|
86
|
+
run: uvx twine check --strict dist/*
|
|
87
|
+
- name: Smoke test the wheel in a clean environment
|
|
88
|
+
run: |
|
|
89
|
+
uv venv /tmp/smoke
|
|
90
|
+
uv pip install --python /tmp/smoke dist/*.whl
|
|
91
|
+
/tmp/smoke/bin/graylog-mcp --version
|
|
92
|
+
# --check exits 1 when an instance is unreachable, 2 on a configuration error
|
|
93
|
+
set +e
|
|
94
|
+
GRAYLOG_URL=http://127.0.0.1:9 GRAYLOG_TOKEN=x /tmp/smoke/bin/graylog-mcp --check > /dev/null
|
|
95
|
+
test $? -eq 1
|
|
96
|
+
- uses: actions/upload-artifact@v7
|
|
97
|
+
with:
|
|
98
|
+
name: dist
|
|
99
|
+
path: dist/
|
|
100
|
+
|
|
101
|
+
docker:
|
|
102
|
+
name: Docker image
|
|
103
|
+
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository
|
|
104
|
+
runs-on: ubuntu-latest
|
|
105
|
+
timeout-minutes: 15
|
|
106
|
+
steps:
|
|
107
|
+
- uses: actions/checkout@v7
|
|
108
|
+
- uses: docker/setup-buildx-action@v4
|
|
109
|
+
- uses: docker/build-push-action@v7
|
|
110
|
+
with:
|
|
111
|
+
context: .
|
|
112
|
+
load: true
|
|
113
|
+
tags: graylog-mcp:ci
|
|
114
|
+
cache-from: type=gha
|
|
115
|
+
cache-to: type=gha,mode=max
|
|
116
|
+
- name: Smoke test the image
|
|
117
|
+
run: |
|
|
118
|
+
docker run --rm --entrypoint graylog-mcp graylog-mcp:ci --version
|
|
119
|
+
docker run -d --name mcp -p 8000:8000 -e GRAYLOG_URL=http://127.0.0.1:9 -e GRAYLOG_TOKEN=x \
|
|
120
|
+
-e GRAYLOG_MCP_HTTP_TOKEN=ci graylog-mcp:ci
|
|
121
|
+
for i in $(seq 1 30); do curl -fs localhost:8000/healthz && break; sleep 1; done
|
|
122
|
+
test "$(curl -s -o /dev/null -w '%{http_code}' -X POST localhost:8000/mcp)" = 401
|
|
123
|
+
docker rm -f mcp
|
|
124
|
+
|
|
125
|
+
start:
|
|
126
|
+
name: Start at login (${{ matrix.os }})
|
|
127
|
+
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository
|
|
128
|
+
runs-on: ${{ matrix.os }}
|
|
129
|
+
timeout-minutes: 15
|
|
130
|
+
strategy:
|
|
131
|
+
fail-fast: false
|
|
132
|
+
matrix:
|
|
133
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
134
|
+
steps:
|
|
135
|
+
- uses: actions/checkout@v7
|
|
136
|
+
- uses: astral-sh/setup-uv@v7
|
|
137
|
+
with:
|
|
138
|
+
python-version: "3.13"
|
|
139
|
+
- run: uv sync
|
|
140
|
+
- name: start, crash, restart, stop with the real service manager
|
|
141
|
+
env:
|
|
142
|
+
XDG_CURRENT_DESKTOP: CI # Linux without a systemd user session: XDG autostart
|
|
143
|
+
run: uv run python tests/smoke_start.py
|
|
144
|
+
- name: per-repository setup, port change and update on this machine
|
|
145
|
+
run: uv run python tests/smoke_repo.py
|
|
146
|
+
|
|
147
|
+
# Single required check for branch protection.
|
|
148
|
+
ci-ok:
|
|
149
|
+
name: CI passed
|
|
150
|
+
if: always()
|
|
151
|
+
needs: [lint, test, build, docker, start]
|
|
152
|
+
runs-on: ubuntu-latest
|
|
153
|
+
steps:
|
|
154
|
+
- env:
|
|
155
|
+
NEEDS: ${{ toJSON(needs) }}
|
|
156
|
+
run: echo "$NEEDS" | jq -e 'all(.[]; .result == "success" or .result == "skipped")'
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: Claude
|
|
2
|
+
|
|
3
|
+
# Claude implements an issue when a maintainer adds the "claude" label, and answers "@claude" in issues and pull
|
|
4
|
+
# requests. It works on a claude/ branch and opens a pull request for review; it never pushes to main.
|
|
5
|
+
# Only people with write access trigger it: labels need triage access, and the action ignores comments from others.
|
|
6
|
+
# Auth: the repository secret ANTHROPIC_API_KEY.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
issues:
|
|
10
|
+
types: [labeled]
|
|
11
|
+
issue_comment:
|
|
12
|
+
types: [created]
|
|
13
|
+
pull_request_review_comment:
|
|
14
|
+
types: [created]
|
|
15
|
+
pull_request_review:
|
|
16
|
+
types: [submitted]
|
|
17
|
+
|
|
18
|
+
permissions: {}
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
claude:
|
|
22
|
+
if: >-
|
|
23
|
+
(github.event_name == 'issues' && github.event.label.name == 'claude') ||
|
|
24
|
+
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
25
|
+
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
26
|
+
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude'))
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
timeout-minutes: 30
|
|
29
|
+
concurrency:
|
|
30
|
+
group: claude-${{ github.event.issue.number || github.event.pull_request.number }}
|
|
31
|
+
permissions:
|
|
32
|
+
contents: write
|
|
33
|
+
pull-requests: write
|
|
34
|
+
issues: write
|
|
35
|
+
id-token: write
|
|
36
|
+
actions: read
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@v7
|
|
39
|
+
with:
|
|
40
|
+
fetch-depth: 1
|
|
41
|
+
- uses: astral-sh/setup-uv@v7
|
|
42
|
+
- uses: anthropics/claude-code-action@v1
|
|
43
|
+
with:
|
|
44
|
+
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
45
|
+
label_trigger: claude
|
|
46
|
+
claude_args: >-
|
|
47
|
+
--max-turns 60
|
|
48
|
+
--allowedTools "Bash(uv sync:*),Bash(uv run pytest:*),Bash(uv run ruff:*),Bash(uv run mypy:*),Bash(git:*)"
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: CodeQL
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, "claude/**"]
|
|
6
|
+
pull_request:
|
|
7
|
+
schedule:
|
|
8
|
+
- cron: "23 4 * * 2"
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
analyze:
|
|
15
|
+
name: Analyze (python, actions)
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
timeout-minutes: 20
|
|
18
|
+
permissions:
|
|
19
|
+
security-events: write
|
|
20
|
+
actions: read
|
|
21
|
+
contents: read
|
|
22
|
+
strategy:
|
|
23
|
+
fail-fast: false
|
|
24
|
+
matrix:
|
|
25
|
+
language: [python, actions]
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v7
|
|
28
|
+
- uses: github/codeql-action/init@v4
|
|
29
|
+
with:
|
|
30
|
+
languages: ${{ matrix.language }}
|
|
31
|
+
queries: security-extended
|
|
32
|
+
- uses: github/codeql-action/analyze@v4
|
|
33
|
+
with:
|
|
34
|
+
category: /language:${{ matrix.language }}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: Integration (Graylog matrix)
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
schedule:
|
|
6
|
+
- cron: "17 3 * * 1" # weekly
|
|
7
|
+
pull_request:
|
|
8
|
+
paths:
|
|
9
|
+
- "src/graylog_mcp/backends/**"
|
|
10
|
+
- "src/graylog_mcp/client.py"
|
|
11
|
+
- "src/graylog_mcp/rca.py"
|
|
12
|
+
- "src/graylog_mcp/scan.py"
|
|
13
|
+
- "src/graylog_mcp/scanrules.py"
|
|
14
|
+
- "tests/fake_graylog.py"
|
|
15
|
+
- "tests/integration/**"
|
|
16
|
+
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
|
|
20
|
+
concurrency:
|
|
21
|
+
group: integration-${{ github.event.pull_request.number || github.ref }}
|
|
22
|
+
cancel-in-progress: true
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
graylog:
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
timeout-minutes: 30
|
|
28
|
+
strategy:
|
|
29
|
+
fail-fast: false
|
|
30
|
+
matrix:
|
|
31
|
+
include:
|
|
32
|
+
- { profile: v43, port: 9043 }
|
|
33
|
+
- { profile: v50, port: 9050 }
|
|
34
|
+
- { profile: v52, port: 9052 }
|
|
35
|
+
- { profile: v61, port: 9061 }
|
|
36
|
+
- { profile: v70, port: 9070 }
|
|
37
|
+
env:
|
|
38
|
+
GRAYLOG_IT_URL: http://127.0.0.1:${{ matrix.port }}
|
|
39
|
+
steps:
|
|
40
|
+
- uses: actions/checkout@v7
|
|
41
|
+
- uses: astral-sh/setup-uv@v7
|
|
42
|
+
with:
|
|
43
|
+
python-version: "3.13"
|
|
44
|
+
enable-cache: true
|
|
45
|
+
- run: uv sync --locked
|
|
46
|
+
- run: sudo sysctl -w vm.max_map_count=262144
|
|
47
|
+
- run: docker compose -f tests/integration/docker-compose.yml --profile ${{ matrix.profile }} up -d
|
|
48
|
+
- name: Seed Graylog
|
|
49
|
+
run: uv run python tests/integration/seed.py
|
|
50
|
+
- name: Run every tool against Graylog
|
|
51
|
+
run: uv run pytest -m integration -v -s tests/integration
|
|
52
|
+
- if: failure()
|
|
53
|
+
run: docker compose -f tests/integration/docker-compose.yml --profile ${{ matrix.profile }} logs --tail 200
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v7
|
|
15
|
+
- uses: astral-sh/setup-uv@v7
|
|
16
|
+
- run: uv sync --locked && uv run pytest -q && uv run mypy
|
|
17
|
+
- name: Check tag matches version and changelog
|
|
18
|
+
run: |
|
|
19
|
+
version="${GITHUB_REF_NAME#v}"
|
|
20
|
+
test "$(uv run python -c 'import graylog_mcp; print(graylog_mcp.__version__)')" = "$version"
|
|
21
|
+
grep -q "^version = \"$version\"" pyproject.toml
|
|
22
|
+
grep -q "^## \[$version\]" CHANGELOG.md
|
|
23
|
+
- run: uv build
|
|
24
|
+
- uses: actions/upload-artifact@v7
|
|
25
|
+
with:
|
|
26
|
+
name: dist
|
|
27
|
+
path: dist/
|
|
28
|
+
|
|
29
|
+
publish-pypi:
|
|
30
|
+
needs: build
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
environment: pypi
|
|
33
|
+
permissions:
|
|
34
|
+
id-token: write # PyPI trusted publishing + PEP 740 attestations (signed with Sigstore)
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/download-artifact@v8
|
|
37
|
+
with:
|
|
38
|
+
name: dist
|
|
39
|
+
path: dist/
|
|
40
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
41
|
+
with:
|
|
42
|
+
attestations: true
|
|
43
|
+
|
|
44
|
+
github-release:
|
|
45
|
+
needs: build
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
permissions:
|
|
48
|
+
contents: write
|
|
49
|
+
id-token: write
|
|
50
|
+
steps:
|
|
51
|
+
- uses: actions/checkout@v7
|
|
52
|
+
- uses: actions/download-artifact@v8
|
|
53
|
+
with:
|
|
54
|
+
name: dist
|
|
55
|
+
path: dist/
|
|
56
|
+
- name: Sign with Sigstore
|
|
57
|
+
uses: sigstore/gh-action-sigstore-python@v3.5.0
|
|
58
|
+
with:
|
|
59
|
+
inputs: ./dist/*.tar.gz ./dist/*.whl
|
|
60
|
+
- name: Create release
|
|
61
|
+
env:
|
|
62
|
+
GH_TOKEN: ${{ github.token }}
|
|
63
|
+
run: |
|
|
64
|
+
notes=$(awk "/^## \\[${GITHUB_REF_NAME#v}\\]/{f=1;next} /^## \\[/{f=0} f" CHANGELOG.md)
|
|
65
|
+
gh release create "$GITHUB_REF_NAME" dist/* --title "$GITHUB_REF_NAME" --notes "$notes"
|
|
66
|
+
|
|
67
|
+
docker:
|
|
68
|
+
needs: build
|
|
69
|
+
runs-on: ubuntu-latest
|
|
70
|
+
permissions:
|
|
71
|
+
contents: read
|
|
72
|
+
packages: write
|
|
73
|
+
id-token: write
|
|
74
|
+
steps:
|
|
75
|
+
- uses: actions/checkout@v7
|
|
76
|
+
- uses: docker/setup-buildx-action@v4
|
|
77
|
+
- uses: docker/login-action@v4
|
|
78
|
+
with:
|
|
79
|
+
registry: ghcr.io
|
|
80
|
+
username: ${{ github.actor }}
|
|
81
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
82
|
+
- uses: docker/metadata-action@v6
|
|
83
|
+
id: meta
|
|
84
|
+
with:
|
|
85
|
+
images: ghcr.io/${{ github.repository }}
|
|
86
|
+
tags: |
|
|
87
|
+
type=semver,pattern={{version}}
|
|
88
|
+
type=semver,pattern={{major}}.{{minor}}
|
|
89
|
+
- uses: docker/build-push-action@v7
|
|
90
|
+
id: push
|
|
91
|
+
with:
|
|
92
|
+
push: true
|
|
93
|
+
tags: ${{ steps.meta.outputs.tags }}
|
|
94
|
+
labels: ${{ steps.meta.outputs.labels }}
|
|
95
|
+
provenance: true
|
|
96
|
+
sbom: true
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# pip install pre-commit && pre-commit install
|
|
2
|
+
repos:
|
|
3
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
4
|
+
rev: v5.0.0
|
|
5
|
+
hooks:
|
|
6
|
+
- id: check-toml
|
|
7
|
+
- id: check-yaml
|
|
8
|
+
- id: end-of-file-fixer
|
|
9
|
+
- id: trailing-whitespace
|
|
10
|
+
- id: check-merge-conflict
|
|
11
|
+
- id: detect-private-key
|
|
12
|
+
exclude: ^tests/
|
|
13
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
14
|
+
rev: v0.16.10
|
|
15
|
+
hooks:
|
|
16
|
+
- id: ruff-check
|
|
17
|
+
args: [--fix]
|
|
18
|
+
- id: ruff-format
|
|
19
|
+
- repo: local
|
|
20
|
+
hooks:
|
|
21
|
+
- id: mypy
|
|
22
|
+
name: mypy
|
|
23
|
+
entry: uv run mypy
|
|
24
|
+
language: system
|
|
25
|
+
pass_filenames: false
|
|
26
|
+
types: [python]
|