|
| 1 | +name: CI - Build, Test, and Publish SDKs |
| 2 | + |
| 3 | +on: |
| 4 | + push: |
| 5 | + branches: [ main, master ] |
| 6 | + pull_request: |
| 7 | + branches: [ main, master ] |
| 8 | + |
| 9 | +jobs: |
| 10 | + version-number: |
| 11 | + runs-on: ubuntu-latest |
| 12 | + steps: |
| 13 | + - name: Set current date in UTC as env variable |
| 14 | + run: | |
| 15 | + export CURRENT_DATE="$(date -u +'%Y.%m.%d')" |
| 16 | + echo "Current date is ${CURRENT_DATE}" |
| 17 | + echo "CURRENT_DATE=${CURRENT_DATE}" >> $GITHUB_ENV |
| 18 | +
|
| 19 | + - id: build_version |
| 20 | + name: Generate Build Version |
| 21 | + run: | |
| 22 | + export BUILD_VERSION="$CURRENT_DATE.${{ github.run_number }}" |
| 23 | + echo "Build version is ${BUILD_VERSION}" |
| 24 | + echo "BUILD_VERSION=${BUILD_VERSION}" >> $GITHUB_OUTPUT |
| 25 | +
|
| 26 | + - id: package_version |
| 27 | + name: Generate Package Version |
| 28 | + run: | |
| 29 | + export PACKAGE_VERSION="$CURRENT_DATE-preview.${{ github.run_number }}" |
| 30 | + echo "Package version is ${PACKAGE_VERSION}" |
| 31 | + echo "PACKAGE_VERSION=${PACKAGE_VERSION}" >> $GITHUB_OUTPUT |
| 32 | + export PYTHON_PACKAGE_VERSION="$CURRENT_DATE+preview.${{ github.run_number }}" |
| 33 | + echo "Python package version is ${PYTHON_PACKAGE_VERSION}" |
| 34 | + echo "PYTHON_PACKAGE_VERSION=${PYTHON_PACKAGE_VERSION}" >> $GITHUB_OUTPUT |
| 35 | +
|
| 36 | + outputs: |
| 37 | + BUILD_VERSION: ${{ steps.build_version.outputs.BUILD_VERSION }} |
| 38 | + PACKAGE_VERSION: ${{ steps.package_version.outputs.PACKAGE_VERSION }} |
| 39 | + PYTHON_PACKAGE_VERSION: ${{ steps.package_version.outputs.PYTHON_PACKAGE_VERSION }} |
| 40 | + |
| 41 | + changed-sdks: |
| 42 | + name: Determine Changed SDKs |
| 43 | + runs-on: ubuntu-latest |
| 44 | + outputs: |
| 45 | + python-sdk: ${{ steps.check_python_sdk.outputs.changed }} |
| 46 | + nodejs-sdk: ${{ steps.check_nodejs_sdk.outputs.changed }} |
| 47 | + dotnet-sdk: ${{ steps.check_dotnet_sdk.outputs.changed }} |
| 48 | + steps: |
| 49 | + - name: Checkout repository |
| 50 | + uses: actions/checkout@v4 |
| 51 | + with: |
| 52 | + fetch-depth: 0 |
| 53 | + |
| 54 | + - id: git_refs |
| 55 | + name: Set Git refs for diff |
| 56 | + run: | |
| 57 | + if [[ "${{ github.event_name }}" == "pull_request" ]]; then |
| 58 | + echo "base=${{ github.event.pull_request.base.sha }}" >> "$GITHUB_OUTPUT" |
| 59 | + echo "head=${{ github.event.pull_request.head.sha }}" >> "$GITHUB_OUTPUT" |
| 60 | + else |
| 61 | + echo "base=${{ github.event.before }}" >> "$GITHUB_OUTPUT" |
| 62 | + echo "head=${{ github.sha }}" >> "$GITHUB_OUTPUT" |
| 63 | + fi |
| 64 | +
|
| 65 | + - id: check_python_sdk |
| 66 | + name: Check Python SDK changes |
| 67 | + run: | |
| 68 | + if git diff --name-only "${{ steps.git_refs.outputs.base }}" "${{ steps.git_refs.outputs.head }}" -- 'python/**' | grep -q .; then |
| 69 | + echo "Python SDK changes detected" |
| 70 | + echo "changed=true" >> $GITHUB_OUTPUT |
| 71 | + else |
| 72 | + echo "No Python SDK changes detected" |
| 73 | + echo "changed=false" >> $GITHUB_OUTPUT |
| 74 | + fi |
| 75 | +
|
| 76 | + - id: check_nodejs_sdk |
| 77 | + name: Check Node.js SDK changes |
| 78 | + run: | |
| 79 | + if git diff --name-only "${{ steps.git_refs.outputs.base }}" "${{ steps.git_refs.outputs.head }}" -- 'nodejs/**' | grep -q .; then |
| 80 | + echo "Node.js SDK changes detected" |
| 81 | + echo "changed=true" >> $GITHUB_OUTPUT |
| 82 | + else |
| 83 | + echo "No Node.js SDK changes detected" |
| 84 | + echo "changed=false" >> $GITHUB_OUTPUT |
| 85 | + fi |
| 86 | +
|
| 87 | + - id: check_dotnet_sdk |
| 88 | + name: Check .NET SDK changes |
| 89 | + run: | |
| 90 | + if git diff --name-only "${{ steps.git_refs.outputs.base }}" "${{ steps.git_refs.outputs.head }}" -- 'dotnet/**' | grep -q .; then |
| 91 | + echo ".NET SDK changes detected" |
| 92 | + echo "changed=true" >> $GITHUB_OUTPUT |
| 93 | + else |
| 94 | + echo "No .NET SDK changes detected" |
| 95 | + echo "changed=false" >> $GITHUB_OUTPUT |
| 96 | + fi |
| 97 | +
|
| 98 | + python-sdk: |
| 99 | + name: Python SDK |
| 100 | + needs: [version-number, changed-sdks] |
| 101 | + runs-on: ubuntu-latest |
| 102 | + defaults: |
| 103 | + run: |
| 104 | + working-directory: ./python |
| 105 | + |
| 106 | + strategy: |
| 107 | + matrix: |
| 108 | + python-version: ['3.11', '3.12'] |
| 109 | + |
| 110 | + steps: |
| 111 | + - name: Checkout repository |
| 112 | + uses: actions/checkout@v4 |
| 113 | + |
| 114 | + - name: Install the latest version of uv and set the python version |
| 115 | + uses: astral-sh/setup-uv@v6 |
| 116 | + with: |
| 117 | + version: '0.6.x' |
| 118 | + python-version: ${{ matrix.python-version }} |
| 119 | + working-directory: ./python |
| 120 | + enable-cache: true |
| 121 | + cache-dependency-glob: "./pyproject.toml" |
| 122 | + |
| 123 | + - name: Install the project |
| 124 | + run: uv lock && uv sync --locked --all-extras --dev |
| 125 | + |
| 126 | + - name: Check linting |
| 127 | + run: | |
| 128 | + uv run --frozen ruff check . |
| 129 | + continue-on-error: true |
| 130 | + |
| 131 | + - name: Check formatting |
| 132 | + run: | |
| 133 | + uv run --frozen ruff format --check . |
| 134 | +
|
| 135 | + - name: Build package |
| 136 | + run: | |
| 137 | + A365_SDK_VERSION=${{ needs.version-number.outputs.PYTHON_PACKAGE_VERSION }} uv build --all-packages --wheel |
| 138 | +
|
| 139 | + - name: Run tests |
| 140 | + run: | |
| 141 | + uv run --frozen python -m pytest tests/ -v --tb=short |
| 142 | +
|
| 143 | + # Copy package and samples to drop folder |
| 144 | + - name: Copy package and samples to drop folder |
| 145 | + run: | |
| 146 | + mkdir -p ~/drop/python-${{ matrix.python-version }}/dist && cp -v dist/*.whl $_ |
| 147 | + mkdir -p ~/drop/python-${{ matrix.python-version }}/samples && cp -rv samples/sample_openai_agent $_ |
| 148 | +
|
| 149 | + # Zip files since upload-artifact does not seem like to like folders |
| 150 | + - name: Create zip |
| 151 | + run: cd ~/drop/python-${{ matrix.python-version }} && zip -r ~/drop/python-${{ matrix.python-version }}.zip . |
| 152 | + |
| 153 | + - name: Upload package and samples as artifacts |
| 154 | + uses: actions/upload-artifact@v4 |
| 155 | + with: |
| 156 | + name: python-${{ matrix.python-version }} |
| 157 | + path: ~/drop/python-${{ matrix.python-version }}.zip |
| 158 | + |
| 159 | + - name: Publish |
| 160 | + if: github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.changed-sdks.outputs.python-sdk == 'true' |
| 161 | + run: | |
| 162 | + uv run twine upload --config-file .pypirc -r Agent365 dist/* |
| 163 | + continue-on-error: true |
| 164 | + env: |
| 165 | + TWINE_USERNAME: __token__ |
| 166 | + TWINE_PASSWORD: ${{ secrets.AZURE_DEVOPS_TOKEN }} |
| 167 | + |
| 168 | + nodejs-sdk: |
| 169 | + name: Node.js SDK |
| 170 | + runs-on: ubuntu-latest |
| 171 | + defaults: |
| 172 | + run: |
| 173 | + working-directory: ./nodejs/src |
| 174 | + |
| 175 | + strategy: |
| 176 | + matrix: |
| 177 | + node-version: ['18', '20'] |
| 178 | + |
| 179 | + steps: |
| 180 | + - name: Checkout repository |
| 181 | + uses: actions/checkout@v4 |
| 182 | + |
| 183 | + - name: Set up Node.js ${{ matrix.node-version }} |
| 184 | + uses: actions/setup-node@v4 |
| 185 | + with: |
| 186 | + node-version: ${{ matrix.node-version }} |
| 187 | + cache: 'npm' |
| 188 | + cache-dependency-path: '**/package-lock.json' |
| 189 | + |
| 190 | + - name: Install dependencies |
| 191 | + run: npm ci |
| 192 | + |
| 193 | + - name: Lint code |
| 194 | + run: npm run lint:all |
| 195 | + |
| 196 | + - name: Build package |
| 197 | + run: npm run build:all |
| 198 | + |
| 199 | + - name: Run tests |
| 200 | + run: npm test |
| 201 | + |
| 202 | + # - name: Publish to NPM (commented for now) |
| 203 | + # if: github.event_name == 'push' && github.ref == 'refs/heads/main' |
| 204 | + # run: npm publish |
| 205 | + # env: |
| 206 | + # NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} |
| 207 | + |
| 208 | + dotnet-sdk: |
| 209 | + name: .NET SDK |
| 210 | + needs: [version-number, changed-sdks] |
| 211 | + runs-on: ubuntu-latest |
| 212 | + defaults: |
| 213 | + run: |
| 214 | + working-directory: ./dotnet/sdk |
| 215 | + |
| 216 | + strategy: |
| 217 | + matrix: |
| 218 | + dotnet-version: ['8.0.x'] |
| 219 | + |
| 220 | + steps: |
| 221 | + - name: Checkout repository |
| 222 | + uses: actions/checkout@v4 |
| 223 | + |
| 224 | + - name: Setup .NET ${{ matrix.dotnet-version }} |
| 225 | + uses: actions/setup-dotnet@v4 |
| 226 | + with: |
| 227 | + dotnet-version: ${{ matrix.dotnet-version }} |
| 228 | + source-url: https://pkgs.dev.azure.com/msazure/OneAgile/_packaging/Agent365/nuget/v3/index.json |
| 229 | + env: |
| 230 | + NUGET_AUTH_TOKEN: ${{ secrets.AZURE_DEVOPS_TOKEN }} |
| 231 | + |
| 232 | + - name: Restore dependencies |
| 233 | + run: dotnet restore Microsoft.Kairo.Sdk.sln |
| 234 | + |
| 235 | + - name: Build solution |
| 236 | + run: dotnet build Microsoft.Kairo.Sdk.sln --no-restore --configuration Release /p:Version=${{ needs.version-number.outputs.BUILD_VERSION }} |
| 237 | + |
| 238 | + - name: Run tests |
| 239 | + run: dotnet test Microsoft.Kairo.Sdk.sln --no-build --configuration Release --verbosity normal |
| 240 | + |
| 241 | + - name: Pack NuGet packages |
| 242 | + run: dotnet pack Microsoft.Kairo.Sdk.sln --no-build --configuration Release --output ../NuGetPackages /p:PackageVersion=${{ needs.version-number.outputs.PACKAGE_VERSION }} |
| 243 | + |
| 244 | + # Copy samples to drop folder |
| 245 | + - name: Copy NuGet packages and samples to drop folder |
| 246 | + run: | |
| 247 | + mkdir -p ~/drop/dotnet/NuGetPackages && cp -v ../NuGetPackages/*.nupkg $_ |
| 248 | + mkdir -p ~/drop/dotnet/samples && cp -rv ../samples/hello_world_a365_agent $_ |
| 249 | + mkdir -p ~/drop/dotnet/samples && cp -rv ../samples/semantic-kernel-multiturn $_ |
| 250 | +
|
| 251 | + # Build samples that depend on the NuGet packages |
| 252 | + - name: Build HelloWorldA365Agent |
| 253 | + run: | |
| 254 | + dotnet build ../samples/hello_world_a365_agent/HelloWorldA365Agent.sln --configuration Release |
| 255 | +
|
| 256 | + - name: Build semantic-kernel-multiturn |
| 257 | + run: | |
| 258 | + dotnet build ../samples/semantic-kernel-multiturn/SemanticKernelMultiturn.csproj --configuration Release |
| 259 | +
|
| 260 | + # Zip files since upload-artifact does not seem like to like folders |
| 261 | + - name: Create zip |
| 262 | + run: cd ~/drop/dotnet && zip -r ~/drop/dotnet.zip . |
| 263 | + |
| 264 | + - name: Upload NuGet packages and samples as artifacts |
| 265 | + uses: actions/upload-artifact@v4 |
| 266 | + with: |
| 267 | + name: dotnet |
| 268 | + path: ~/drop/dotnet.zip |
| 269 | + |
| 270 | + - name: Publish |
| 271 | + if: github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.changed-sdks.outputs.dotnet-sdk == 'true' |
| 272 | + env: |
| 273 | + NUGET_AUTH_TOKEN: ${{ secrets.AZURE_DEVOPS_TOKEN }} |
| 274 | + run: dotnet nuget push ../NuGetPackages/*.nupkg --api-key AzureDevOps --source https://pkgs.dev.azure.com/msazure/OneAgile/_packaging/Agent365/nuget/v3/index.json |
| 275 | + |
| 276 | + dotnet-samples: |
| 277 | + name: .NET Samples |
| 278 | + runs-on: ubuntu-latest |
| 279 | + defaults: |
| 280 | + run: |
| 281 | + working-directory: ./dotnet/samples/ |
| 282 | + |
| 283 | + steps: |
| 284 | + - name: Checkout repository |
| 285 | + uses: actions/checkout@v4 |
| 286 | + |
| 287 | + - name: Setup .NET 9 |
| 288 | + uses: actions/setup-dotnet@v4 |
| 289 | + with: |
| 290 | + dotnet-version: '9.0.x' |
| 291 | + |
| 292 | + - name: Build basic_agent (KairoSample) |
| 293 | + run: | |
| 294 | + dotnet build basic_agent/KairoSample.sln --configuration Release |
| 295 | +
|
| 296 | + - name: Build devin_agent (Devin AI PoC) |
| 297 | + run: | |
| 298 | + dotnet build devin_agent/devin-ai-poc.sln --configuration Release |
0 commit comments