azure-cli-extensions: update docs on adding extension

Closes https://github.com/NixOS/nixpkgs/issues/342214

Signed-off-by: Paul Meyer <katexochen0@gmail.com>

+69 -16
+14 -12
pkgs/by-name/az/azure-cli/README.md
··· 33 33 and the name of the extension you want to package as `extension`: 34 34 35 35 ```sh 36 - ./query-extension-index.sh --cli-version=2.61.0 --extension=azure-devops --download 36 + nix run .#azure-cli.extension-tool -- \ 37 + --cli-version=2.61.0 \ 38 + --extension=azure-devops \ 39 + --init 37 40 ``` 38 41 39 42 The output should look something like this: ··· 41 44 ```json 42 45 { 43 46 "pname": "azure-devops", 44 - "description": "Tools for managing Azure DevOps.", 45 - "version": "1.0.1", 46 - "url": "https://github.com/Azure/azure-devops-cli-extension/releases/download/20240514.1/azure_devops-1.0.1-py2.py3-none-any.whl", 47 - "sha256": "f300d0288f017148514ebe6f5912aef10c7a6f29bdc0c916b922edf1d75bc7db", 47 + "version": "1.0.2", 48 + "url": "https://github.com/Azure/azure-devops-cli-extension/releases/download/20250624.2/azure_devops-1.0.2-py2.py3-none-any.whl", 49 + "hash": "sha256-4rDeAqOnRRKMP26MJxG4u9vBuos6/SQIoVgfNbBpulk=", 50 + "description": "Tools for managing Azure DevOps", 48 51 "license": "MIT", 49 - "requires": [ 50 - "distro (==1.3.0)", 51 - "distro==1.3.0" 52 + "requirements": [ 53 + "distro (>=1.6.0)" 52 54 ] 53 55 } 54 56 ``` ··· 58 60 ```nix 59 61 azure-devops = mkAzExtension { 60 62 pname = "azure-devops"; 61 - version = "1.0.0"; 62 - url = "https://github.com/Azure/azure-devops-cli-extension/releases/download/20240206.1/azure_devops-${version}-py2.py3-none-any.whl"; 63 - sha256 = "658a2854d8c80f874f9382d421fa45abf6a38d00334737dda006f8dec64cf70a"; 63 + version = "1.0.2"; 64 + url = "https://github.com/Azure/azure-devops-cli-extension/releases/download/20250624.2/azure_devops-${version}-py2.py3-none-any.whl"; 65 + hash = "sha256-4rDeAqOnRRKMP26MJxG4u9vBuos6/SQIoVgfNbBpulk="; 64 66 description = "Tools for managing Azure DevOps"; 65 67 propagatedBuildInputs = with python3Packages; [ 66 68 distro ··· 71 73 72 74 * The attribute name should be the same as `pname`. 73 75 * Replace the version in `url` with `${version}`. 74 - * The json output `requires` must be transformed into `propagetedBuildInputs`. 76 + * The json output `requirements` must be transformed into package `requirements`. 75 77 * If `license` is `"MIT"`, it can be left out in the nix expression, as the builder defaults to that license. 76 78 * Add yourself as maintainer in `meta.maintainers`. 77 79
+55 -4
pkgs/by-name/az/azure-cli/extensions-tool.py
··· 174 174 return max(versions, key=lambda e: parse(e["metadata"]["version"]), default=None) 175 175 176 176 177 - def processExtension( 177 + def find_extension_version( 178 178 extVersions: dict, 179 179 cli_version: Version, 180 180 ext_name: Optional[str] = None, 181 181 requirements: bool = False, 182 - ) -> Optional[Ext]: 182 + ) -> Optional[Dict[str, Any]]: 183 183 versions = filter(_filter_invalid, extVersions) 184 184 versions = filter(lambda v: _filter_compatible(v, cli_version), versions) 185 185 latest = _get_latest_version(versions) ··· 188 188 if ext_name and latest["metadata"]["name"] != ext_name: 189 189 return None 190 190 if not requirements and "run_requires" in latest["metadata"]: 191 + return None 192 + return latest 193 + 194 + 195 + def find_and_transform_extension_version( 196 + extVersions: dict, 197 + cli_version: Version, 198 + ext_name: Optional[str] = None, 199 + requirements: bool = False, 200 + ) -> Optional[Ext]: 201 + latest = find_extension_version(extVersions, cli_version, ext_name, requirements) 202 + if not latest: 191 203 return None 192 204 193 205 return _transform_dict_to_obj(latest) ··· 335 347 action=argparse.BooleanOptionalAction, 336 348 help="whether to commit changes to git", 337 349 ) 350 + parser.add_argument( 351 + "--init", 352 + action=argparse.BooleanOptionalAction, 353 + help="whether you want to init a new extension", 354 + ) 338 355 args = parser.parse_args() 339 356 cli_version = parse(args.cli_version) 340 357 ··· 348 365 assert index["formatVersion"] == "1" # only support formatVersion 1 349 366 extensions_remote = index["extensions"] 350 367 368 + # init just prints the json of the extension version that matches the cli version. 369 + if args.init: 370 + if not args.extension: 371 + logger.error("extension name is required for --init") 372 + exit(1) 373 + 374 + for ext_name, ext_versions in extensions_remote.items(): 375 + if ext_name != args.extension: 376 + continue 377 + ext = find_extension_version( 378 + ext_versions, 379 + cli_version, 380 + args.extension, 381 + requirements=True, 382 + ) 383 + break 384 + if not ext: 385 + logger.error(f"Extension {args.extension} not found in index") 386 + exit(1) 387 + 388 + ext_translated = { 389 + "pname": ext["metadata"]["name"], 390 + "version": ext["metadata"]["version"], 391 + "url": ext["downloadUrl"], 392 + "hash": _convert_hash_digest_from_hex_to_b64_sri(ext["sha256Digest"]), 393 + "description": ext["metadata"]["summary"].rstrip("."), 394 + "license": ext["metadata"]["license"], 395 + "requirements": ext["metadata"]["run_requires"][0]["requires"], 396 + } 397 + print(json.dumps(ext_translated, indent=2)) 398 + return 399 + 351 400 if args.extension: 352 401 logger.info(f"updating extension: {args.extension}") 353 402 354 403 ext = Optional[Ext] 355 404 for _ext_name, extension in extensions_remote.items(): 356 - extension = processExtension( 405 + extension = find_and_transform_extension_version( 357 406 extension, cli_version, args.extension, requirements=True 358 407 ) 359 408 if extension: ··· 402 451 403 452 extensions_remote_filtered = set() 404 453 for _ext_name, extension in extensions_remote.items(): 405 - extension = processExtension(extension, cli_version, args.extension) 454 + extension = find_and_transform_extension_version( 455 + extension, cli_version, args.extension 456 + ) 406 457 if extension: 407 458 extensions_remote_filtered.add(extension) 408 459