Skip to content

Commit c1b9c8f

Browse files
committed
ci: add workflow to check CLI documentation sync
Add GitHub workflow that verifies CLI documentation stays in sync with implementation. The workflow runs on PRs, generates current docs, compares with existing docs, and comments on PR if outdated.
1 parent fe6e08e commit c1b9c8f

File tree

3 files changed

+81
-2
lines changed

3 files changed

+81
-2
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
name: Check CLI Documentation
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize]
6+
7+
jobs:
8+
check-docs:
9+
name: Verify CLI documentation is up-to-date
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Checkout code
13+
uses: actions/checkout@v4
14+
15+
- name: Set up Python
16+
uses: actions/setup-python@v5
17+
with:
18+
python-version: "3.10"
19+
20+
- name: Install dependencies
21+
run: |
22+
python3 -m pip install --upgrade pip
23+
pip install -e .
24+
25+
- name: Generate current CLI documentation
26+
run: |
27+
typer pyaxm.cli utils docs --name pyaxm-cli --output /tmp/cli.md
28+
29+
- name: Compare with existing documentation
30+
id: compare_docs
31+
run: |
32+
# Calculate MD5 hashes for both files
33+
OLD_HASH=$(md5sum docs/cli.md | awk '{ print $1 }')
34+
NEW_HASH=$(md5sum /tmp/cli.md | awk '{ print $1 }')
35+
36+
# Compare hashes
37+
if [ "$OLD_HASH" != "$NEW_HASH" ]; then
38+
echo "docs_outdated=true" >> $GITHUB_OUTPUT
39+
exit 1
40+
else
41+
echo "CLI documentation is up-to-date."
42+
echo "Hash: $OLD_HASH"
43+
echo "docs_outdated=false" >> $GITHUB_OUTPUT
44+
fi
45+
46+
- name: Comment on PR if documentation is outdated
47+
if: ${{ steps.compare_docs.outputs.docs_outdated == 'true' }}
48+
uses: actions/github-script@v6
49+
with:
50+
github-token: ${{ secrets.GITHUB_TOKEN }}
51+
script: |
52+
const pull_request_number = context.issue.number;
53+
const comment = 'CLI Documentation Check Failed;
54+
55+
github.rest.issues.createComment({
56+
owner: context.repo.owner,
57+
repo: context.repo.repo,
58+
issue_number: pull_request_number,
59+
body: comment
60+
});

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,19 @@ The token path is the location where the access token will be stored.
4141
## CLI:
4242
A command-line interface (CLI) tool called `pyaxm-cli` is included for easy access to the API.
4343

44-
For detailed usage instructions, available commands, options, and examples, please refer to the [CLI documentation](docs/cli.md).
44+
### Overview
45+
The CLI provides a convenient way to interact with the Apple Business Manager API directly from your terminal. It includes commands for managing devices, MDM servers, and retrieving device information.
46+
47+
### Detailed Documentation
48+
For comprehensive documentation of all available commands, options, and usage examples, please refer to the [CLI documentation](docs/cli.md).
49+
50+
### Updating Documentation
51+
The CLI documentation is automatically generated from the code. To update it after making changes to the CLI implementation, run:
52+
```bash
53+
typer pyaxm.cli utils docs --name pyaxm-cli --output docs/cli.md
54+
```
55+
56+
A GitHub workflow automatically checks that the documentation stays in sync.
4557

4658
# Client:
4759
Example usage:

pyaxm/cli.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
from pyaxm.client import Client
77

88
app = typer.Typer()
9-
client = Client()
109

1110
@app.command()
1211
def devices():
1312
"""List all devices in the organization."""
13+
client = Client()
1414
devices = client.list_devices()
1515
devices_data = []
1616
for device in devices:
@@ -23,6 +23,7 @@ def devices():
2323
@app.command()
2424
def device(device_id: Annotated[str, typer.Argument()]):
2525
"""Get a device by ID."""
26+
client = Client()
2627
device = client.get_device(device_id)
2728
device_info = {'id': device.id}
2829
device_info.update(device.attributes.model_dump())
@@ -32,6 +33,7 @@ def device(device_id: Annotated[str, typer.Argument()]):
3233
@app.command()
3334
def apple_care_coverage(device_id: Annotated[str, typer.Argument()]):
3435
"""Get AppleCare coverage for a device."""
36+
client = Client()
3537
coverage = client.get_apple_care_coverage(device_id)
3638
coverage_data = [item.attributes.model_dump() for item in coverage]
3739
df = pd.DataFrame(coverage_data)
@@ -40,6 +42,7 @@ def apple_care_coverage(device_id: Annotated[str, typer.Argument()]):
4042
@app.command()
4143
def mdm_servers():
4244
"""List all MDM servers."""
45+
client = Client()
4346
servers = client.list_mdm_servers()
4447
servers_data = []
4548
for server in servers:
@@ -52,6 +55,7 @@ def mdm_servers():
5255
@app.command()
5356
def mdm_server(server_id: Annotated[str, typer.Argument()]):
5457
"""List devices in a specific MDM server."""
58+
client = Client()
5559
devices = client.list_devices_in_mdm_server(server_id)
5660
devices_data = [{'id': device.id} for device in devices]
5761
df = pd.DataFrame(devices_data)
@@ -60,6 +64,7 @@ def mdm_server(server_id: Annotated[str, typer.Argument()]):
6064
@app.command()
6165
def mdm_server_assigned(device_id: Annotated[str, typer.Argument()]):
6266
"""Get the server assignment for a device."""
67+
client = Client()
6368
server_assignment = client.get_device_server_assignment(device_id)
6469
assignment_info = {'id': server_assignment.id}
6570
df = pd.DataFrame([assignment_info])
@@ -68,6 +73,7 @@ def mdm_server_assigned(device_id: Annotated[str, typer.Argument()]):
6873
@app.command()
6974
def assign_device(device_id: Annotated[List[str], typer.Argument()], server_id: Annotated[str, typer.Argument()]):
7075
"""Assign one or more devices to an MDM server."""
76+
client = Client()
7177
activity = client.assign_unassign_device_to_mdm_server(device_id, server_id, 'ASSIGN_DEVICES')
7278
activity_data = {'id': activity.id}
7379
activity_data.update(activity.attributes.model_dump())
@@ -77,6 +83,7 @@ def assign_device(device_id: Annotated[List[str], typer.Argument()], server_id:
7783
@app.command()
7884
def unassign_device(device_id: Annotated[List[str], typer.Argument()], server_id: Annotated[str, typer.Argument()]):
7985
"""Unassign one or more devices from an MDM server."""
86+
client = Client()
8087
activity = client.assign_unassign_device_to_mdm_server(device_id, server_id, 'UNASSIGN_DEVICES')
8188
activity_data = {'id': activity.id}
8289
activity_data.update(activity.attributes.model_dump())

0 commit comments

Comments
 (0)