Skip to content

Add azpysdk changelog command group wrapping Chronus#46016

Merged
l0lawrence merged 20 commits intomainfrom
copilot/azpysdk-add-chronus-capabilities
Apr 28, 2026
Merged

Add azpysdk changelog command group wrapping Chronus#46016
l0lawrence merged 20 commits intomainfrom
copilot/azpysdk-add-chronus-capabilities

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 31, 2026

Integrates Chronus changelog management into the azpysdk CLI so developers don't need to use npx chronus directly.

New subcommands

Command Delegates to Purpose
azpysdk changelog add [package] npx chronus add Add a change entry (interactive or non-interactive)
azpysdk changelog verify npx chronus verify Check modified packages have entries
azpysdk changelog create npx chronus changelog Generate CHANGELOG.md from entries
azpysdk changelog status npx chronus status Show pending changes / version bumps

Commands work from both the repository root and from within a package directory. When running azpysdk changelog add from inside a package folder (e.g. sdk/storage/azure-storage-blob), the package path is detected automatically and passed to chronus. An explicit package argument always takes precedence.

The add subcommand supports --kind (-k) and --message (-m) flags for non-interactive use, including tagging entries as breaking changes. Valid kinds: breaking, feature, deprecation, fix, dependencies, internal. If omitted, chronus falls back to its interactive prompts.

Changes

  • azpysdk/changelog.py — New changelog Check subclass. Runs npx chronus <cmd> from repo root with inherited stdio for interactive prompts. Auto-detects package path from CWD when inside an sdk/<service>/<package> directory. Supports --kind and --message flags on add for non-interactive change entry creation (e.g. breaking changes). Errors clearly when Node.js/npx is missing.
  • azpysdk/main.py — Import and register the changelog command.
  • tests/test_changelog_commands.py — 41 tests covering parser structure, correct argument passthrough, --kind/--message flag forwarding, CWD-based package detection, repo-root cwd, exit code propagation, and npx-missing error handling.
# Example usage — from repo root
azpysdk changelog add sdk/storage/azure-storage-blob
azpysdk changelog add --kind breaking -m "Removed deprecated API"
azpysdk changelog add sdk/core/azure-core -k feature -m "Added new endpoint"
azpysdk changelog verify
azpysdk changelog create

# Example usage — from inside a package directory
cd sdk/storage/azure-storage-blob
azpysdk changelog add    # auto-detects the package
azpysdk changelog add -k fix -m "Fixed upload bug"

Copilot AI linked an issue Mar 31, 2026 that may be closed by this pull request
Copilot AI changed the title [WIP] Add chronus capabilities to azpysdk Add azpysdk changelog command group wrapping Chronus Mar 31, 2026
Copilot AI requested a review from l0lawrence March 31, 2026 16:26
Comment thread eng/tools/azure-sdk-tools/azpysdk/changelog.py Outdated
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 31, 2026

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • scanning-api.github.com
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node /home/REDACTED/work/_temp/ghcca-node/node/bin/node --enable-source-maps /home/REDACTED/work/_temp/copilot-developer-action-main/dist/index.js (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI requested a review from l0lawrence March 31, 2026 16:46
@l0lawrence
Copy link
Copy Markdown
Member

This should also support breaking changes — e.g. a --breaking flag on azpysdk changelog add or a way to tag entries as breaking so Chronus generates the appropriate changelog section and version bump.

@l0lawrence
Copy link
Copy Markdown
Member

This should also support breaking changes — e.g. a --breaking flag on azpysdk changelog add or a way to tag entries as breaking so Chronus generates the appropriate changelog section and version bump.

@copilot

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 7, 2026

This should also support breaking changes — e.g. a --breaking flag on azpysdk changelog add or a way to tag entries as breaking so Chronus generates the appropriate changelog section and versi...

Added in f63e08c. azpysdk changelog add now supports --kind (-k) and --message (-m) flags that forward directly to chronus's native options. Valid kinds are: breaking, feature, deprecation, fix, dependencies, internal.

Examples:

azpysdk changelog add --kind breaking -m "Removed deprecated API"
azpysdk changelog add sdk/core/azure-core -k feature -m "Added new endpoint"

If --kind or --message are omitted, chronus falls back to its interactive prompts as before.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • registry.npmjs.org
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/_temp/ghcca-node/node/bin/npx --no chronus add --help (dns block)
  • timotheeguerin.github.io
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node /home/REDACTED/work/_temp/ghcca-node/node/bin/node --enable-source-maps /home/REDACTED/work/_temp/copilot-developer-action-main/dist/index.js (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@l0lawrence
Copy link
Copy Markdown
Member

@copilot There are several issues to fix in this PR:

1. Read _CHANGE_KINDS from .chronus/config.yaml instead of hardcoding

In eng/tools/azure-sdk-tools/azpysdk/changelog.py, the _CHANGE_KINDS list is hardcoded and will silently diverge from .chronus/config.yaml. Instead, read the change kinds dynamically from the config file at module load time (with the hardcoded list as a fallback). Use pyyaml (already available in the repo) to parse .chronus/config.yaml and extract the keys from changeKinds. Add a helper function like:

def _load_change_kinds() -> List[str]:
    config_path = os.path.join(REPO_ROOT, ".chronus", "config.yaml")
    try:
        import yaml
        with open(config_path) as f:
            config = yaml.safe_load(f)
        kinds = list(config.get("changeKinds", {}).keys())
        if kinds:
            return kinds
    except Exception:
        pass
    return ["breaking", "feature", "deprecation", "fix", "dependencies", "internal"]

Then use _CHANGE_KINDS = _load_change_kinds() and add a test that validates the loaded kinds match what's in the config file.

2. Don't auto-install in non-TTY/CI without explicit opt-in

In _ensure_chronus_installed, the current code automatically runs npm install when stdin is not a TTY (CI environments). This is surprising and slow. Instead, require an explicit opt-in via the AZPYSDK_AUTO_INSTALL environment variable. Change the non-interactive branch to:

if not sys.stdin.isatty():
    if not os.environ.get("AZPYSDK_AUTO_INSTALL"):
        logger.error(
            "Chronus is not installed and running in non-interactive mode.\n"
            "Set AZPYSDK_AUTO_INSTALL=1 to allow automatic installation, or run:\n\n"
            f"    cd {REPO_ROOT}\n"
            "    npm install\n"
        )
        raise SystemExit(1)
    logger.info("AZPYSDK_AUTO_INSTALL set - running 'npm install' automatically.")

Update the corresponding tests to check for the env var behavior.

3. Use args.package directly instead of getattr

In _run_add, replace getattr(args, "package", None) with args.package since add_argument always sets the attribute. Same for args.kind and args.message. The getattr pattern is misleading - it suggests the attribute might not exist.

4. Avoid storing parser as private attr on Namespace

In _no_subcommand, accessing args._changelog_parser relies on a private attribute stashed on the Namespace. Instead, store the parser reference as an instance attribute on the changelog class itself (e.g. self._parser = p) and reference self._parser.print_help() in _no_subcommand.

Please make all four fixes and update the tests accordingly.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 7, 2026

@copilot There are several issues to fix in this PR:

1. Read _CHANGE_KINDS from .chronus/config.yaml instead of hardcoding...

All four fixes applied in 358c1c6:

  1. Dynamic change kinds_load_change_kinds() reads .chronus/config.yaml via pyyaml at module load, falls back to _FALLBACK_CHANGE_KINDS if config is missing or unparseable. New test validates loaded kinds match the config file.

  2. AZPYSDK_AUTO_INSTALL gate — Non-interactive mode now exits with an actionable error unless AZPYSDK_AUTO_INSTALL=1 is set. Two new tests cover both paths.

  3. Direct attribute access — Replaced getattr(args, "package", None) etc. with args.package, args.kind, args.message.

  4. Parser on instanceself._parser stores the parser reference; _no_subcommand uses self._parser.print_help() instead of args._changelog_parser.

45 tests passing.

@l0lawrence
Copy link
Copy Markdown
Member

@copilot if the user does not have chronus installed, install it for them and log it

@l0lawrence
Copy link
Copy Markdown
Member

@copilot if the user does not have chronus installed, install it for them and log it

@copilot

l0lawrence pushed a commit that referenced this pull request Apr 22, 2026
…iscovery

Two CI failures on PR #46016:

1. static-analysis (black): changelog.py and test_changelog_commands.py failed 'black --check'. Applied black with the repo's eng/black-pyproject.toml config.

2. verify-azpysdk-checks: the workflow discovers checks by scraping 'azpysdk -h' and invokes each one as 'azpysdk <check> --isolate <package>'. The changelog command group rejects --isolate (it's a developer tool wrapping Chronus, not a per-package check) and exits 2. Filter 'changelog' out of the discovery pipeline, same way 'next-*' checks are already filtered.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI and others added 6 commits April 22, 2026 15:21
Adds `azpysdk changelog {add,verify,create,status}` subcommands that
delegate to `npx chronus` at the repository root, enabling developers
to manage changelogs without leaving the azpysdk CLI.

Agent-Logs-Url: https://github.com/Azure/azure-sdk-for-python/sessions/a188ee1e-f36a-4ca9-be34-654196dd5328

Co-authored-by: l0lawrence <100643745+l0lawrence@users.noreply.github.com>
When running `azpysdk changelog add` from within a package directory
(e.g. sdk/storage/azure-storage-blob), the package path is now detected
automatically and passed to chronus. An explicit package argument still
takes precedence. Chronus itself always runs from the repo root.

Agent-Logs-Url: https://github.com/Azure/azure-sdk-for-python/sessions/758fb61b-770f-40c1-91a6-108220c6a402

Co-authored-by: l0lawrence <100643745+l0lawrence@users.noreply.github.com>
Add --kind (-k) and --message (-m) flags to `azpysdk changelog add`
that forward to chronus's native --kind and --message options. This
lets developers tag entries as breaking (or any other change kind)
non-interactively:

  azpysdk changelog add --kind breaking -m "Removed deprecated API"
  azpysdk changelog add -k feature -m "Added new endpoint"

Valid kinds: breaking, feature, deprecation, fix, dependencies, internal

Also fix _ensure_chronus_installed to skip the interactive prompt
when stdin is not a TTY (non-interactive / CI environments).

Agent-Logs-Url: https://github.com/Azure/azure-sdk-for-python/sessions/aa3dee26-9283-4594-a49f-64fc64d3d995

Co-authored-by: l0lawrence <100643745+l0lawrence@users.noreply.github.com>
…ct attr access, parser on instance

1. Read _CHANGE_KINDS from .chronus/config.yaml via _load_change_kinds()
   with hardcoded fallback when config or pyyaml is unavailable.
2. Non-interactive (CI) mode now requires AZPYSDK_AUTO_INSTALL=1 env var
   before running npm install automatically.
3. Use args.package/args.kind/args.message directly instead of getattr.
4. Store parser reference as self._parser on the changelog class instance
   instead of stashing a private attr on the argparse Namespace.

Agent-Logs-Url: https://github.com/Azure/azure-sdk-for-python/sessions/c9c4bf6e-9283-48b9-9861-00062d368e90

Co-authored-by: l0lawrence <100643745+l0lawrence@users.noreply.github.com>
l0lawrence and others added 3 commits April 23, 2026 08:39
Co-authored-by: Copilot <copilot@github.com>
The prior root package.json/lockfile were gitignored (the root is reserved
for tsp-client transient files), so they never actually shipped. Move the
pinned Chronus dev dependency to .github/chronus/ and commit both
package.json (exact version 1.3.1, no caret) and package-lock.json so
transitive deps are locked with integrity hashes.

Update azpysdk/changelog.py to:
  - look for chronus under .github/chronus/node_modules
  - install via 'npm ci' (honors lockfile, fails on drift) instead of
    'npm install'
  - invoke the pinned chronus binary directly instead of via npx, so
    there is no ambient resolution or registry lookup even if the local
    install is somehow incomplete

Tests updated accordingly; all 44 pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@l0lawrence
Copy link
Copy Markdown
Member

image

@l0lawrence
Copy link
Copy Markdown
Member

installing chronus for user after asking for permissions ^^

Comment thread eng/tools/azure-sdk-tools/azpysdk/changelog.py Outdated
@l0lawrence l0lawrence marked this pull request as ready for review April 24, 2026 19:48
@l0lawrence l0lawrence requested review from a team and mccoyp as code owners April 24, 2026 19:48
Copilot AI review requested due to automatic review settings April 24, 2026 19:48
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new azpysdk changelog command group to wrap Chronus changelog operations from the Azure SDK for Python tooling, along with pinned Chronus Node dependencies and CI/test updates.

Changes:

  • Introduces azpysdk changelog subcommands (add, verify, create, status) that invoke a pinned Chronus binary and optionally auto-detect the package from CWD.
  • Registers the new command group in the azpysdk CLI and updates the azure-sdk-tools GitHub workflow to exclude it from the “run all checks” dispatcher.
  • Adds a comprehensive new test suite for parser shape, argument forwarding, CWD-based package detection, and install gating behavior.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
eng/tools/azure-sdk-tools/azpysdk/changelog.py New CLI command group implementing Chronus invocation, install gating, and package resolution.
eng/tools/azure-sdk-tools/azpysdk/main.py Registers the new changelog command group in the top-level CLI.
eng/tools/azure-sdk-tools/tests/test_changelog_commands.py Adds unit tests for parser registration, command invocation, and install behavior.
.github/workflows/azure-sdk-tools.yml Excludes changelog from the auto-discovered “checks” list run by the workflow.
.github/chronus/package.json Adds pinned Chronus dev dependency for reproducible local execution.
.github/chronus/package-lock.json Locks Chronus transitive dependency graph for reproducibility and integrity.
Files not reviewed (1)
  • .github/chronus/package-lock.json: Language not supported

Comment thread eng/tools/azure-sdk-tools/azpysdk/changelog.py Outdated
Comment thread eng/tools/azure-sdk-tools/azpysdk/changelog.py Outdated
Comment thread eng/tools/azure-sdk-tools/tests/test_changelog_commands.py Outdated
Comment thread eng/tools/azure-sdk-tools/tests/test_changelog_commands.py
l0lawrence added a commit that referenced this pull request Apr 24, 2026
Per review feedback on #46016, route package discovery through the shared
Check.get_targeted_directories pipeline used by import_all and other
azpysdk checks instead of custom discover_targeted_packages / walk-up logic.

Behavior changes:
- add/create/status now inherit the common 'target' positional (default '**').
- Subdirectory walk-up is dropped: run from package root with '.' or pass the
  package path/name explicitly.
- verify is unchanged (always repo-level, no target).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@l0lawrence l0lawrence force-pushed the copilot/azpysdk-add-chronus-capabilities branch from 889db0a to 593b23b Compare April 24, 2026 21:24
Comment thread .github/workflows/azure-sdk-tools.yml
@l0lawrence l0lawrence enabled auto-merge (squash) April 28, 2026 17:28
@l0lawrence l0lawrence merged commit 4f13652 into main Apr 28, 2026
18 checks passed
@l0lawrence l0lawrence deleted the copilot/azpysdk-add-chronus-capabilities branch April 28, 2026 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[azpysdk] add chronus capabilities to azpysdk

4 participants