name: UniLabOS Conda Build on: # 在 CI Check 成功后自动触发 workflow_run: workflows: ["CI Check"] types: [completed] branches: [main, dev] # 标签推送时直接触发(发布版本) push: tags: ['v*'] # 手动触发 workflow_dispatch: inputs: platforms: description: '选择构建平台 (逗号分隔): linux-64, osx-64, osx-arm64, win-64' required: false default: 'linux-64' build_full: description: '是否构建 unilabos-full 完整包 (默认只构建 unilabos 基础包)' required: false default: false type: boolean upload_to_anaconda: description: '是否上传到Anaconda.org' required: false default: false type: boolean skip_ci_check: description: '跳过等待 CI Check (手动触发时可选)' required: false default: false type: boolean jobs: # 等待 CI Check 完成的 job (仅用于 workflow_run 触发) wait-for-ci: runs-on: ubuntu-latest if: github.event_name == 'workflow_run' outputs: should_continue: ${{ steps.check.outputs.should_continue }} steps: - name: Check CI status id: check run: | if [[ "${{ github.event.workflow_run.conclusion }}" == "success" ]]; then echo "should_continue=true" >> $GITHUB_OUTPUT echo "CI Check passed, proceeding with build" else echo "should_continue=false" >> $GITHUB_OUTPUT echo "CI Check did not succeed (status: ${{ github.event.workflow_run.conclusion }}), skipping build" fi build: needs: [wait-for-ci] # 运行条件:workflow_run 触发且 CI 成功,或者其他触发方式 if: | always() && (needs.wait-for-ci.result == 'skipped' || needs.wait-for-ci.outputs.should_continue == 'true') strategy: fail-fast: false matrix: include: - os: ubuntu-latest platform: linux-64 - os: macos-15 # Intel (via Rosetta) platform: osx-64 - os: macos-latest # ARM64 platform: osx-arm64 - os: windows-latest platform: win-64 runs-on: ${{ matrix.os }} defaults: run: shell: bash -l {0} steps: - uses: actions/checkout@v6 with: # 如果是 workflow_run 触发,使用触发 CI Check 的 commit ref: ${{ github.event.workflow_run.head_sha || github.ref }} fetch-depth: 0 - name: Check if platform should be built id: should_build run: | if [[ "${{ github.event_name }}" != "workflow_dispatch" ]]; then echo "should_build=true" >> $GITHUB_OUTPUT elif [[ -z "${{ github.event.inputs.platforms }}" ]]; then echo "should_build=true" >> $GITHUB_OUTPUT elif [[ "${{ github.event.inputs.platforms }}" == *"${{ matrix.platform }}"* ]]; then echo "should_build=true" >> $GITHUB_OUTPUT else echo "should_build=false" >> $GITHUB_OUTPUT fi - name: Setup Miniconda if: steps.should_build.outputs.should_build == 'true' uses: conda-incubator/setup-miniconda@v3 with: miniconda-version: 'latest' channels: conda-forge,robostack-staging,uni-lab,defaults channel-priority: strict activate-environment: build-env auto-update-conda: false show-channel-urls: true - name: Install rattler-build and anaconda-client if: steps.should_build.outputs.should_build == 'true' run: | conda install -c conda-forge rattler-build anaconda-client - name: Show environment info if: steps.should_build.outputs.should_build == 'true' run: | conda info conda list | grep -E "(rattler-build|anaconda-client)" echo "Platform: ${{ matrix.platform }}" echo "OS: ${{ matrix.os }}" echo "Build full package: ${{ github.event.inputs.build_full || 'false' }}" echo "Building packages:" echo " - unilabos-env (environment dependencies)" echo " - unilabos (with pip package)" if [[ "${{ github.event.inputs.build_full }}" == "true" ]]; then echo " - unilabos-full (complete package)" fi - name: Build unilabos-env (conda environment only, noarch) if: steps.should_build.outputs.should_build == 'true' run: | echo "Building unilabos-env (conda environment dependencies)..." rattler-build build -r .conda/environment/recipe.yaml -c uni-lab -c robostack-staging -c conda-forge - name: Build unilabos (with pip package) if: steps.should_build.outputs.should_build == 'true' run: | echo "Building unilabos package..." rattler-build build -r .conda/base/recipe.yaml -c uni-lab -c robostack-staging -c conda-forge --channel ./output - name: Build unilabos-full - Only when explicitly requested if: | steps.should_build.outputs.should_build == 'true' && github.event.inputs.build_full == 'true' run: | echo "Building unilabos-full package on ${{ matrix.platform }}..." rattler-build build -r .conda/full/recipe.yaml -c uni-lab -c robostack-staging -c conda-forge --channel ./output - name: List built packages if: steps.should_build.outputs.should_build == 'true' run: | echo "Built packages in output directory:" find ./output -name "*.conda" | head -10 ls -la ./output/${{ matrix.platform }}/ || echo "${{ matrix.platform }} directory not found" ls -la ./output/noarch/ || echo "noarch directory not found" echo "Output directory structure:" find ./output -type f -name "*.conda" - name: Prepare artifacts for upload if: steps.should_build.outputs.should_build == 'true' run: | mkdir -p conda-packages-temp find ./output -name "*.conda" -exec cp {} conda-packages-temp/ \; echo "Copied files to temp directory:" ls -la conda-packages-temp/ - name: Upload conda package artifacts if: steps.should_build.outputs.should_build == 'true' uses: actions/upload-artifact@v6 with: name: conda-package-unilabos-${{ matrix.platform }} path: conda-packages-temp if-no-files-found: warn retention-days: 30 - name: Upload to Anaconda.org (uni-lab organization) if: github.event.inputs.upload_to_anaconda == 'true' run: | for package in $(find ./output -name "*.conda"); do echo "Uploading $package to uni-lab organization..." anaconda -t ${{ secrets.ANACONDA_API_TOKEN }} upload --user uni-lab --force "$package" done