Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions .agents/update-openapi-changelog/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
name: update-openapi-changelog
description: Generates accurate changelog bullets for Meraki OpenAPI spec updates by analyzing the generated code diff, then writes them into CHANGELOG.md. Use when reviewing or processing an OpenAPI update PR, when asked to fill in changelog bullets for a spec bump, or when CHANGELOG.md contains a TODO placeholder from an automated OpenAPI update.
---

# Update OpenAPI Changelog

Use this skill when CHANGELOG.md has a TODO placeholder from an automated OpenAPI version bump, or when you need to write changelog bullets for a generated SDK update.

## Workflow

### 1. Identify versions

```bash
# New version (already written by the update workflow)
cat .api-version

# Old version (from the previous commit)
git show HEAD~1:.api-version 2>/dev/null || git log --oneline | head -5
```

### 2. Collect the generated diff

Limit the diff to generated output only — this keeps the context focused:

```bash
git diff HEAD~1 -- meraki_client/ tests/generated/ docs/api_reference/ ':(exclude)meraki_client/aio/'
```

`meraki_client/aio/` mirrors `meraki_client/_api/` exactly, so excluding it avoids duplicate noise.

If the diff is very large (> ~500 lines), summarize it by focusing on:

- New/deleted files (new or removed endpoint modules)
- Added/removed function signatures
- Added/removed parameters and response fields

### 3. Generate bullets

Use the following prompt exactly. Fill in `old_api_version`, `new_api_version`, and `generated_diff` from the steps above.

```
[system]
You write concise, accurate changelog bullets for a generated Python SDK.
Never invent changes that are not supported by the provided diff context.

[user]
We are updating Meraki OpenAPI from v{{old_api_version}} to v{{new_api_version}}.

Generated code diff context:
{{generated_diff}}

Draft changelog bullets for:
#### Update to Meraki API v{{new_api_version}}

Requirements:
- Return ONLY markdown bullet lines that begin with "- ".
- Return 3-8 bullets.
- Focus on user-visible SDK changes from generated code.
- Prioritize:
- added or removed endpoints
- added or removed request parameters
- added or removed response fields
- removed modules
- Use operation IDs or snake_case names exactly as shown in the diff.
- If unsure, omit the item.
- No headings, no prose, no code fences.
```

### 4. Apply bullets to CHANGELOG.md

Edit `CHANGELOG.md`. Place the bullets under `### Changed` in the `## Unreleased` section:

```markdown
### Changed

#### Update to Meraki API v<new_api_version>

- <bullet 1>
- <bullet 2>
```

## Quality bar

- Do not describe internal codegen machinery — only user-visible SDK surface changes.
- If the diff shows no meaningful user-visible changes, write a single bullet: `- No user-visible SDK changes in this spec update.`
2 changes: 1 addition & 1 deletion .api-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.67.0
1.68.0
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

-
### Changed

#### Update to Meraki API v1.68.0

- Added `connect_network_appliance_umbrella_account` and `disconnect_network_appliance_umbrella_account` endpoints to connect/disconnect a Cisco Umbrella account from a network.
- Added `get_organization_integrations_deployable` and `get_organization_integrations_deployed` endpoints to list available and active integrations for an organization.
- Added `get_organization_wireless_devices_provisioning_deployments`, `create_organization_wireless_devices_provisioning_deployment`, `update_organization_wireless_devices_provisioning_deployments`, and `delete_organization_wireless_devices_provisioning_deployment` endpoints for zero touch wireless AP provisioning deployments.
- Camera endpoints `get_device_camera_quality_and_retention`, `update_device_camera_quality_and_retention`, `get_device_camera_sense`, `update_device_camera_sense`, `get_device_camera_video_link`, `get_device_camera_wireless_profiles`, `update_device_camera_wireless_profiles`, and `update_organization_camera_onboarding_statuses` now return typed response schemas instead of `DictResponse`.
- Added `ecmpUplinkConfigs` field to appliance VPN peer responses (`get_network_appliance_vpn_bgp`, `update_network_appliance_vpn_bgp`).
- Added `vrf`, `vrfType`, and `ipVersion` fields to device multicast routing response.
- Added `model` field to network clients response; added `open-enhanced-with-radius` as a valid SSID `auth_mode` value.

## v0.10.3

Expand Down
2 changes: 1 addition & 1 deletion meraki_client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"types",
]
__version__ = "0.10.3"
__api_version__ = "v1.67.0"
__api_version__ = "v1.68.0"


class MerakiClient:
Expand Down
94 changes: 91 additions & 3 deletions meraki_client/_api/appliance.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from meraki_client.schemas import (
BulkOrganizationApplianceDnsLocalProfilesAssignmentsCreateItemsItem,
BulkOrganizationApplianceDnsLocalProfilesAssignmentsCreateResponse,
ConnectNetworkApplianceUmbrellaAccountApi,
ConnectNetworkApplianceUmbrellaAccountResponse,
CreateDeviceApplianceVmxAuthenticationTokenResponse,
CreateNetworkAppliancePrefixesDelegatedStaticOrigin,
CreateNetworkApplianceRfProfileFiveGhzSettings,
Expand Down Expand Up @@ -2286,7 +2288,7 @@ def update_network_appliance_firewall_settings(
def get_network_appliance_ports(
self, network_id: str
) -> PaginatedResponse[GetNetworkAppliancePortsResponseItem]:
"""List per-port VLAN settings for all ports of a MX.
"""List per-port VLAN settings for all ports of a secure router or security appliance.

[API documentation: getNetworkAppliancePorts](https://developer.cisco.com/meraki/api-v1/#!get-network-appliance-ports)

Expand Down Expand Up @@ -2330,7 +2332,7 @@ def get_network_appliance_ports(
def get_network_appliance_port(
self, *, network_id: str, port_id: str
) -> GetNetworkAppliancePortResponse:
"""Return per-port VLAN settings for a single MX port.
"""Return per-port VLAN settings for a single secure router or security appliance port.

[API documentation: getNetworkAppliancePort](https://developer.cisco.com/meraki/api-v1/#!get-network-appliance-port)

Expand Down Expand Up @@ -2378,7 +2380,7 @@ def update_network_appliance_port(
allowed_vlans: str | None = None,
access_policy: str | None = None,
) -> UpdateNetworkAppliancePortResponse:
"""Update the per-port VLAN settings for a single MX port.
"""Update the per-port VLAN settings for a single secure router or security appliance port.

[API documentation: updateNetworkAppliancePort](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-port)

Expand Down Expand Up @@ -5019,6 +5021,66 @@ def update_network_appliance_traffic_shaping_vpn_exclusions(
response_schema=UpdateNetworkApplianceTrafficShapingVpnExclusionsResponse,
)

def connect_network_appliance_umbrella_account(
self, *, network_id: str, api: ConnectNetworkApplianceUmbrellaAccountApi
) -> ConnectNetworkApplianceUmbrellaAccountResponse:
"""Connect a Cisco Umbrella account to this network.

[API documentation: connectNetworkApplianceUmbrellaAccount](https://developer.cisco.com/meraki/api-v1/#!connect-network-appliance-umbrella-account)

Args:
network_id: Network ID.
api: Umbrella API credentials.

Returns:
Successful operation.

Example API response:
```json
{
"umbrella": {
"organization": {
"id": "8769012"
}
}
}
```

"""
network_id = urllib.parse.quote(str(network_id), safe="")
path = f"/networks/{network_id}/appliance/umbrella/account/connect"

payload: dict[str, Any] = {}
if api is not None:
payload["api"] = api.model_dump(by_alias=True, exclude_none=True)

return self._session.post(
scope="appliance",
operation_id="connectNetworkApplianceUmbrellaAccount",
path=path,
json=payload,
response_schema=ConnectNetworkApplianceUmbrellaAccountResponse,
)

def disconnect_network_appliance_umbrella_account(self, network_id: str) -> None:
"""Disconnect Umbrella account from this network.

[API documentation: disconnectNetworkApplianceUmbrellaAccount](https://developer.cisco.com/meraki/api-v1/#!disconnect-network-appliance-umbrella-account)

Args:
network_id: Network ID.

Returns:
Successful operation.

"""
network_id = urllib.parse.quote(str(network_id), safe="")
path = f"/networks/{network_id}/appliance/umbrella/account/disconnect"

return self._session.post(
scope="appliance", operation_id="disconnectNetworkApplianceUmbrellaAccount", path=path
)

def get_network_appliance_uplinks_usage_history(
self,
network_id: str,
Expand Down Expand Up @@ -8072,6 +8134,19 @@ def get_organization_appliance_vpn_third_party_vpn_peers(
"multiExitDiscriminator": 1,
"weight": 10
},
"ecmpUplinkConfigs": [
{
"id": "7890",
"wan": "WAN 1",
"privateSubnets": [
"169.254.10.0/30"
],
"ebgpNeighbor": {
"neighborIp": "169.254.10.2",
"sourceIp": "169.254.10.1"
}
}
],
"priorityInGroup": 1,
"group": {
"number": 1,
Expand Down Expand Up @@ -8189,6 +8264,19 @@ def update_organization_appliance_vpn_third_party_vpn_peers(
"multiExitDiscriminator": 1,
"weight": 10
},
"ecmpUplinkConfigs": [
{
"id": "7890",
"wan": "WAN 1",
"privateSubnets": [
"169.254.10.0/30"
],
"ebgpNeighbor": {
"neighborIp": "169.254.10.2",
"sourceIp": "169.254.10.1"
}
}
],
"priorityInGroup": 1,
"group": {
"number": 1,
Expand Down
47 changes: 46 additions & 1 deletion meraki_client/_api/batch/appliance.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from meraki_client.schemas import (
BulkOrganizationApplianceDnsLocalProfilesAssignmentsCreateItemsItem,
ConnectNetworkApplianceUmbrellaAccountApi,
CreateNetworkAppliancePrefixesDelegatedStaticOrigin,
CreateNetworkApplianceRfProfileFiveGhzSettings,
CreateNetworkApplianceRfProfilePerSsidSettings,
Expand Down Expand Up @@ -269,7 +270,7 @@ def update_network_appliance_port(
allowed_vlans: str | None = None,
access_policy: str | None = None,
) -> CreateOrganizationActionBatchActionsItem:
"""Update the per-port VLAN settings for a single MX port.
"""Update the per-port VLAN settings for a single secure router or security appliance port.

[API documentation: updateNetworkAppliancePort](https://developer.cisco.com/meraki/api-v1/#!update-network-appliance-port)

Expand Down Expand Up @@ -1003,6 +1004,50 @@ def update_network_appliance_traffic_shaping_vpn_exclusions(
body=payload,
)

def connect_network_appliance_umbrella_account(
self, *, network_id: str, api: ConnectNetworkApplianceUmbrellaAccountApi
) -> CreateOrganizationActionBatchActionsItem:
"""Connect a Cisco Umbrella account to this network.

[API documentation: connectNetworkApplianceUmbrellaAccount](https://developer.cisco.com/meraki/api-v1/#!connect-network-appliance-umbrella-account)

Args:
network_id: Network ID.
api: Umbrella API credentials.

"""
network_id = urllib.parse.quote(str(network_id), safe="")
path = f"/networks/{network_id}/appliance/umbrella/account/connect"

payload: dict[str, Any] = {}
if api is not None:
payload["api"] = api.model_dump(by_alias=True, exclude_none=True)

return CreateOrganizationActionBatchActionsItem(
resource=path,
operation="action",
body=payload,
)

def disconnect_network_appliance_umbrella_account(
self, network_id: str
) -> CreateOrganizationActionBatchActionsItem:
"""Disconnect Umbrella account from this network.

[API documentation: disconnectNetworkApplianceUmbrellaAccount](https://developer.cisco.com/meraki/api-v1/#!disconnect-network-appliance-umbrella-account)

Args:
network_id: Network ID.

"""
network_id = urllib.parse.quote(str(network_id), safe="")
path = f"/networks/{network_id}/appliance/umbrella/account/disconnect"

return CreateOrganizationActionBatchActionsItem(
resource=path,
operation="disconnect",
)

def create_network_appliance_vlan(
self,
*,
Expand Down
Loading