Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ push *ARGS: migration-check lint-fix fmt _auto-commit-fixes test
_auto-commit-fixes:
@{{auto_commit_script}}

# Update aionrs dependency (e.g. just update-aionrs or just update-aionrs v0.1.19)
# Update aionrs dependency: bump Cargo.toml tag, then open a PR whose body
# carries aionrs feat/fix/perf as conventional footer for release-please.
# e.g. `just update-aionrs` (latest) or `just update-aionrs v0.2.9`
update-aionrs *TAG:
@{{update_aionrs_script}} {{TAG}}

Expand Down
27 changes: 27 additions & 0 deletions scripts/just/aionrs-changelog-footer.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
$ErrorActionPreference = "Stop"

# Reads aionrs commit subject lines from the pipeline and emits a
# conventional-commit footer block. Keeps only feat/fix/perf, rewrites the
# scope to `engine`, drops original sub-scope and breaking "!", dedupes, and
# groups by type (feat -> fix -> perf). Emits "No user-facing engine changes."
# when nothing qualifies.

$lines = @($input)
$pattern = '^(feat|fix|perf)(?:\([^)]*\))?!?:\s*(.+?)\s*$'
$seen = [System.Collections.Generic.HashSet[string]]::new()
$groups = @{
feat = [System.Collections.Generic.List[string]]::new()
fix = [System.Collections.Generic.List[string]]::new()
perf = [System.Collections.Generic.List[string]]::new()
}

foreach ($line in $lines) {
$m = [regex]::Match(($line -replace "`r$", ""), $pattern)
if (-not $m.Success) { continue }
$typ = $m.Groups[1].Value
$entry = "$typ(engine): $($m.Groups[2].Value)"
if ($seen.Add($entry)) { $groups[$typ].Add($entry) }
}

$out = @($groups.feat) + @($groups.fix) + @($groups.perf)
if ($out.Count -gt 0) { $out -join "`n" } else { "No user-facing engine changes." }
33 changes: 33 additions & 0 deletions scripts/just/aionrs-changelog-footer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env bash
set -euo pipefail

# Reads aionrs commit subject lines (one per line) on stdin and emits a
# conventional-commit footer block on stdout. Keeps only feat/fix/perf,
# rewrites the scope to `engine`, drops original sub-scope and breaking "!",
# dedupes, and groups by type (feat -> fix -> perf). Emits a single
# "No user-facing engine changes." line when nothing qualifies.

# Program is passed on fd 3 so that stdin stays connected to the piped
# commit-subject stream (a plain `python3 - <<'PY'` heredoc would consume
# stdin itself, leaving nothing to read).
python3 /dev/fd/3 3<<'PY'
import re, sys

pat = re.compile(r'^(feat|fix|perf)(?:\([^)]*\))?!?:\s*(.+?)\s*$')
seen = set()
groups = {'feat': [], 'fix': [], 'perf': []}

for raw in sys.stdin:
m = pat.match(raw.rstrip('\n'))
if not m:
continue
typ, desc = m.group(1), m.group(2)
entry = f'{typ}(engine): {desc}'
if entry in seen:
continue
seen.add(entry)
groups[typ].append(entry)

out = groups['feat'] + groups['fix'] + groups['perf']
print('\n'.join(out) if out else 'No user-facing engine changes.')
PY
48 changes: 48 additions & 0 deletions scripts/just/aionrs-changelog-footer.test.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
$ErrorActionPreference = "Stop"
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$script = Join-Path $scriptDir "aionrs-changelog-footer.ps1"

function Assert-Transform($name, $inputText, $expected) {
$actual = ($inputText -split "`n" | & $script) -join "`n"
if ($actual -ne $expected) {
Write-Error "FAIL [$name]`n--- expected ---`n$expected`n--- actual ---`n$actual"
exit 1
}
}

Assert-Transform "filter+scope+dedup" @"
feat(agent): persist and report context usage
fix(agent): preserve emergency watermark after microcompact
Merge pull request #239 from iOfficeAI/jiahe/feat/context-usage
feat(agent): persist and report context usage
chore(main): release 0.2.8
chore: sync Cargo.lock for release
"@ @"
feat(engine): persist and report context usage
fix(engine): preserve emergency watermark after microcompact
"@

Assert-Transform "grouping" @"
fix(providers): buffer partial UTF-8 across SSE chunk boundaries
perf(agent): reduce token accounting overhead
feat: add openai responses api support
"@ @"
feat(engine): add openai responses api support
fix(engine): buffer partial UTF-8 across SSE chunk boundaries
perf(engine): reduce token accounting overhead
"@

Assert-Transform "empty" @"
chore: sync Cargo.lock for release
docs: update readme
"@ "No user-facing engine changes."

Assert-Transform "scopeless-and-bang" @"
feat!: drop legacy config
fix(config)!: rename field
"@ @"
feat(engine): drop legacy config
fix(engine): rename field
"@

Write-Output "aionrs-changelog-footer ps1 tests passed"
54 changes: 54 additions & 0 deletions scripts/just/aionrs-changelog-footer.test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env bash
set -euo pipefail

script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
script="$script_dir/aionrs-changelog-footer.sh"

assert_transform() {
local name="$1" input="$2" expected="$3"
local actual
actual="$(printf '%s' "$input" | bash "$script")"
if [[ "$actual" != "$expected" ]]; then
echo "FAIL [$name]" >&2
echo "--- expected ---" >&2; printf '%s\n' "$expected" >&2
echo "--- actual ---" >&2; printf '%s\n' "$actual" >&2
exit 1
fi
}

# Case 1: real v0.2.7...v0.2.8-style stream with merge/release noise + duplicate
assert_transform "filter+scope+dedup" \
'feat(agent): persist and report context usage
fix(agent): preserve emergency watermark after microcompact
Merge pull request #239 from iOfficeAI/jiahe/feat/context-usage
feat(agent): persist and report context usage
chore(main): release 0.2.8
chore: sync Cargo.lock for release
Merge pull request #240 from iOfficeAI/release-please--branches--main' \
'feat(engine): persist and report context usage
fix(engine): preserve emergency watermark after microcompact'

# Case 2: grouping order feat -> fix -> perf regardless of input order
assert_transform "grouping" \
'fix(providers): buffer partial UTF-8 across SSE chunk boundaries
perf(agent): reduce token accounting overhead
feat: add openai responses api support' \
'feat(engine): add openai responses api support
fix(engine): buffer partial UTF-8 across SSE chunk boundaries
perf(engine): reduce token accounting overhead'

# Case 3: no qualifying commits -> sentinel line
assert_transform "empty" \
'chore: sync Cargo.lock for release
docs: update readme
Merge pull request #1 from x/y' \
'No user-facing engine changes.'

# Case 4: scope-less and breaking-marker forms normalize to engine, drop "!"
assert_transform "scopeless-and-bang" \
'feat!: drop legacy config
fix(config)!: rename field' \
'feat(engine): drop legacy config
fix(engine): rename field'

echo "aionrs-changelog-footer script tests passed"
103 changes: 70 additions & 33 deletions scripts/just/update-aionrs.ps1
Original file line number Diff line number Diff line change
@@ -1,46 +1,83 @@
param(
[string] $Tag = ""
)

param([string] $Tag = "")
$ErrorActionPreference = "Stop"

if ([string]::IsNullOrWhiteSpace($Tag)) {
$refs = git ls-remote --tags https://github.com/iOfficeAI/aionrs.git
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$repoRoot = (Resolve-Path (Join-Path $scriptDir "../..")).ProviderPath
$footerScript = Join-Path $scriptDir "aionrs-changelog-footer.ps1"
$aionrsRepo = "https://github.com/iOfficeAI/aionrs.git"
$aionrsSlug = "iOfficeAI/aionrs"

function Fail($msg) { Write-Error $msg; exit 1 }

# preflight
if (-not (Get-Command gh -ErrorAction SilentlyContinue)) { Fail "gh CLI not found" }
gh auth status *> $null
if ($LASTEXITCODE -ne 0) { Fail "gh not authenticated; run 'gh auth login'" }
Set-Location $repoRoot
git diff --quiet; $d1 = $LASTEXITCODE
git diff --cached --quiet; $d2 = $LASTEXITCODE
if ($d1 -ne 0 -or $d2 -ne 0) { Fail "working tree not clean; commit or stash changes first" }

# resolve target tag
if ([string]::IsNullOrWhiteSpace($Tag)) {
$refs = git ls-remote --tags $aionrsRepo
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
$Tag = $refs |
ForEach-Object {
if ($_ -match "refs/tags/(v[0-9]+(?:\.[0-9]+)*(?:[-+][0-9A-Za-z.-]+)?)$") {
$Matches[1]
}
} |
ForEach-Object { if ($_ -match "refs/tags/(v[0-9]+(?:\.[0-9]+)*(?:[-+][0-9A-Za-z.-]+)?)$") { $Matches[1] } } |
Sort-Object { [version](($_ -replace "^v", "") -replace "[-+].*$", "") } |
Select-Object -Last 1

if ([string]::IsNullOrWhiteSpace($Tag)) {
Write-Error "No aionrs tags found"
exit 1
}
if ([string]::IsNullOrWhiteSpace($Tag)) { Fail "No aionrs tags found" }
Write-Output "Using latest tag: $Tag"
}

$path = "Cargo.toml"
$text = Get-Content -LiteralPath $path -Raw
$pattern = 'git = "https://github\.com/iOfficeAI/aionrs\.git", tag = "[^"]*"'
# read OLD tag from Cargo.toml, assert consistency
$cargo = Get-Content -LiteralPath "Cargo.toml" -Raw
$readPattern = 'git = "https://github\.com/iOfficeAI/aionrs\.git", tag = "([^"]*)"'
$found = [regex]::Matches($cargo, $readPattern) | ForEach-Object { $_.Groups[1].Value }
if ($found.Count -eq 0) { Fail "No aionrs git dependency tags found in Cargo.toml" }
$uniq = @($found | Select-Object -Unique)
if ($uniq.Count -ne 1) { Fail "aionrs tags in Cargo.toml are inconsistent: $($uniq -join ', ')" }
$oldTag = $uniq[0]

if ($oldTag -eq $Tag) { Write-Output "already on $Tag; nothing to do"; exit 0 }
Write-Output "Updating aionrs $oldTag -> $Tag"

# rewrite Cargo.toml
$replacePattern = 'git = "https://github\.com/iOfficeAI/aionrs\.git", tag = "[^"]*"'
$replacement = "git = `"https://github.com/iOfficeAI/aionrs.git`", tag = `"$Tag`""
$matches = [regex]::Matches($text, $pattern)
if ($matches.Count -eq 0) {
Write-Error "No aionrs git dependency tags found in Cargo.toml"
$updated = [regex]::Replace($cargo, $replacePattern, $replacement)
[System.IO.File]::WriteAllText((Resolve-Path -LiteralPath "Cargo.toml").ProviderPath, $updated, [System.Text.UTF8Encoding]::new($false))

# refresh lockfile
cargo check --workspace
if ($LASTEXITCODE -ne 0) { Fail "cargo check failed" }

# build changelog footer from aionrs compare range
$subjects = gh api "repos/$aionrsSlug/compare/$oldTag...$Tag" --jq '.commits[].commit.message | split("\n")[0]'
if ($LASTEXITCODE -ne 0) { Fail "failed to fetch aionrs compare range" }
$footer = ($subjects | & $footerScript) -join "`n"

$prBody = @"
Bumps embedded engine aionrs $oldTag → $Tag.
https://github.com/$aionrsSlug/compare/$oldTag...$Tag

$footer
"@

# branch + commit
$branch = "chore/update-aionrs-$Tag"
git checkout -b $branch
git add Cargo.toml Cargo.lock
git commit -m "chore(deps): update aionrs to $Tag"

# push through the full pre-push gate
just push -u origin $branch
if ($LASTEXITCODE -ne 0) {
Write-Error "pre-push gate failed. The aionrs bump likely needs adaptation code. Branch '$branch' is committed locally but NOT pushed, and no PR was created."
exit 1
}
$updated = [regex]::Replace($text, $pattern, $replacement)

[System.IO.File]::WriteAllText(
(Resolve-Path -LiteralPath $path).ProviderPath,
$updated,
[System.Text.UTF8Encoding]::new($false)
)
cargo check --workspace
exit $LASTEXITCODE
# create PR
gh pr create --title "chore(deps): update aionrs to $Tag" --body $prBody --base main --head $branch
if ($LASTEXITCODE -ne 0) { Fail "gh pr create failed" }
Write-Output "PR created for aionrs $oldTag -> $Tag"
Loading
Loading