Skip to content
Open
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
06f5f1e
Add stub code
Oct 27, 2025
74a3d0f
Fix parsing
Oct 29, 2025
b80cda8
Fix parsing
Oct 29, 2025
add68de
Fix displaying
Oct 29, 2025
1f12482
Merge remote-tracking branch 'other-repo/henrydai/ImplementCRUDforCha…
Oct 30, 2025
aeb58e6
Fix commands
Oct 30, 2025
1636d5d
Add tests
Oct 30, 2025
b9696af
Merge remote-tracking branch 'other-repo/henrydai/ImplementCRUDforCha…
Oct 30, 2025
b26a3b2
Fix style
Oct 30, 2025
1a9b886
Merge remote-tracking branch 'other-repo/henrydai/ImplementCRUDforCha…
Oct 30, 2025
ea95cc0
Rename cli extension module name
Nov 3, 2025
6e4bdaa
Merge remote-tracking branch 'other-repo/henrydai/ImplementCRUDforCha…
Nov 3, 2025
bdeffae
Fix linter
Nov 3, 2025
c50dfe8
Merge remote-tracking branch 'other-repo/henrydai/ImplementCRUDforCha…
Nov 3, 2025
78286dd
Fix linter
Nov 3, 2025
421d339
Merge remote-tracking branch 'other-repo/henrydai/ImplementCRUDforCha…
Nov 3, 2025
56b725b
Fix linter
Nov 3, 2025
d03e382
Merge remote-tracking branch 'other-repo/henrydai/ImplementCRUDforCha…
Nov 3, 2025
964371c
Fix module name
Nov 3, 2025
34d2514
Merge remote-tracking branch 'other-repo/henrydai/ImplementCRUDforCha…
Nov 3, 2025
3f5b4d7
add test scenarios
Nov 4, 2025
f0d9bdc
Merge remote-tracking branch 'other-repo/henrydai/ImplementCRUDforCha…
Nov 4, 2025
1578369
Fix style
Nov 4, 2025
7274b10
Merge remote-tracking branch 'other-repo/henrydai/ImplementCRUDforCha…
Nov 4, 2025
6c8d92c
Add service name
Nov 4, 2025
ee776c6
Add stageprogression and stagemap
Nov 25, 2025
aa3b9bd
Merge remote-tracking branch 'other-repo/henrydai/ImplementCRUDforCha…
Dec 4, 2025
8dd8743
Update alias
Dec 11, 2025
d02017a
Update ChangeRecord name
Dec 11, 2025
871d9b4
Merge remote-tracking branch 'other-repo/henrydai/ImplementCRUDforCha…
Dec 11, 2025
bf2565b
Address comments
Dec 19, 2025
e52f0b2
Merge remote-tracking branch 'other-repo/henrydai/ImplementCRUDforCha…
Dec 19, 2025
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
8 changes: 8 additions & 0 deletions src/azure-changesafety/HISTORY.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.. :changelog:

Release History
===============

1.0.0b1
++++++
* Initial release.
49 changes: 49 additions & 0 deletions src/azure-changesafety/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Azure CLI Change Safety Extension
Azure CLI extension for managing Change Safety `ChangeState` resources used to coordinate operational changes across Azure targets.

## Installation
```bash
az extension add --source <path-to-extension-dist> --yes
# or install the latest published build
az extension add --name azure-changesafety
```

## Commands
```bash
az changesafety changerecord create # Create a ChangeState definition for one or more targets.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please fix renaming of ChangeState to ChangeRecord everywhere

az changesafety changerecord update # Update metadata, rollout configuration, or target definitions.
az changesafety changerecord delete # Delete a ChangeState resource.
az changesafety changerecord show # Display details for a ChangeState resource.
```

Run `az changesafety changerecord -h` to see full parameter details and examples.

## Examples
Create a ChangeState describing a web app rollout:
```bash

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AppDeployment example without a stagemap seems odd. Please use examples of the known user scenarios that we understand very well.

az changesafety changerecord create \
-g MyResourceGroup \
-n changerecord-webapp-rollout \
--change-type AppDeployment \
--rollout-type Normal \
--targets "resourceId=/subscriptions/<subId>/resourceGroups/MyResourceGroup/providers/Microsoft.Web/sites/myApp,operation=create" \
--links name=Runbook uri=https://contoso.com/runbook
```

Update the rollout type and add a comment:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a common scenario or an example we have discussed where the user can update RolloutType. Please use common usage patterns that our existing scenarios require. For example, I would have expected to see the manual touch example as the first one.

```bash
az changesafety changerecord update \
-g MyResourceGroup \
-n changerecord-webapp-rollout \
--rollout-type Emergency \
--comments "Escalated due to customer impact"
```

Delete a ChangeState:
```bash
az changesafety changerecord delete -g MyResourceGroup -n changerecord-webapp-rollout --yes

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the user does not specify the resourcegroup, what would be the default scope?

```

## Additional Information
- View command documentation: `az changesafety changerecord -h`
- Remove the extension when no longer needed: `az extension remove --name azure-changesafety`
42 changes: 42 additions & 0 deletions src/azure-changesafety/azext_changesafety/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
#
# Code generated by aaz-dev-tools
# --------------------------------------------------------------------------------------------

from azure.cli.core import AzCommandsLoader
from azext_changesafety._help import helps # pylint: disable=unused-import


class ChangeStateCommandsLoader(AzCommandsLoader):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this auto generated from swagger? Can we use ChangeRecord in the code?


def __init__(self, cli_ctx=None):
from azure.cli.core.commands import CliCommandType
custom_command_type = CliCommandType(
operations_tmpl='azext_changesafety.custom#{}')
super().__init__(cli_ctx=cli_ctx,
custom_command_type=custom_command_type)

def load_command_table(self, args):
from azext_changesafety.commands import load_command_table
from azure.cli.core.aaz import load_aaz_command_table
try:
from . import aaz
except ImportError:
aaz = None
if aaz:
load_aaz_command_table(
loader=self,
aaz_pkg_name=aaz.__name__,
args=args
)
load_command_table(self, args)
return self.command_table

def load_arguments(self, command):
from azext_changesafety._params import load_arguments
load_arguments(self, command)


COMMAND_LOADER_CLS = ChangeStateCommandsLoader
117 changes: 117 additions & 0 deletions src/azure-changesafety/azext_changesafety/_help.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
#
# Code generated by aaz-dev-tools
# --------------------------------------------------------------------------------------------

# pylint: disable=line-too-long
# pylint: disable=too-many-lines

from knack.help_files import helps # pylint: disable=unused-import

helps['changesafety'] = """
type: group
short-summary: Manage Change Safety resources.
"""

helps['changesafety changerecord'] = """
type: group
short-summary: Manage ChangeState resources that describe planned changes across targets.
"""

helps['changesafety changerecord create'] = """
type: command
short-summary: Create a ChangeState resource.
long-summary: >
Provide at least one target definition to describe which resources or operations the ChangeState
will affect. Targets are expressed as comma or semicolon separated key=value pairs such as
resourceId=RESOURCE_ID,operation=DELETE. The command is also available through the alias

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is capitalization necessary?

`az changesafety changerecord`. If you omit scheduling flags, the anticipated start time defaults
to now and the anticipated end time defaults to eight hours later (UTC).
parameters:
- name: --targets
short-summary: >
One or more target definitions expressed as key=value pairs (for example
resourceId=RESOURCE_ID,operation=CREATE,resourceType=Microsoft.Compute/virtualMachines).
- name: --anticipated-start-time
short-summary: Expected start time in ISO 8601 format. Defaults to current UTC time when omitted.
- name: --anticipated-end-time
short-summary: Expected completion time in ISO 8601 format. Defaults to eight hours after the anticipated start time when omitted.
- name: --change-type
short-summary: Classify the change such as AppDeployment, Config, ManualTouch, or PolicyDeployment.
- name: --rollout-type
short-summary: Specify the rollout urgency (Normal, Hotfix, or Emergency).
- name: --stage-map-name --stagemap-name
short-summary: StageMap name in the current subscription scope; the resource ID is built for you.
- name: --stage-map
short-summary: Reference an existing StageMap resource using resource-id=RESOURCE_ID and optional parameters key=value pairs.
- name: --links
short-summary: Add supporting links by repeating --links name=NAME uri=URL [description=TEXT].
examples:
- name: Create with StageMap reference and status link
text: |-
az changesafety changerecord create -g MyResourceGroup -n changerecord002 --change-type ManualTouch --rollout-type Normal --stage-map "{resource-id:/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MyResourceGroup/providers/Microsoft.ChangeSafety/stageMaps/rolloutStageMap}" --targets "resourceId=/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MyResourceGroup/providers/Microsoft.Compute/virtualMachines/myVm,operation=PATCH" --links "[{name:status,uri:'https://contoso.com/change/rollout-002'}]"
az changesafety changerecord delete -g MyResourceGroup -n changerecord002 --yes
- name: Create a change state for a VM rollout
text: |-
az changesafety changerecord create -g MyResourceGroup -n changerecord001 --change-type AppDeployment --rollout-type Normal --targets "resourceId=/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MyResourceGroup/providers/Microsoft.Compute/virtualMachines/myVm,operation=PUT"
- name: Create with staging rollout configuration
text: |-
az changesafety changerecord create -g MyResourceGroup -n changerecord-ops01 --rollout-type Hotfix --targets "resourceId=/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MyResourceGroup/providers/Microsoft.Web/sites/myApp,operation=POST"
- name: Reference a StageMap by name
text: |-
az changesafety changerecord create -g MyResourceGroup -n changerecord003 --change-type ManualTouch --rollout-type Normal --stagemap-name rolloutStageMap --targets "resourceId=/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MyResourceGroup/providers/Microsoft.Compute/virtualMachines/myVm,operation=DELETE"
"""

helps['changesafety changerecord update'] = """
type: command
short-summary: Update an existing ChangeState resource.
long-summary: >
Use this command to modify descriptive metadata, rollout settings, or replace targets for an
existing ChangeState. When you pass --targets, the supplied definitions overwrite the previous set.
This command is also available through the alias `az change-safety change-record`.
parameters:
- name: --targets
short-summary: >
Optional target definitions to replace the existing list. Provide key=value pairs such as
resourceId=RESOURCE_ID,operation=DELETE.
- name: --stage-map-name --stagemap-name
short-summary: StageMap name in the current subscription scope; the resource ID is built for you.
- name: --stage-map
short-summary: Reference an existing StageMap resource using resource-id=RESOURCE_ID and optional parameters key=value pairs.
- name: --comments
short-summary: Provide notes about the latest update to the change state.
- name: --anticipated-start-time
short-summary: Update the expected start time in ISO 8601 format. If omitted, the current value is preserved.
- name: --anticipated-end-time
short-summary: Update the expected completion time in ISO 8601 format. If omitted, the current value is preserved.
examples:
- name: Adjust rollout type and add a comment
text: |-
az changesafety changerecord update -g MyResourceGroup -n changerecord001 --rollout-type Emergency --comments "Escalated to emergency rollout"
- name: Update scheduling window
text: |-
az changesafety changerecord update -g MyResourceGroup -n changerecord001 --anticipated-start-time "2024-09-01T08:00:00Z" --anticipated-end-time "2024-09-01T12:00:00Z"
- name: Replace the target definition
text: |-
az changesafety changerecord update -g MyResourceGroup -n changerecord001 --targets "resourceId=/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MyResourceGroup/providers/Microsoft.Sql/servers/myServer,operation=PATCH"
"""

helps['changesafety changerecord delete'] = """
type: command
short-summary: Delete a ChangeState resource.
examples:
- name: Delete a change state without confirmation
text: |-
az changesafety changerecord delete -g MyResourceGroup -n changerecord001 --yes
"""

helps['changesafety changerecord show'] = """
type: command
short-summary: Show details for a ChangeState resource.
examples:
- name: Show a change state
text: |-
az changesafety changerecord show -g MyResourceGroup -n changerecord001
"""
13 changes: 13 additions & 0 deletions src/azure-changesafety/azext_changesafety/_params.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
#
# Code generated by aaz-dev-tools
# --------------------------------------------------------------------------------------------

# pylint: disable=too-many-lines
# pylint: disable=too-many-statements


def load_arguments(self, _): # pylint: disable=unused-argument
pass
6 changes: 6 additions & 0 deletions src/azure-changesafety/azext_changesafety/aaz/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
#
# Code generated by aaz-dev-tools
# --------------------------------------------------------------------------------------------
10 changes: 10 additions & 0 deletions src/azure-changesafety/azext_changesafety/aaz/latest/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
#
# Code generated by aaz-dev-tools
# --------------------------------------------------------------------------------------------

# pylint: skip-file
# flake8: noqa

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
#
# Code generated by aaz-dev-tools
# --------------------------------------------------------------------------------------------

# pylint: skip-file
# flake8: noqa

from azure.cli.core.aaz import *


@register_command_group(
"changesafety",
)
class __CMDGroup(AAZCommandGroup):
"""Manage Change Safety
"""
pass


__all__ = ["__CMDGroup"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
#
# Code generated by aaz-dev-tools
# --------------------------------------------------------------------------------------------

# pylint: skip-file
# flake8: noqa

from .__cmd_group import *
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
#
# Code generated by aaz-dev-tools
# --------------------------------------------------------------------------------------------

# pylint: skip-file
# flake8: noqa

from azure.cli.core.aaz import *


@register_command_group(
"changesafety changestate",
)
class __CMDGroup(AAZCommandGroup):
"""Manage Change State
"""
pass


__all__ = ["__CMDGroup"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
#
# Code generated by aaz-dev-tools
# --------------------------------------------------------------------------------------------

# pylint: skip-file
# flake8: noqa

from .__cmd_group import *
from ._create import *
from ._delete import *
from ._show import *
from ._update import *
Loading
Loading