copilot-session-usage 0.6.0__tar.gz → 0.6.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/.github/skills/gh-release-notes/SKILL.md +16 -0
- copilot_session_usage-0.6.1/.github/workflows/refresh-pricing.yml +72 -0
- copilot_session_usage-0.6.1/.github/workflows/release-notes.yml +127 -0
- copilot_session_usage-0.6.1/.github/workflows/release.yml +195 -0
- copilot_session_usage-0.6.1/CONTRIBUTING.md +65 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/PKG-INFO +1 -1
- copilot_session_usage-0.6.1/docs/internal/automated_release_proces.md +497 -0
- copilot_session_usage-0.6.0/CONTRIBUTING.md +0 -49
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/.editorconfig +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/.gitattributes +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/.github/changes/requests/skill-breakdown/01-request.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/.github/guidelines/git-commit-message.guideline.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/.github/guidelines/knowledge-base.guidelines.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/.github/pull_request_template.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/.github/skills/consolidate-knowledge-base/SKILL.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/.github/skills/record-finding/SKILL.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/.github/workflows/ci.yml +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/.github/workflows/publish.yml +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/.gitignore +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/.readthedocs.yaml +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/AGENTS.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/CHANGELOG.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/LICENSE +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/README.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/_static/changelog.js +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/_static/custom.css +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/changelog.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/conf.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/explanation/how-cost-estimation-works.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/explanation/index.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/how-to/add-commit-trailer.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/how-to/analyze-specific-session.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/how-to/batch-and-spending.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/how-to/export-json.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/how-to/index.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/how-to/wsl2.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/index.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/installation.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/reference/api.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/reference/cli.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/reference/index.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/reference/pricing.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/tutorials/getting-started.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/docs/source/tutorials/index.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/justfile +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/_schema/Base.schema.yaml +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/_schema/Concept.schema.yaml +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/_schema/Experiment.schema.yaml +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/_schema/Finding.schema.yaml +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/_schema/Hypothesis.schema.yaml +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/_schema/Outcome.schema.yaml +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/_schema/Playbook.schema.yaml +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/_schema/Principle.schema.yaml +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/_schema/Reference.schema.yaml +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/_schema/Structure.schema.yaml +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/concepts/copilot-cli.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/concepts/index.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/concepts/overview.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/concepts/session-cost-analysis.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/concepts/threshold-based-pricing.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/experiments/index.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/experiments/verify-subagent-cost-attribution.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/findings/2026.07.02-00.00-subagent-logs-runsubagent-prefix.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/findings/2026.07.02-22.00-title-generation-not-counted-as-model-turn.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/findings/2026.07.02-23.00-cache-write-approximation.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/findings/index.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/guides/automation-scripts.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/guides/cost-optimization.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/guides/index.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/guides/wsl2-setup.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/ideas/index.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/ideas/multi-session-efficiency-analytics.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/index.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/log.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/principles/findings-are-immutable.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/principles/index.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/reference/debug-log-format.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/reference/index.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/reference/pricing-formats.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/structures/cache-cost-approximation.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/structures/index.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/structures/knowledge-base-information-types.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/structures/session-discovery-algorithm.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/structures/subagent-cost-tracking.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/knowledge/structures/vscode-copilot-extension.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/pyproject.toml +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/scripts/refresh_pricing.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/skills/copilot-session-usage/SKILL.md +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/src/copilot_session_usage/__init__.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/src/copilot_session_usage/_internal/__init__.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/src/copilot_session_usage/_internal/copilot_cli.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/src/copilot_session_usage/_internal/core.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/src/copilot_session_usage/_internal/git.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/src/copilot_session_usage/_internal/vscode.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/src/copilot_session_usage/api.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/src/copilot_session_usage/cli.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/src/copilot_session_usage/data/__init__.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/src/copilot_session_usage/data/custom-models-pricing.yml +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/src/copilot_session_usage/data/models-and-pricing.lock +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/src/copilot_session_usage/data/models-and-pricing.yml +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/tests/conftest.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/tests/test_api.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/tests/test_cli.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/tests/test_core.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/tests/test_coverage_gaps.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/tests/test_git.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/tests/test_rendering.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/tests/test_vscode.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/tests/test_vscode_platform.py +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/uv.lock +0 -0
- {copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/uv.toml +0 -0
{copilot_session_usage-0.6.0 → copilot_session_usage-0.6.1}/.github/skills/gh-release-notes/SKILL.md
RENAMED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gh-release-notes
|
|
3
|
+
description: Generate end-user-friendly GitHub release notes from the actual diff between releases, including user impact, examples, breaking changes, and public documentation links.
|
|
4
|
+
argument-hint: "from_tag=... to_tag=... repo_path=..."
|
|
5
|
+
user-invocable: true
|
|
6
|
+
---
|
|
7
|
+
|
|
1
8
|
# Release Notes Generator (Git Diff Based)
|
|
2
9
|
|
|
3
10
|
Generate **end-user friendly** release notes by analyzing actual code changes between releases.
|
|
@@ -186,6 +193,15 @@ Organize changes into buckets. **Only include sections that have content.** Omit
|
|
|
186
193
|
|
|
187
194
|
---
|
|
188
195
|
|
|
196
|
+
## Non-interactive automation mode
|
|
197
|
+
|
|
198
|
+
When this skill is invoked by a CI job with an explicit request for machine-readable output:
|
|
199
|
+
|
|
200
|
+
- Honor the requested tag range and repository path exactly.
|
|
201
|
+
- Do not modify, commit, or push repository files unless the caller explicitly requests it.
|
|
202
|
+
- Return only the final release-note Markdown, without an explanation or a code fence.
|
|
203
|
+
- Preserve the user-impact categories, examples, breaking-change detection, and public documentation links described above.
|
|
204
|
+
|
|
189
205
|
## How to Use This Skill in a Session
|
|
190
206
|
|
|
191
207
|
**User Query:**
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
name: Refresh GitHub model pricing
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
# Run once a day, shortly after GitHub's documentation refresh window.
|
|
6
|
+
- cron: "17 2 * * *"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: refresh-pricing
|
|
11
|
+
cancel-in-progress: false
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: write
|
|
15
|
+
pull-requests: write
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
refresh-pricing:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- name: Check out repository
|
|
23
|
+
uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- name: Install uv
|
|
26
|
+
uses: astral-sh/setup-uv@v5
|
|
27
|
+
with:
|
|
28
|
+
enable-cache: true
|
|
29
|
+
python-version: "3.12"
|
|
30
|
+
|
|
31
|
+
- name: Install just
|
|
32
|
+
uses: extractions/setup-just@v2
|
|
33
|
+
|
|
34
|
+
- name: Install dependencies
|
|
35
|
+
run: uv sync --frozen --all-groups
|
|
36
|
+
|
|
37
|
+
- name: Refresh pricing
|
|
38
|
+
run: just refresh-pricing
|
|
39
|
+
|
|
40
|
+
- name: Check for upstream pricing changes
|
|
41
|
+
id: changes
|
|
42
|
+
shell: bash
|
|
43
|
+
run: |
|
|
44
|
+
pricing_file="src/copilot_session_usage/data/models-and-pricing.yml"
|
|
45
|
+
if git diff --quiet -- "$pricing_file"; then
|
|
46
|
+
echo "changed=false" >> "$GITHUB_OUTPUT"
|
|
47
|
+
echo "No pricing YAML changes detected."
|
|
48
|
+
else
|
|
49
|
+
echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
50
|
+
echo "Pricing YAML changed:"
|
|
51
|
+
git diff --stat -- "$pricing_file"
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
- name: Create or update pull request
|
|
55
|
+
if: steps.changes.outputs.changed == 'true'
|
|
56
|
+
uses: peter-evans/create-pull-request@v7
|
|
57
|
+
with:
|
|
58
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
59
|
+
base: main
|
|
60
|
+
branch: automation/refresh-pricing
|
|
61
|
+
delete-branch: true
|
|
62
|
+
commit-message: "chore(pricing): refresh GitHub model pricing"
|
|
63
|
+
title: "chore(pricing): refresh GitHub model pricing"
|
|
64
|
+
body: |
|
|
65
|
+
This automated pull request updates the bundled GitHub Copilot model pricing data.
|
|
66
|
+
|
|
67
|
+
Source: https://raw.githubusercontent.com/github/docs/main/data/tables/copilot/models-and-pricing.yml
|
|
68
|
+
|
|
69
|
+
The update was generated by running `just refresh-pricing`.
|
|
70
|
+
add-paths: |
|
|
71
|
+
src/copilot_session_usage/data/models-and-pricing.yml
|
|
72
|
+
src/copilot_session_usage/data/models-and-pricing.lock
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
name: Generate release notes (manual)
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
tag:
|
|
7
|
+
description: "Existing version tag to generate a draft release for"
|
|
8
|
+
required: true
|
|
9
|
+
type: string
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: release-notes-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: false
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: write
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
generate-release-notes:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- name: Check out tagged source
|
|
24
|
+
uses: actions/checkout@v4
|
|
25
|
+
with:
|
|
26
|
+
fetch-depth: 0
|
|
27
|
+
ref: ${{ inputs.tag || github.ref }}
|
|
28
|
+
|
|
29
|
+
- name: Resolve release range
|
|
30
|
+
id: range
|
|
31
|
+
shell: bash
|
|
32
|
+
env:
|
|
33
|
+
TARGET_TAG: ${{ inputs.tag || github.ref_name }}
|
|
34
|
+
run: |
|
|
35
|
+
set -euo pipefail
|
|
36
|
+
|
|
37
|
+
if [[ ! "$TARGET_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([.-].*)?$ ]]; then
|
|
38
|
+
echo "::error::Expected a semantic-version tag such as v0.7.0, got '$TARGET_TAG'."
|
|
39
|
+
exit 1
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
previous_tag="$(git tag --sort=-v:refname --merged "$TARGET_TAG" \
|
|
43
|
+
| awk -v current="$TARGET_TAG" '$0 != current { print; exit }')"
|
|
44
|
+
|
|
45
|
+
if [[ -z "$previous_tag" ]]; then
|
|
46
|
+
echo "::error::Could not find a previous release tag for $TARGET_TAG."
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
echo "target_tag=$TARGET_TAG" >> "$GITHUB_OUTPUT"
|
|
51
|
+
echo "previous_tag=$previous_tag" >> "$GITHUB_OUTPUT"
|
|
52
|
+
echo "Generating notes from $previous_tag to $TARGET_TAG."
|
|
53
|
+
|
|
54
|
+
- name: Verify release-note skill
|
|
55
|
+
env:
|
|
56
|
+
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
|
57
|
+
run: |
|
|
58
|
+
set -euo pipefail
|
|
59
|
+
|
|
60
|
+
if [[ -z "${COPILOT_GITHUB_TOKEN:-}" ]]; then
|
|
61
|
+
echo "::error::The COPILOT_GITHUB_TOKEN repository secret is not configured."
|
|
62
|
+
echo "Create a fine-grained PAT with the Copilot Requests permission and add it as a repository secret."
|
|
63
|
+
exit 1
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
if ! gh copilot -- skill list | grep -Fq 'gh-release-notes'; then
|
|
67
|
+
echo "::error::The gh-release-notes skill was not discovered by GitHub CLI."
|
|
68
|
+
exit 1
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
- name: Generate release notes with the skill
|
|
72
|
+
env:
|
|
73
|
+
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
|
74
|
+
PREVIOUS_TAG: ${{ steps.range.outputs.previous_tag }}
|
|
75
|
+
TARGET_TAG: ${{ steps.range.outputs.target_tag }}
|
|
76
|
+
run: |
|
|
77
|
+
set -euo pipefail
|
|
78
|
+
|
|
79
|
+
prompt="Use the /gh-release-notes skill.
|
|
80
|
+
|
|
81
|
+
Generate the final release notes for ${TARGET_TAG}, covering the actual changes from ${PREVIOUS_TAG} to ${TARGET_TAG} in ${GITHUB_WORKSPACE}.
|
|
82
|
+
|
|
83
|
+
Follow the skill's diff-based analysis process. Use the project's public documentation URL when documentation links are appropriate. Return only the final release-note Markdown, with no introduction, explanation, or code fence. Do not modify any repository files."
|
|
84
|
+
|
|
85
|
+
gh copilot -- \
|
|
86
|
+
--prompt "$prompt" \
|
|
87
|
+
--silent \
|
|
88
|
+
--no-ask-user \
|
|
89
|
+
--no-auto-update \
|
|
90
|
+
--no-color \
|
|
91
|
+
--disable-builtin-mcps \
|
|
92
|
+
--available-tools='read,shell' \
|
|
93
|
+
--allow-tool='read' \
|
|
94
|
+
--allow-tool='shell(git:*)' \
|
|
95
|
+
--allow-url='https://github.com' \
|
|
96
|
+
--allow-url='https://copilot-session-usage.readthedocs.io' \
|
|
97
|
+
> release-notes.md
|
|
98
|
+
|
|
99
|
+
if [[ ! -s release-notes.md ]]; then
|
|
100
|
+
echo "::error::The release-note skill returned an empty document."
|
|
101
|
+
exit 1
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
- name: Upload generated notes for review
|
|
105
|
+
uses: actions/upload-artifact@v4
|
|
106
|
+
with:
|
|
107
|
+
name: release-notes-${{ steps.range.outputs.target_tag }}
|
|
108
|
+
path: release-notes.md
|
|
109
|
+
|
|
110
|
+
- name: Create draft GitHub release
|
|
111
|
+
env:
|
|
112
|
+
GH_TOKEN: ${{ github.token }}
|
|
113
|
+
TARGET_TAG: ${{ steps.range.outputs.target_tag }}
|
|
114
|
+
run: |
|
|
115
|
+
set -euo pipefail
|
|
116
|
+
|
|
117
|
+
if gh release view "$TARGET_TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
|
|
118
|
+
echo "::error::A GitHub Release already exists for $TARGET_TAG."
|
|
119
|
+
exit 1
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
gh release create "$TARGET_TAG" \
|
|
123
|
+
--repo "$GITHUB_REPOSITORY" \
|
|
124
|
+
--verify-tag \
|
|
125
|
+
--draft \
|
|
126
|
+
--title "$TARGET_TAG" \
|
|
127
|
+
--notes-file release-notes.md
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
increment:
|
|
7
|
+
description: "Version bump to apply"
|
|
8
|
+
required: true
|
|
9
|
+
type: choice
|
|
10
|
+
default: auto
|
|
11
|
+
options:
|
|
12
|
+
- auto
|
|
13
|
+
- major
|
|
14
|
+
- minor
|
|
15
|
+
- patch
|
|
16
|
+
draft:
|
|
17
|
+
description: "Create a draft release instead of publishing it"
|
|
18
|
+
required: true
|
|
19
|
+
type: boolean
|
|
20
|
+
default: false
|
|
21
|
+
force:
|
|
22
|
+
description: "Force a patch release when auto finds no eligible commit"
|
|
23
|
+
required: true
|
|
24
|
+
type: boolean
|
|
25
|
+
default: false
|
|
26
|
+
|
|
27
|
+
concurrency:
|
|
28
|
+
group: release
|
|
29
|
+
cancel-in-progress: false
|
|
30
|
+
|
|
31
|
+
permissions:
|
|
32
|
+
contents: write
|
|
33
|
+
|
|
34
|
+
jobs:
|
|
35
|
+
release:
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
env:
|
|
38
|
+
GH_TOKEN: ${{ github.token }}
|
|
39
|
+
RELEASE_BRANCH: ${{ github.event.repository.default_branch }}
|
|
40
|
+
INCREMENT: ${{ inputs.increment }}
|
|
41
|
+
DRAFT_RELEASE: ${{ inputs.draft }}
|
|
42
|
+
FORCE_RELEASE: ${{ inputs.force }}
|
|
43
|
+
|
|
44
|
+
steps:
|
|
45
|
+
- name: Check out the default branch
|
|
46
|
+
uses: actions/checkout@v4
|
|
47
|
+
with:
|
|
48
|
+
fetch-depth: 0
|
|
49
|
+
ref: ${{ github.event.repository.default_branch }}
|
|
50
|
+
|
|
51
|
+
- name: Install uv
|
|
52
|
+
uses: astral-sh/setup-uv@v5
|
|
53
|
+
|
|
54
|
+
- name: Install release tooling
|
|
55
|
+
run: uv sync --locked --all-groups
|
|
56
|
+
|
|
57
|
+
- name: Calculate version and create tag
|
|
58
|
+
id: version
|
|
59
|
+
shell: bash
|
|
60
|
+
run: |
|
|
61
|
+
set -euo pipefail
|
|
62
|
+
|
|
63
|
+
if [[ -n "$(git status --porcelain)" ]]; then
|
|
64
|
+
echo "::error::The release branch is not clean. Refusing to create a release."
|
|
65
|
+
git status --short
|
|
66
|
+
exit 1
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
git switch --force-create "$RELEASE_BRANCH" "origin/$RELEASE_BRANCH"
|
|
70
|
+
|
|
71
|
+
previous_tag="$(git describe --tags --abbrev=0 HEAD 2>/dev/null || true)"
|
|
72
|
+
if [[ -z "$previous_tag" ]]; then
|
|
73
|
+
echo "::error::Could not find a previous release tag."
|
|
74
|
+
exit 1
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
if [[ "$INCREMENT" == "auto" ]]; then
|
|
78
|
+
bump_args=(--get-next --yes)
|
|
79
|
+
if [[ "$FORCE_RELEASE" == "true" ]]; then
|
|
80
|
+
bump_args+=(--allow-no-commit)
|
|
81
|
+
fi
|
|
82
|
+
if ! next_version_output="$(uv run --no-sync cz bump "${bump_args[@]}" 2>&1)"; then
|
|
83
|
+
echo "::error::No eligible conventional commits were found for an automatic release."
|
|
84
|
+
printf '%s\n' "$next_version_output"
|
|
85
|
+
exit 1
|
|
86
|
+
fi
|
|
87
|
+
else
|
|
88
|
+
echo "Using explicit $INCREMENT bump."
|
|
89
|
+
next_version_output="$(uv run --no-sync cz bump --get-next \
|
|
90
|
+
--increment "${INCREMENT^^}" --yes --allow-no-commit)"
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
next_version="$(printf '%s\n' "$next_version_output" | tail -n 1)"
|
|
94
|
+
if [[ ! "$next_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
95
|
+
echo "::error::Commitizen returned an invalid next version: '$next_version'."
|
|
96
|
+
printf '%s\n' "$next_version_output"
|
|
97
|
+
exit 1
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
target_tag="v$next_version"
|
|
101
|
+
if [[ ! "$target_tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([.-].*)?$ ]]; then
|
|
102
|
+
echo "::error::The calculated version did not create a semantic-version tag."
|
|
103
|
+
exit 1
|
|
104
|
+
fi
|
|
105
|
+
if git rev-parse "$target_tag" >/dev/null 2>&1; then
|
|
106
|
+
echo "::error::The tag $target_tag already exists."
|
|
107
|
+
exit 1
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
git tag "$target_tag"
|
|
111
|
+
git push origin "$target_tag"
|
|
112
|
+
|
|
113
|
+
echo "previous_tag=$previous_tag" >> "$GITHUB_OUTPUT"
|
|
114
|
+
echo "target_tag=$target_tag" >> "$GITHUB_OUTPUT"
|
|
115
|
+
echo "Generated $target_tag from $previous_tag without modifying the default branch."
|
|
116
|
+
|
|
117
|
+
- name: Verify release-note skill
|
|
118
|
+
env:
|
|
119
|
+
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
|
120
|
+
run: |
|
|
121
|
+
set -euo pipefail
|
|
122
|
+
|
|
123
|
+
if [[ -z "${COPILOT_GITHUB_TOKEN:-}" ]]; then
|
|
124
|
+
echo "::error::The COPILOT_GITHUB_TOKEN repository secret is not configured."
|
|
125
|
+
echo "Create a fine-grained PAT with the Copilot Requests permission and add it as a repository secret."
|
|
126
|
+
exit 1
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
if ! gh copilot -- skill list | grep -Fq 'gh-release-notes'; then
|
|
130
|
+
echo "::error::The gh-release-notes skill was not discovered by GitHub CLI."
|
|
131
|
+
exit 1
|
|
132
|
+
fi
|
|
133
|
+
|
|
134
|
+
- name: Generate release notes with gh-release-notes
|
|
135
|
+
env:
|
|
136
|
+
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
|
137
|
+
PREVIOUS_TAG: ${{ steps.version.outputs.previous_tag }}
|
|
138
|
+
TARGET_TAG: ${{ steps.version.outputs.target_tag }}
|
|
139
|
+
run: |
|
|
140
|
+
set -euo pipefail
|
|
141
|
+
|
|
142
|
+
prompt="Use the /gh-release-notes skill.
|
|
143
|
+
|
|
144
|
+
Generate the final release notes for ${TARGET_TAG}, covering the actual changes from ${PREVIOUS_TAG} to ${TARGET_TAG} in ${GITHUB_WORKSPACE}.
|
|
145
|
+
|
|
146
|
+
Follow the skill's diff-based analysis process. Use the project's public documentation URL when documentation links are appropriate. Return only the final release-note Markdown, with no introduction, explanation, or code fence. Do not modify, commit, or push any repository files."
|
|
147
|
+
|
|
148
|
+
gh copilot -- \
|
|
149
|
+
--prompt "$prompt" \
|
|
150
|
+
--silent \
|
|
151
|
+
--no-ask-user \
|
|
152
|
+
--no-auto-update \
|
|
153
|
+
--no-color \
|
|
154
|
+
--disable-builtin-mcps \
|
|
155
|
+
--available-tools='read,shell' \
|
|
156
|
+
--allow-tool='read' \
|
|
157
|
+
--allow-tool='shell(git:*)' \
|
|
158
|
+
--allow-url='https://github.com' \
|
|
159
|
+
--allow-url='https://copilot-session-usage.readthedocs.io' \
|
|
160
|
+
> release-notes.md
|
|
161
|
+
|
|
162
|
+
if [[ ! -s release-notes.md ]]; then
|
|
163
|
+
echo "::error::The release-note skill returned an empty document."
|
|
164
|
+
exit 1
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
- name: Upload generated notes
|
|
168
|
+
uses: actions/upload-artifact@v4
|
|
169
|
+
with:
|
|
170
|
+
name: release-notes-${{ steps.version.outputs.target_tag }}
|
|
171
|
+
path: release-notes.md
|
|
172
|
+
|
|
173
|
+
- name: Create GitHub release
|
|
174
|
+
env:
|
|
175
|
+
TARGET_TAG: ${{ steps.version.outputs.target_tag }}
|
|
176
|
+
shell: bash
|
|
177
|
+
run: |
|
|
178
|
+
set -euo pipefail
|
|
179
|
+
|
|
180
|
+
if gh release view "$TARGET_TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
|
|
181
|
+
echo "::error::A GitHub Release already exists for $TARGET_TAG."
|
|
182
|
+
exit 1
|
|
183
|
+
fi
|
|
184
|
+
|
|
185
|
+
release_args=(
|
|
186
|
+
--repo "$GITHUB_REPOSITORY"
|
|
187
|
+
--verify-tag
|
|
188
|
+
--title "$TARGET_TAG"
|
|
189
|
+
--notes-file release-notes.md
|
|
190
|
+
)
|
|
191
|
+
if [[ "$DRAFT_RELEASE" == "true" ]]; then
|
|
192
|
+
release_args+=(--draft)
|
|
193
|
+
fi
|
|
194
|
+
|
|
195
|
+
gh release create "$TARGET_TAG" "${release_args[@]}"
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Contributing to copilot-session-usage
|
|
2
|
+
|
|
3
|
+
## Setup
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
# Clone the repository
|
|
7
|
+
git clone https://github.com/gsemet/copilot-session-usage
|
|
8
|
+
cd copilot-session-usage
|
|
9
|
+
|
|
10
|
+
# Install dependencies (uses uv)
|
|
11
|
+
just dev
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Development workflow
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Run tests
|
|
18
|
+
just test
|
|
19
|
+
|
|
20
|
+
# Run full validation
|
|
21
|
+
just preflight
|
|
22
|
+
|
|
23
|
+
# Build documentation
|
|
24
|
+
just docs
|
|
25
|
+
|
|
26
|
+
# Serve docs with auto-reload
|
|
27
|
+
just docs-serve
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Code style
|
|
31
|
+
|
|
32
|
+
- **Formatter**: ruff (line length 100)
|
|
33
|
+
- **Linter**: ruff, ty, mypy
|
|
34
|
+
- **Type checker**: mypy (strict)
|
|
35
|
+
- **Test runner**: pytest with pytest-cov
|
|
36
|
+
|
|
37
|
+
## Adding features
|
|
38
|
+
|
|
39
|
+
1. Add or update code in `src/copilot_session_usage/`
|
|
40
|
+
2. Add tests in `tests/`
|
|
41
|
+
3. Update documentation in `docs/source/`
|
|
42
|
+
4. Run `just preflight` to validate
|
|
43
|
+
5. Submit a pull request
|
|
44
|
+
|
|
45
|
+
## Release process
|
|
46
|
+
|
|
47
|
+
1. Open the **Release** workflow under the repository's Actions tab.
|
|
48
|
+
2. Run it from the default branch, choosing `auto` to derive the major, minor, or
|
|
49
|
+
patch bump from conventional commits, or choose an explicit bump. Enable
|
|
50
|
+
`force` to create a patch release when `auto` finds no eligible commit.
|
|
51
|
+
3. The workflow uses Commitizen to calculate the next version, creates and pushes
|
|
52
|
+
the `vX.Y.Z` tag on the existing default-branch commit, and invokes the
|
|
53
|
+
`gh-release-notes` skill through `gh copilot`. It does not create a
|
|
54
|
+
version/changelog commit.
|
|
55
|
+
4. The generated notes are uploaded as an artifact and used to create the GitHub
|
|
56
|
+
Release. Enable the `draft` option if the release needs review before publishing.
|
|
57
|
+
5. Publishing the GitHub Release triggers CI and publishes the package to PyPI via
|
|
58
|
+
OIDC.
|
|
59
|
+
|
|
60
|
+
The workflow requires a repository secret named `COPILOT_GITHUB_TOKEN`. It must be
|
|
61
|
+
a fine-grained token with the **Copilot Requests** permission. The normal Actions
|
|
62
|
+
`GITHUB_TOKEN` is used for repository writes and GitHub Release creation.
|
|
63
|
+
|
|
64
|
+
The **Generate release notes (manual)** workflow remains available when notes need
|
|
65
|
+
to be regenerated for an existing tag without creating a new release.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: copilot-session-usage
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.1
|
|
4
4
|
Summary: Usage and cost analytics for GitHub Copilot and Copilot-CLI session logs
|
|
5
5
|
Project-URL: Homepage, https://github.com/gsemet/copilot-session-usage
|
|
6
6
|
Project-URL: Documentation, https://copilot-session-usage.readthedocs.io/en/stable/
|