diff --git a/.github/actions/run-appinspect/action.yml b/.github/actions/run-appinspect/action.yml index 51147a6cd..15f7c052b 100644 --- a/.github/actions/run-appinspect/action.yml +++ b/.github/actions/run-appinspect/action.yml @@ -1,28 +1,22 @@ name: Run Splunk AppInspect description: Package a mock app containing the SDK and its dependencies, then validate it with AppInspect. -inputs: - mock-app-path: - description: Path to app packaged for scanning with AppInspect - required: true - default: ./tests/system/test_apps/generating_app - runs: using: composite steps: - name: Install AppInspect dependencies shell: bash run: sudo apt-get install -y libmagic1 - - name: Install the SDK and its dependencies into the mock app + - name: Install the SDK and its dependencies into a mock app shell: bash run: | - mkdir -p ${{ inputs.mock-app-path }}/bin/lib - uv pip install ".[openai, anthropic, google]" --target ${{ inputs.mock-app-path }}/bin/lib + mkdir -p ./tests/system/test_apps/generating_app/bin/lib + uv pip install ".[openai, anthropic, google]" --target ./tests/system/test_apps/generating_app/bin/lib - name: Package the mock app shell: bash run: | - cd ${{ inputs.mock-app-path }} + cd ./tests/system/test_apps/generating_app tar -czf mock_app.tgz --exclude="__pycache__" bin default metadata - name: Validate the mock app with AppInspect shell: bash - run: uvx splunk-appinspect inspect ${{ inputs.mock-app-path }}/mock_app.tgz --included-tags cloud + run: uvx splunk-appinspect inspect ./tests/system/test_apps/generating_app/mock_app.tgz --included-tags cloud diff --git a/.github/actions/setup-sdk-environment/action.yml b/.github/actions/setup-sdk-environment/action.yml index 04c7c1ba9..30d8df447 100644 --- a/.github/actions/setup-sdk-environment/action.yml +++ b/.github/actions/setup-sdk-environment/action.yml @@ -2,10 +2,6 @@ name: Set up SDK environment description: Perform all the shared setup steps inputs: - python-version: - description: Python version used for this run - required: true - default: "3.13" deps-group: description: Dependency groups passed to `uv sync --group` required: true @@ -17,7 +13,7 @@ runs: - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 with: version: 0.11.6 - python-version: ${{ inputs.python-version }} + python-version: 3.13 activate-environment: true enable-cache: true cache-python: true @@ -25,4 +21,4 @@ runs: env: SDK_DEPS_GROUP: ${{ inputs.deps-group }} shell: bash - run: SDK_DEPS_GROUP="${{ inputs.deps-group }}" make ci-install + run: make ci-install diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index bcae6e510..c3e7cb1dc 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -8,6 +8,8 @@ updates: groups: github-actions: patterns: ["*"] + cooldown: + default-days: 7 - package-ecosystem: "uv" directory: "/" schedule: @@ -15,3 +17,5 @@ updates: groups: python-uv-lock: patterns: ["*"] + cooldown: + default-days: 7 diff --git a/.github/workflows/appinspect.yml b/.github/workflows/appinspect.yml index 44a1c6c5f..e65b69284 100644 --- a/.github/workflows/appinspect.yml +++ b/.github/workflows/appinspect.yml @@ -5,11 +5,18 @@ on: pull_request: workflow_dispatch: +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: {} + env: PYTHON_VERSION: 3.13 jobs: appinspect: + name: Run AppInspect runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index f1b18bc85..f510f93dc 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -1,4 +1,4 @@ -name: Python CD +name: Python SDK CD on: push: branches: [develop] @@ -6,11 +6,18 @@ on: types: [published] workflow_dispatch: +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: false + +permissions: {} + env: DIST_DIR: dist/ jobs: build-distributables: + name: Build release distributables # Why building is separate from publishing: # https://github.com/pypa/gh-action-pypi-publish/issues/217#issuecomment-1965727093 runs-on: ubuntu-latest @@ -26,15 +33,17 @@ jobs: deps-group: release - name: Set pre-release version if: startsWith(github.ref, 'refs/tags/') != true + env: + RUN_NUMBER: ${{ github.run_number }} run: | VERSION_BASE="$(uv version --short)" - RUN_NUMBER="${{ github.run_number }}" uv version "${VERSION_BASE}.dev${RUN_NUMBER}" - name: Set release version if: startsWith(github.ref, 'refs/tags/') == true + env: + VERSION_TAG: ${{ github.event.release.tag_name }} run: | - VERSION_TAG="${{ github.event.release.tag_name }}" - [[ $VERSION_TAG != $(uv version --short) ]] && { + [[ ${VERSION_TAG} != $(uv version --short) ]] && { printf "Git tag should be identical to version field in pyproject.toml" exit 1 } @@ -60,11 +69,12 @@ jobs: path: docs/_build/html publish-pre-release: + name: Publish pre-release to Test PyPI if: startsWith(github.ref, 'refs/tags/') == false needs: build-distributables runs-on: ubuntu-latest permissions: - id-token: write + id-token: write # Required for OIDC-based trusted publishing to PyPI environment: name: splunk-test-pypi url: https://test.pypi.org/project/splunk-sdk/ @@ -80,11 +90,12 @@ jobs: repository-url: https://test.pypi.org/legacy/ publish-release: + name: Publish release to PyPI if: startsWith(github.ref, 'refs/tags/') == true needs: build-distributables runs-on: ubuntu-latest permissions: - id-token: write + id-token: write # Required for OIDC-based trusted publishing to PyPI environment: name: splunk-pypi url: https://pypi.org/project/splunk-sdk/ diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index f9d0b1542..93e88dbf8 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -5,8 +5,15 @@ on: pull_request: workflow_dispatch: +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: {} + jobs: lint: + name: Run linters runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 162d1910c..8f23ebd47 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,8 +9,11 @@ concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true +permissions: {} + jobs: test: + name: Run test suite runs-on: ubuntu-latest strategy: matrix: @@ -30,7 +33,9 @@ jobs: SPLUNKBASE_PASSWORD: ${{ secrets.SPLUNKBASE_PASSWORD }} run: uv run ./scripts/download_splunk_mcp_server_app.py - name: Launch Splunk Docker instance - run: SPLUNK_VERSION=${{ matrix.splunk-version }} docker compose up -d + env: + SPLUNK_VERSION: ${{ matrix.splunk-version }} + run: docker compose up -d - name: Set up .env run: cp .env.template .env - name: Write internal AI secrets to .env @@ -51,10 +56,8 @@ jobs: uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae with: path: .pytest_cache - key: pytest-cache-${{ runner.os }}-py${{ matrix.python-version }}-${{ github.ref_name }}-${{ - github.sha }} - restore-keys: | - pytest-cache-${{ runner.os }}-py${{ matrix.python-version }}-${{ github.ref_name }}- + key: pytest-cache-${{ runner.os }}-py${{ matrix.python-version }}-${{ github.ref_name }}-${{ github.sha }} + restore-keys: pytest-cache-${{ runner.os }}-py${{ matrix.python-version }}-${{ github.ref_name }}- - name: Run unit tests run: make test-unit - name: Run integration/system tests diff --git a/.gitignore b/.gitignore index c86b11f00..856716ff3 100644 --- a/.gitignore +++ b/.gitignore @@ -279,6 +279,7 @@ $RECYCLE.BIN/ .vscode/ docs/_build/ +.claude/ !*.conf.spec **/metadata/local.meta diff --git a/Makefile b/Makefile index e62aa91de..fd145d5e6 100644 --- a/Makefile +++ b/Makefile @@ -2,9 +2,13 @@ ## VIRTUALENV MANAGEMENT -# https://docs.astral.sh/uv/reference/cli/#uv-run--upgrade +# https://docs.astral.sh/uv/reference/cli/#uv-sync # --no-config skips Splunk's internal PyPI mirror UV_SYNC_CMD := uv sync --no-config +# https://docs.astral.sh/uv/reference/cli/#uv-run +UV_RUN_CMD := uv run +# https://docs.zizmor.sh/usage +ZIZMOR_CMD := $(UV_RUN_CMD) zizmor --pedantic --strict-collection .PHONY: install install: @@ -20,9 +24,12 @@ upgrade: ci-install: $(UV_SYNC_CMD) --frozen --group $(SDK_DEPS_GROUP) -UV_RUN_CMD := uv run .PHONY: lint -lint: lint-python # TODO: Add mbake +lint: lint-python lint-gh-actions # TODO: Add mbake + +.PHONY: lint-gh-actions +lint-gh-actions: + $(ZIZMOR_CMD) ./.github .PHONY: lint-python lint-python: @@ -31,7 +38,11 @@ lint-python: $(UV_RUN_CMD) basedpyright .PHONY: ci-lint -ci-lint: ci-lint-python # TODO: Add mbake +ci-lint: ci-lint-python ci-lint-gh-actions # TODO: Add mbake + +.PHONY: ci-lint-gh-actions +ci-lint-gh-actions: + $(ZIZMOR_CMD) ./.github .PHONY: ci-lint-python ci-lint-python: diff --git a/pyproject.toml b/pyproject.toml index fcf5a3731..021d5b895 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,7 +53,12 @@ test = [ "vcrpy>=8.1.1", ] release = ["build>=1.5.0", "jinja2>=3.1.6", "sphinx>=9.1.0", "twine>=6.2.0"] -lint = ["basedpyright>=1.39.4", "ruff>=0.15.12", "mbake>=1.4.6"] +lint = [ + "basedpyright>=1.39.4", + "ruff>=0.15.12", + "mbake>=1.4.6", + "zizmor==1.25.2", +] dev = [ "rich>=15.0.0", { include-group = "test" }, diff --git a/uv.lock b/uv.lock index 57c885951..e6c527804 100644 --- a/uv.lock +++ b/uv.lock @@ -1829,11 +1829,13 @@ dev = [ { name = "splunk-sdk", extra = ["anthropic", "google", "openai"] }, { name = "twine" }, { name = "vcrpy" }, + { name = "zizmor" }, ] lint = [ { name = "basedpyright" }, { name = "mbake" }, { name = "ruff" }, + { name = "zizmor" }, ] release = [ { name = "build" }, @@ -1883,11 +1885,13 @@ dev = [ { name = "splunk-sdk", extras = ["openai", "anthropic", "google"], specifier = ">=3.0.0" }, { name = "twine", specifier = ">=6.2.0" }, { name = "vcrpy", specifier = ">=8.1.1" }, + { name = "zizmor", specifier = "==1.25.2" }, ] lint = [ { name = "basedpyright", specifier = ">=1.39.4" }, { name = "mbake", specifier = ">=1.4.6" }, { name = "ruff", specifier = ">=0.15.12" }, + { name = "zizmor", specifier = "==1.25.2" }, ] release = [ { name = "build", specifier = ">=1.5.0" }, @@ -2328,6 +2332,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/74/35/698e7e3ff38e22992ea24870a511d8762474fb6783627a2910ff22a185c2/xxhash-3.7.0-cp314-cp314t-win_arm64.whl", hash = "sha256:468f0fc114faaa4b36699f8e328bbc3bb11dc418ba94ac52c26dd736d4b6c637", size = 28807, upload-time = "2026-04-25T11:09:11.234Z" }, ] +[[package]] +name = "zizmor" +version = "1.25.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b3/41/8987d546e3101cc76748b2f1b0ccda58e244773ef5124d39e7e749e3d6e4/zizmor-1.25.2.tar.gz", hash = "sha256:f26ffeb16659c8922c7b08203ca5a4f8bf5e1a7e8d190734961c40877cf778ea", size = 517794, upload-time = "2026-05-16T06:28:43.816Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/bd/84108a92ccbfda0d28efc11f382997c7a767b58863bf4a550634b8cf0211/zizmor-1.25.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:17cc8cfd9d472e8b11945a869c198d25cfdf4a33f36fa7a1f9674099f5fb509d", size = 9115548, upload-time = "2026-05-16T06:28:33.591Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c0/66453a2553a66286a96ca32d75e3e6bcc94ce7f907cd5f8c2c3fce55315e/zizmor-1.25.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d3e301eb4465e2da77857cf01ab4ef0184cf3818e826800b270ab01ae7338977", size = 8665071, upload-time = "2026-05-16T06:28:30.861Z" }, + { url = "https://files.pythonhosted.org/packages/52/3e/d60939d1cc4907c0d021a7c46362aab5e8045550bb09157d56c070e43568/zizmor-1.25.2-py3-none-manylinux_2_24_aarch64.whl", hash = "sha256:cf64374149b567c9373228b76c8e77a389b4071899f84b82c36ee50fab894e79", size = 8842884, upload-time = "2026-05-16T06:28:26.041Z" }, + { url = "https://files.pythonhosted.org/packages/46/82/f3e8d9b6d941194f2558591b449c106d46a16ea566b95eccff3a83bf6acc/zizmor-1.25.2-py3-none-manylinux_2_28_armv7l.whl", hash = "sha256:0beba1601be08bd00c9277e6ed4b026e125b26b379d86d6d98eb708409b3050d", size = 8449741, upload-time = "2026-05-16T06:28:45.424Z" }, + { url = "https://files.pythonhosted.org/packages/4b/13/445bc98acc2c976d6b8f8ca59b9c09f055adb5ffb3445d99af8ff7efcb4f/zizmor-1.25.2-py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:c4246f1344d8dbeffc044d7bb11b131773a7db7eb57d9073c45942dfd3543a1f", size = 9285184, upload-time = "2026-05-16T06:28:39.21Z" }, + { url = "https://files.pythonhosted.org/packages/cf/78/fc7717c706bde7531b2fde12003994fbc04c47ab4f91aa6ca9b3b24b30fd/zizmor-1.25.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:dbb1b5c85b8de8eaa0227c6620f06c8e4fbd0a4da2086e218bc225c0bef0923d", size = 8886579, upload-time = "2026-05-16T06:28:51.384Z" }, + { url = "https://files.pythonhosted.org/packages/ca/bc/a46f11377cdc145c625d62d88c30fead56f9d29bc31652069a1a0eaed6c2/zizmor-1.25.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d670a1e2f00b3cd56febd145bc1a0b2c4caf1cbe5dad8128721843fa877e2d2e", size = 8413576, upload-time = "2026-05-16T06:28:36.376Z" }, + { url = "https://files.pythonhosted.org/packages/2b/3b/0fd93b77171c8f229e8e1304eecc9931bf3009f722c57967d545d9f151b6/zizmor-1.25.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b75c84d7387389f95edadbe859fb2aaf0a360c5b080932cc53e92ae1db6f09ef", size = 9378162, upload-time = "2026-05-16T06:28:41.999Z" }, + { url = "https://files.pythonhosted.org/packages/b5/3f/dcb85fb9a0d87794847f9043f9db9bb4d274cf4b8077604bc13850c8fdb4/zizmor-1.25.2-py3-none-win32.whl", hash = "sha256:aa9f4c43b499c55339c3ef2e885133c5017cd9a18d76d9335541203cfa5ae1e7", size = 7548509, upload-time = "2026-05-16T06:28:28.828Z" }, + { url = "https://files.pythonhosted.org/packages/d2/81/1cb088098bd53f9b910098b0c19d06dc587acf328a170ef8afd1cd93b482/zizmor-1.25.2-py3-none-win_amd64.whl", hash = "sha256:af55bd9bd119ea8cbce2a7addc3922503019de32c1fe31106d70b3dc77d77908", size = 8609822, upload-time = "2026-05-16T06:28:48.078Z" }, +] + [[package]] name = "zstandard" version = "0.25.0"