1717 - js
1818 - rust
1919 - both
20+ release_mode :
21+ description : ' Manual release mode'
22+ required : true
23+ type : choice
24+ default : ' instant'
25+ options :
26+ - instant
27+ - changelog-pr
2028 bump_type :
2129 description : ' Version bump type'
2230 required : true
@@ -37,6 +45,7 @@ concurrency:
3745env :
3846 CARGO_TERM_COLOR : always
3947 RUSTFLAGS : -Dwarnings
48+ CARGO_TOKEN : ${{ secrets.CARGO_TOKEN }}
4049
4150jobs :
4251 # === DETECT CHANGES ===
@@ -268,6 +277,10 @@ jobs:
268277 working-directory : rust
269278 run : cargo clippy --all-targets --all-features
270279
280+ - name : Check file size limit
281+ working-directory : rust
282+ run : node ../scripts/rust/check-file-size.mjs
283+
271284 # === RUST TEST ===
272285 rust-test :
273286 name : Rust Test (${{ matrix.os }})
@@ -459,17 +472,63 @@ jobs:
459472 working-directory : rust
460473 run : cargo build --release
461474
475+ - name : Publish to Crates.io
476+ if : steps.check.outputs.should_release == 'true'
477+ id : publish-crate
478+ working-directory : rust
479+ run : |
480+ PACKAGE_NAME=$(grep '^name = ' Cargo.toml | head -1 | sed 's/name = "\(.*\)"/\1/')
481+ PACKAGE_VERSION=$(grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
482+ echo "Package: $PACKAGE_NAME@$PACKAGE_VERSION"
483+
484+ echo "=== Attempting to publish to crates.io ==="
485+
486+ # Try to publish and capture the result
487+ set +e # Don't exit on error
488+ cargo publish --token ${{ secrets.CARGO_TOKEN }} --allow-dirty 2>&1 | tee publish_output.txt
489+ PUBLISH_EXIT_CODE=$?
490+ set -e # Re-enable exit on error
491+
492+ if [ $PUBLISH_EXIT_CODE -eq 0 ]; then
493+ echo "Successfully published $PACKAGE_NAME@$PACKAGE_VERSION to crates.io"
494+ echo "publish_result=success" >> $GITHUB_OUTPUT
495+ elif grep -q "already uploaded" publish_output.txt || grep -q "already exists" publish_output.txt; then
496+ echo "Version $PACKAGE_VERSION already exists on crates.io - this is OK"
497+ echo "publish_result=already_exists" >> $GITHUB_OUTPUT
498+ else
499+ echo "Failed to publish for unknown reason"
500+ cat publish_output.txt
501+ echo "publish_result=failed" >> $GITHUB_OUTPUT
502+ exit 1
503+ fi
504+
505+ - name : Report crates.io publish status
506+ if : steps.check.outputs.should_release == 'true'
507+ run : |
508+ if [ "${{ steps.publish-crate.outputs.publish_result }}" = "success" ]; then
509+ echo "Package was successfully published to crates.io"
510+ elif [ "${{ steps.publish-crate.outputs.publish_result }}" = "already_exists" ]; then
511+ echo "Package version already exists on crates.io - no action needed"
512+ else
513+ echo "Publishing to crates.io failed - please check the logs"
514+ fi
515+
462516 - name : Create GitHub Release
463517 if : steps.check.outputs.should_release == 'true'
464518 env :
465519 GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
466520 working-directory : rust
467- run : node ../scripts/rust/create-github-release.mjs --release-version "${{ steps.current_version.outputs.version }}" --repository "${{ github.repository }}"
521+ run : |
522+ PACKAGE_NAME=$(grep '^name = ' Cargo.toml | head -1 | sed 's/name = "\(.*\)"/\1/')
523+ node ../scripts/rust/create-github-release.mjs \
524+ --release-version "${{ steps.current_version.outputs.version }}" \
525+ --repository "${{ github.repository }}" \
526+ --crates-io-url "https://crates.io/crates/$PACKAGE_NAME"
468527
469- # === MANUAL RELEASE ===
528+ # === MANUAL INSTANT RELEASE ===
470529 manual-release :
471- name : Manual Release (${{ github.event.inputs.release_target }})
472- if : github.event_name == 'workflow_dispatch'
530+ name : Manual Instant Release (${{ github.event.inputs.release_target }})
531+ if : github.event_name == 'workflow_dispatch' && github.event.inputs.release_mode == 'instant'
473532 runs-on : ubuntu-latest
474533 permissions :
475534 contents : write
@@ -522,6 +581,19 @@ jobs:
522581 run : node ../scripts/js/create-github-release.mjs --release-version "${{ steps.js_publish.outputs.published_version }}" --repository "${{ github.repository }}"
523582
524583 # Rust Manual Release
584+ - name : Rust Collect changelog fragments
585+ if : github.event.inputs.release_target == 'rust' || github.event.inputs.release_target == 'both'
586+ working-directory : rust
587+ run : |
588+ # Check if there are any fragments to collect
589+ FRAGMENTS=$(find changelog.d -name "*.md" ! -name "README.md" 2>/dev/null | wc -l)
590+ if [ "$FRAGMENTS" -gt 0 ]; then
591+ echo "Found $FRAGMENTS changelog fragment(s), collecting..."
592+ node ../scripts/rust/collect-changelog.mjs
593+ else
594+ echo "No changelog fragments found, skipping collection"
595+ fi
596+
525597 - name : Rust Version and commit
526598 if : github.event.inputs.release_target == 'rust' || github.event.inputs.release_target == 'both'
527599 id : rust_version
@@ -533,9 +605,168 @@ jobs:
533605 working-directory : rust
534606 run : cargo build --release
535607
608+ - name : Rust Publish to Crates.io
609+ if : (github.event.inputs.release_target == 'rust' || github.event.inputs.release_target == 'both') && (steps.rust_version.outputs.version_committed == 'true' || steps.rust_version.outputs.already_released == 'true')
610+ id : rust_publish_crate
611+ working-directory : rust
612+ run : |
613+ PACKAGE_NAME=$(grep '^name = ' Cargo.toml | head -1 | sed 's/name = "\(.*\)"/\1/')
614+ PACKAGE_VERSION=$(grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
615+ echo "Package: $PACKAGE_NAME@$PACKAGE_VERSION"
616+
617+ echo "=== Attempting to publish to crates.io ==="
618+
619+ # Try to publish and capture the result
620+ set +e # Don't exit on error
621+ cargo publish --token ${{ secrets.CARGO_TOKEN }} --allow-dirty 2>&1 | tee publish_output.txt
622+ PUBLISH_EXIT_CODE=$?
623+ set -e # Re-enable exit on error
624+
625+ if [ $PUBLISH_EXIT_CODE -eq 0 ]; then
626+ echo "Successfully published $PACKAGE_NAME@$PACKAGE_VERSION to crates.io"
627+ echo "publish_result=success" >> $GITHUB_OUTPUT
628+ elif grep -q "already uploaded" publish_output.txt || grep -q "already exists" publish_output.txt; then
629+ echo "Version $PACKAGE_VERSION already exists on crates.io - this is OK"
630+ echo "publish_result=already_exists" >> $GITHUB_OUTPUT
631+ else
632+ echo "Failed to publish for unknown reason"
633+ cat publish_output.txt
634+ echo "publish_result=failed" >> $GITHUB_OUTPUT
635+ exit 1
636+ fi
637+
638+ - name : Rust Report crates.io publish status
639+ if : (github.event.inputs.release_target == 'rust' || github.event.inputs.release_target == 'both') && (steps.rust_version.outputs.version_committed == 'true' || steps.rust_version.outputs.already_released == 'true')
640+ run : |
641+ if [ "${{ steps.rust_publish_crate.outputs.publish_result }}" = "success" ]; then
642+ echo "Package was successfully published to crates.io"
643+ elif [ "${{ steps.rust_publish_crate.outputs.publish_result }}" = "already_exists" ]; then
644+ echo "Package version already exists on crates.io - no action needed"
645+ else
646+ echo "Publishing to crates.io failed - please check the logs"
647+ fi
648+
536649 - name : Rust Create GitHub Release
537650 if : (github.event.inputs.release_target == 'rust' || github.event.inputs.release_target == 'both') && (steps.rust_version.outputs.version_committed == 'true' || steps.rust_version.outputs.already_released == 'true')
538651 env :
539652 GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
540653 working-directory : rust
541- run : node ../scripts/rust/create-github-release.mjs --release-version "${{ steps.rust_version.outputs.new_version }}" --repository "${{ github.repository }}"
654+ run : |
655+ PACKAGE_NAME=$(grep '^name = ' Cargo.toml | head -1 | sed 's/name = "\(.*\)"/\1/')
656+ node ../scripts/rust/create-github-release.mjs \
657+ --release-version "${{ steps.rust_version.outputs.new_version }}" \
658+ --repository "${{ github.repository }}" \
659+ --crates-io-url "https://crates.io/crates/$PACKAGE_NAME"
660+
661+ # === MANUAL CHANGELOG PR ===
662+ changelog-pr :
663+ name : Create Changelog PR (${{ github.event.inputs.release_target }})
664+ if : github.event_name == 'workflow_dispatch' && github.event.inputs.release_mode == 'changelog-pr'
665+ runs-on : ubuntu-latest
666+ permissions :
667+ contents : write
668+ pull-requests : write
669+ steps :
670+ - uses : actions/checkout@v4
671+ with :
672+ fetch-depth : 0
673+
674+ - name : Setup Node.js
675+ uses : actions/setup-node@v4
676+ with :
677+ node-version : ' 20.x'
678+
679+ - name : Create JS changelog fragment
680+ if : github.event.inputs.release_target == 'js' || github.event.inputs.release_target == 'both'
681+ working-directory : js
682+ run : |
683+ BUMP_TYPE="${{ github.event.inputs.bump_type }}"
684+ DESCRIPTION="${{ github.event.inputs.description }}"
685+ TIMESTAMP=$(date +%Y%m%d%H%M%S)
686+ FRAGMENT_FILE=".changeset/${TIMESTAMP}-manual-${BUMP_TYPE}.md"
687+
688+ # Create changeset file
689+ mkdir -p .changeset
690+ cat > "$FRAGMENT_FILE" << EOF
691+ ---
692+ "agent-commander": $BUMP_TYPE
693+ ---
694+
695+ EOF
696+
697+ if [ -n "$DESCRIPTION" ]; then
698+ echo "${DESCRIPTION}" >> "$FRAGMENT_FILE"
699+ else
700+ echo "Manual ${BUMP_TYPE} release" >> "$FRAGMENT_FILE"
701+ fi
702+
703+ echo "Created changeset fragment: $FRAGMENT_FILE"
704+ cat "$FRAGMENT_FILE"
705+
706+ - name : Create Rust changelog fragment
707+ if : github.event.inputs.release_target == 'rust' || github.event.inputs.release_target == 'both'
708+ working-directory : rust
709+ run : |
710+ BUMP_TYPE="${{ github.event.inputs.bump_type }}"
711+ DESCRIPTION="${{ github.event.inputs.description }}"
712+ TIMESTAMP=$(date +%Y%m%d%H%M%S)
713+ FRAGMENT_FILE="changelog.d/${TIMESTAMP}-manual-${BUMP_TYPE}.md"
714+
715+ # Determine changelog category based on bump type
716+ case "$BUMP_TYPE" in
717+ major)
718+ CATEGORY="### Breaking Changes"
719+ ;;
720+ minor)
721+ CATEGORY="### Added"
722+ ;;
723+ patch)
724+ CATEGORY="### Fixed"
725+ ;;
726+ esac
727+
728+ # Create changelog fragment with frontmatter
729+ mkdir -p changelog.d
730+ cat > "$FRAGMENT_FILE" << EOF
731+ ---
732+ bump: $BUMP_TYPE
733+ ---
734+
735+ $CATEGORY
736+
737+ EOF
738+
739+ if [ -n "$DESCRIPTION" ]; then
740+ echo "- ${DESCRIPTION}" >> "$FRAGMENT_FILE"
741+ else
742+ echo "- Manual ${BUMP_TYPE} release" >> "$FRAGMENT_FILE"
743+ fi
744+
745+ echo "Created changelog fragment: $FRAGMENT_FILE"
746+ cat "$FRAGMENT_FILE"
747+
748+ - name : Create Pull Request
749+ uses : peter-evans/create-pull-request@v7
750+ with :
751+ token : ${{ secrets.GITHUB_TOKEN }}
752+ commit-message : ' chore: add changelog for manual ${{ github.event.inputs.bump_type }} release (${{ github.event.inputs.release_target }})'
753+ branch : changelog-manual-release-${{ github.run_id }}
754+ delete-branch : true
755+ title : ' chore: manual ${{ github.event.inputs.bump_type }} release (${{ github.event.inputs.release_target }})'
756+ body : |
757+ ## Manual Release Request
758+
759+ This PR was created by a manual workflow trigger to prepare a **${{ github.event.inputs.bump_type }}** release.
760+
761+ ### Release Details
762+ - **Target:** ${{ github.event.inputs.release_target }}
763+ - **Type:** ${{ github.event.inputs.bump_type }}
764+ - **Description:** ${{ github.event.inputs.description || 'Manual release' }}
765+ - **Triggered by:** @${{ github.actor }}
766+
767+ ### Next Steps
768+ 1. Review the changelog fragment(s) in this PR
769+ 2. Merge this PR to main
770+ 3. The automated release workflow will:
771+ - For JS: Publish to npm and create a GitHub release
772+ - For Rust: Publish to crates.io and create a GitHub release
0 commit comments