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
44 changes: 25 additions & 19 deletions .github/workflows/auto-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ jobs:
fi

# Extract commit message (after SHA)
MESSAGE=$(echo "$commit" | sed 's/^[a-f0-9]* //')
MESSAGE="${commit#* }"

# Check for breaking changes
if echo "$MESSAGE" | grep -qiE '!:' || echo "$MESSAGE" | grep -qiE 'BREAKING CHANGE'; then
Expand Down Expand Up @@ -113,10 +113,12 @@ jobs:
BUMP="none"
fi

echo "bump=$BUMP" >> "$GITHUB_OUTPUT"
echo "breaking=$BREAKING" >> "$GITHUB_OUTPUT"
echo "features=$FEATURES" >> "$GITHUB_OUTPUT"
echo "fixes=$FIXES" >> "$GITHUB_OUTPUT"
{
echo "bump=$BUMP"
echo "breaking=$BREAKING"
echo "features=$FEATURES"
echo "fixes=$FIXES"
} >> "$GITHUB_OUTPUT"

- name: Calculate new version
if: steps.analyze.outputs.bump != 'none'
Expand Down Expand Up @@ -168,7 +170,7 @@ jobs:
echo "Creating tag: $NEW_TAG"
# Use GitHub API to create tag (triggers workflows)
SHA=$(git rev-parse HEAD)
gh api repos/${GITHUB_REPOSITORY}/git/refs -X POST -f ref="refs/tags/$NEW_TAG" -f sha="$SHA"
gh api "repos/${GITHUB_REPOSITORY}/git/refs" -X POST -f ref="refs/tags/$NEW_TAG" -f sha="$SHA"
echo "Tag $NEW_TAG created successfully via GitHub API"

- name: Summary
Expand All @@ -180,20 +182,24 @@ jobs:
FEATURES: ${{ steps.analyze.outputs.features }}
FIXES: ${{ steps.analyze.outputs.fixes }}
run: |
echo "## Auto Release Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **New Tag:** $NEW_TAG" >> $GITHUB_STEP_SUMMARY
echo "- **Bump Type:** $BUMP" >> $GITHUB_STEP_SUMMARY
echo "- **Breaking Changes:** $BREAKING" >> $GITHUB_STEP_SUMMARY
echo "- **Features:** $FEATURES" >> $GITHUB_STEP_SUMMARY
echo "- **Fixes:** $FIXES" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Release workflow will be triggered automatically." >> $GITHUB_STEP_SUMMARY
{
echo "## Auto Release Summary"
echo ""
echo "- **New Tag:** $NEW_TAG"
echo "- **Bump Type:** $BUMP"
echo "- **Breaking Changes:** $BREAKING"
echo "- **Features:** $FEATURES"
echo "- **Fixes:** $FIXES"
echo ""
echo "Release workflow will be triggered automatically."
} >> "$GITHUB_STEP_SUMMARY"

- name: No release needed
if: steps.analyze.outputs.bump == 'none'
run: |
echo "## No Release Needed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "No conventional commits (feat:, fix:, BREAKING CHANGE) found since last tag." >> $GITHUB_STEP_SUMMARY
echo "Skipping release." >> $GITHUB_STEP_SUMMARY
{
echo "## No Release Needed"
echo ""
echo "No conventional commits (feat:, fix:, BREAKING CHANGE) found since last tag."
echo "Skipping release."
} >> "$GITHUB_STEP_SUMMARY"
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ concurrency:

jobs:
docs:
uses: YiAgent/OpenCI/.github/workflows/reusable-docs.yml@b96e013bfaad2e6898dd6a25d127411a21da5c00
uses: YiAgent/OpenCI/.github/workflows/reusable-docs.yml@4e1ecadc2505761f104f3fd8d255eee4eb369d90
with:
build-cmd: ${{ vars.DOCS_BUILD_CMD || '' }}
docs-path: ${{ vars.DOCS_DIR || 'docs' }}
Expand Down
66 changes: 60 additions & 6 deletions actions/issue/extract-plan/extract-plan.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,27 @@ extract_plan_from_file() {
done < "$file" \
| PLAN_VERSION="$PLAN_VERSION" perl -0777 -ne '
my $v = quotemeta $ENV{PLAN_VERSION};
while (m{ \{ (?: [^{}] | (?R) )* "version" \s* : \s* "$v" (?: [^{}] | (?R) )* \} }gsx) {
print "$&\n"
my $t = $_; my @found; my $pos = 0;
while ($pos < length $t) {
if (substr($t,$pos,1) eq "{") {
my ($d,$i,$s,$e) = (1,$pos+1,0,0);
while ($i < length($t) && $d > 0) {
my $c = substr($t,$i,1);
if ($e) { $e=0 }
elsif ($s) { if ($c eq "\\") { $e=1 } elsif ($c eq "\"") { $s=0 } }
elsif ($c eq "\"") { $s=1 }
elsif ($c eq "{") { $d++ }
elsif ($c eq "}") { $d-- }
$i++;
}
if ($d == 0) {
my $cand = substr($t,$pos,$i-$pos);
push @found, $cand if $cand =~ /"version"\s*:\s*"$v"/;
}
}
$pos++;
}
print "$found[-1]\n" if @found;
' \
| tail -n1
)"
Expand All @@ -76,9 +94,27 @@ extract_plan_from_file() {
found="$(printf '%s' "$concatenated" \
| PLAN_VERSION="$PLAN_VERSION" perl -0777 -ne '
my $v = quotemeta $ENV{PLAN_VERSION};
while (m{ \{ (?: [^{}] | (?R) )* "version" \s* : \s* "$v" (?: [^{}] | (?R) )* \} }gsx) {
print "$&\n"
my $t = $_; my @found; my $pos = 0;
while ($pos < length $t) {
if (substr($t,$pos,1) eq "{") {
my ($d,$i,$s,$e) = (1,$pos+1,0,0);
while ($i < length($t) && $d > 0) {
my $c = substr($t,$i,1);
if ($e) { $e=0 }
elsif ($s) { if ($c eq "\\") { $e=1 } elsif ($c eq "\"") { $s=0 } }
elsif ($c eq "\"") { $s=1 }
elsif ($c eq "{") { $d++ }
elsif ($c eq "}") { $d-- }
$i++;
}
if ($d == 0) {
my $cand = substr($t,$pos,$i-$pos);
push @found, $cand if $cand =~ /"version"\s*:\s*"$v"/;
}
}
$pos++;
}
print "$found[-1]\n" if @found;
' \
| tail -n1)"
if [ -n "$found" ] && jq -e . <<<"$found" >/dev/null 2>&1; then
Expand Down Expand Up @@ -106,9 +142,27 @@ extract_plan_from_file() {
if [ -n "${concatenated:-}" ]; then
found="$(printf '%s' "$concatenated" \
| perl -0777 -ne '
while (m{ \{ (?: [^{}] | (?R) )* "actions" \s* : \s* \[ (?: [^\[\]] | (?R) )* \] (?: [^{}] | (?R) )* \} }gsx) {
print "$&\n"
my $t = $_; my @found; my $pos = 0;
while ($pos < length $t) {
if (substr($t,$pos,1) eq "{") {
my ($d,$i,$s,$e) = (1,$pos+1,0,0);
while ($i < length($t) && $d > 0) {
my $c = substr($t,$i,1);
if ($e) { $e=0 }
elsif ($s) { if ($c eq "\\") { $e=1 } elsif ($c eq "\"") { $s=0 } }
elsif ($c eq "\"") { $s=1 }
elsif ($c eq "{") { $d++ }
elsif ($c eq "}") { $d-- }
$i++;
}
if ($d == 0) {
my $cand = substr($t,$pos,$i-$pos);
push @found, $cand if $cand =~ /"actions"\s*:\s*\[/;
}
}
$pos++;
}
print "$found[-1]\n" if @found;
' \
| while IFS= read -r candidate; do
if printf '%s' "$candidate" | jq -e '.version == "'"$PLAN_VERSION"'" and (.actions | type) == "array"' >/dev/null 2>&1; then
Expand Down
22 changes: 20 additions & 2 deletions actions/pr/extract-plan/extract-plan.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,27 @@ extract_plan_from_file() {
found="$(printf '%s' "$concatenated" \
| PLAN_VERSION="$PLAN_VERSION" perl -0777 -ne '
my $v = quotemeta $ENV{PLAN_VERSION};
while (m{ \{ (?: [^{}] | (?R) )* "version" \s* : \s* "$v" (?: [^{}] | (?R) )* \} }gsx) {
print "$&\n"
my $t = $_; my @found; my $pos = 0;
while ($pos < length $t) {
if (substr($t,$pos,1) eq "{") {
my ($d,$i,$s,$e) = (1,$pos+1,0,0);
while ($i < length($t) && $d > 0) {
my $c = substr($t,$i,1);
if ($e) { $e=0 }
elsif ($s) { if ($c eq "\\") { $e=1 } elsif ($c eq "\"") { $s=0 } }
elsif ($c eq "\"") { $s=1 }
elsif ($c eq "{") { $d++ }
elsif ($c eq "}") { $d-- }
$i++;
}
if ($d == 0) {
my $cand = substr($t,$pos,$i-$pos);
push @found, $cand if $cand =~ /"version"\s*:\s*"$v"/;
}
}
$pos++;
}
print "$found[-1]\n" if @found;
' \
| tail -n1)"
if [ -n "$found" ] && jq -e . <<<"$found" >/dev/null 2>&1; then
Expand Down
10 changes: 8 additions & 2 deletions lefthook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,10 @@ pre-commit:
glob: "*.sh"
run: |
if command -v shellcheck >/dev/null 2>&1; then
shellcheck {staged_files}
# --severity=error: SC2034 (warning) is a false positive in library
# files sourced by other scripts; pre-push shellcheck-full uses the
# same threshold for consistency.
shellcheck --severity=error {staged_files}
else
echo "::notice::shellcheck not installed; skipping shell lint"
fi
Expand Down Expand Up @@ -312,7 +315,10 @@ pre-push:
exit 0
fi
# shellcheck disable=SC2086
shellcheck $files
# Use --severity=error: SC2034 (warning) produces false positives in
# library files sourced by other scripts (variables appear unused to
# shellcheck but are consumed by the sourcing scripts).
shellcheck --severity=error $files

yamllint-full:
tags: lint
Expand Down
19 changes: 19 additions & 0 deletions tests/actions/issue-extract-plan.bats
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,25 @@ JSONL
echo "$plan" | grep -q '"skill":"escalate"'
}

@test "JSONL: plan with nested params objects is extracted (regression for #93)" {
# The (?R) recursive perl regex broke when action plan had nested {} objects,
# e.g. params:{"reason":"...","labels":["needs-human"]} inside an action entry.
local ef="${TMPDIR}/exec.jsonl"
cat >"$ef" <<'JSONL'
{"type":"system","subtype":"init","message":"Claude Code initialized"}
{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"```json\n{\"version\":\"issue-action-plan/v1\",\"reasoning\":\"nested\",\"actions\":[{\"id\":\"escalate\",\"skill\":\"escalate\",\"params\":{\"reason\":\"not parseable\",\"labels\":[\"needs-human\"]},\"risk\":\"low\"}],\"skip_reason\":null}\n```"}]}}
{"type":"result","subtype":"success","is_error":false}
JSONL

run_extract "false" "$ef"
[ "$status" -eq 0 ]

local plan
plan="$(get_output_var action-plan)"
echo "$plan" | grep -q '"reasoning":"nested"'
echo "$plan" | grep -q '"params"'
}

@test "no crash when the second jq receives empty input (regression for #81)" {
# The original bug: extract returned an empty string and the canonicalize
# step `jq -c . <<<"$plan"` then crashed with 'Invalid numeric literal at
Expand Down
10 changes: 5 additions & 5 deletions tests/workflows/reusable/test-reusable-issue.sh
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ else
info "Created bug issue #${BUG_ISSUE}"

# Wait for workflow
local run_id
run_id""
if run_id=$(wait_for_workflow "issue-ops.yml"); then
info "Workflow run: ${run_id}"

Expand All @@ -670,7 +670,7 @@ else
fi

# Wait for agent comment
local agent_body
agent_body
if agent_body=$(wait_for_agent_comment "$BUG_ISSUE" "openci-agent-run"); then
if validate_issue_plan "$(extract_plan_from_comment "$agent_body")" "bug-issue-plan"; then
pass "Bug issue: valid issue-action-plan/v1 found"
Expand All @@ -696,11 +696,11 @@ else
_CURRENT_ISSUE="$FEATURE_ISSUE"
info "Created feature request issue #${FEATURE_ISSUE}"

local run_id2
run_id2
if run_id2=$(wait_for_workflow "issue-ops.yml"); then
local agent_body2
agent_body2
if agent_body2=$(wait_for_agent_comment "$FEATURE_ISSUE" "openci-agent-run"); then
local plan2
plan2
plan2=$(extract_plan_from_comment "$agent_body2")
if validate_issue_plan "$plan2" "feature-plan"; then
# Check for enhancement label in plan
Expand Down
Loading