codetether-agent 1.1.8

A2A-native AI coding agent for the CodeTether ecosystem
Documentation
// Jenkins Job Configuration Requirements:
// - Multibranch Pipeline: Add "Discover tags" behavior in Branch Sources → Git → Behaviors
// - Or configure GitHub webhook to trigger builds on tag push events
// - The "Package & Release" and "Publish to crates.io" stages only run when building tags
// - Windows cross-compilation requires: mingw-w64 (gcc + g++), rustup target x86_64-pc-windows-gnu
// - macOS builds are handled by GitHub Actions (.github/workflows/macos-release.yml)

pipeline {
    agent any

    environment {
        CARGO_HOME            = "${env.HOME}/.cargo"
        RUSTUP_HOME           = "${env.HOME}/.rustup"
        PATH                  = "/usr/local/bin:${env.HOME}/.cargo/bin:${env.PATH}"
        REPO                  = 'rileyseaburg/codetether-agent'
        BINARY_NAME           = 'codetether'

        // sccache backed by MinIO S3
        RUSTC_WRAPPER         = 'sccache'
        SCCACHE_BUCKET        = 'sccache'
        SCCACHE_ENDPOINT      = 'http://192.168.50.223:9000'
        SCCACHE_REGION        = 'us-east-1'
        SCCACHE_S3_KEY_PREFIX = 'codetether'
        SCCACHE_S3_USE_SSL    = 'false'
    }

    options {
        timestamps()
        timeout(time: 60, unit: 'MINUTES')
        disableConcurrentBuilds()
    }

    stages {
        stage('Checkout') {
            steps {
                checkout scm
                // Clean stale .cargo from workspace (CARGO_HOME is now $HOME/.cargo)
                sh 'rm -rf "${WORKSPACE}/.cargo"'
            }
        }

        stage('Build') {
            parallel {
                stage('Linux x86_64') {
                    steps {
                        withCredentials([
                            string(credentialsId: 'minio-access-key', variable: 'AWS_ACCESS_KEY_ID'),
                            string(credentialsId: 'minio-secret-key', variable: 'AWS_SECRET_ACCESS_KEY')
                        ]) {
                            sh '''
                                rustc --version
                                sccache --start-server 2>/dev/null || true
                                sccache --show-stats 2>&1 | grep "Cache location" || true
                                cargo build --release --features functiongemma
                                echo "=== sccache stats ==="
                                sccache --show-stats || true
                            '''
                        }
                    }
                }
                stage('Windows x86_64') {
                    steps {
                        withCredentials([
                            string(credentialsId: 'minio-access-key', variable: 'AWS_ACCESS_KEY_ID'),
                            string(credentialsId: 'minio-secret-key', variable: 'AWS_SECRET_ACCESS_KEY')
                        ]) {
                            sh '''
                                echo "Cross-compiling for Windows..."
                                cargo build --target x86_64-pc-windows-gnu --release --features functiongemma
                            '''
                        }
                    }
                }
            }
        }

        stage('Package & Release') {
            when {
                buildingTag()
            }
            steps {
                script {
                    env.VERSION = env.TAG_NAME
                }
                sh """
                    mkdir -p dist

                    # Linux x86_64
                    LINUX_ARTIFACT="${BINARY_NAME}-${VERSION}-x86_64-unknown-linux-gnu"
                    cp target/release/${BINARY_NAME} "dist/\${LINUX_ARTIFACT}"
                    cd dist && tar czf "\${LINUX_ARTIFACT}.tar.gz" "\${LINUX_ARTIFACT}" && cd ..

                    # Windows x86_64
                    WIN_ARTIFACT="${BINARY_NAME}-${VERSION}-x86_64-pc-windows-gnu.exe"
                    cp target/x86_64-pc-windows-gnu/release/${BINARY_NAME}.exe "dist/\${WIN_ARTIFACT}"
                    cd dist && tar czf "\${WIN_ARTIFACT%.exe}.tar.gz" "\${WIN_ARTIFACT}" && cd ..

                    # Checksums for all artifacts
                    cd dist && sha256sum *.tar.gz *.exe > SHA256SUMS-${VERSION}.txt && cd ..
                """
                archiveArtifacts artifacts: 'dist/*.tar.gz, dist/*.exe, dist/SHA256SUMS-*.txt', fingerprint: true

                withCredentials([string(credentialsId: 'github-token', variable: 'GH_TOKEN')]) {
                    sh """
                        # Extract release notes from annotated tag (generated by release.sh via codetether)
                        TAG_BODY=\$(git tag -l --format='%(contents:body)' ${env.TAG_NAME} 2>/dev/null || echo '')
                        if [ -n "\$TAG_BODY" ]; then
                            echo "\$TAG_BODY" > /tmp/release-notes.md
                            NOTES_FLAG="--notes-file /tmp/release-notes.md"
                        else
                            NOTES_FLAG="--generate-notes"
                        fi

                        gh release create ${env.TAG_NAME} \
                            dist/*.tar.gz \
                            dist/*.exe \
                            dist/SHA256SUMS-${VERSION}.txt \
                            --repo ${REPO} \
                            --title "${env.TAG_NAME} - CodeTether Agent" \
                            \$NOTES_FLAG \
                            --latest \
                            --verify-tag || \
                        gh release upload ${env.TAG_NAME} \
                            dist/*.tar.gz \
                            dist/*.exe \
                            dist/SHA256SUMS-${VERSION}.txt \
                            --repo ${REPO} --clobber
                    """
                }
            }
        }

        stage('Publish to crates.io') {
            when {
                buildingTag()
            }
            steps {
                withCredentials([
                    string(credentialsId: 'cargo-registry-token', variable: 'CARGO_REGISTRY_TOKEN'),
                    string(credentialsId: 'minio-access-key', variable: 'AWS_ACCESS_KEY_ID'),
                    string(credentialsId: 'minio-secret-key', variable: 'AWS_SECRET_ACCESS_KEY')
                ]) {
                    sh '''
                        echo "Publishing ${TAG_NAME} to crates.io ..."
                        cargo publish --allow-dirty --features functiongemma
                    '''
                }
            }
        }
    }

    post {
        success {
            echo "Build successful: ${env.TAG_NAME ?: env.BRANCH_NAME}"
        }
        failure {
            echo "Build failed: ${env.TAG_NAME ?: env.BRANCH_NAME}"
        }
    }
}