name: Build Release on: release: types: [created] schedule: - cron: "0 0 * * 3" workflow_dispatch: permissions: contents: write actions: write jobs: upload_src: runs-on: ubuntu-latest outputs: build_tag: ${{ steps.get_tag.outputs.build_tag }} steps: - name: Harden the runner (Audit all outbound calls) uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 with: egress-policy: audit - name: Checkout Source uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.sha }} fetch-depth: 2 fetch-tags: true submodules: 'recursive' - name: get tag and create release if weekly id: get_tag shell: bash -l {0} env: GH_TOKEN: ${{ github.token }} run: | if [ "${{ github.event_name }}" = "release" ]; then export BUILD_TAG="${{ github.event.release.tag_name }}" else export BUILD_TAG=weekly-$(date "+%Y.%m.%d") gh release create ${BUILD_TAG} --title "Development Build ${BUILD_TAG}" -F .github/workflows/weekly-build-notes.md --prerelease || true fi echo "BUILD_TAG=${BUILD_TAG}" >> "$GITHUB_ENV" echo "build_tag=${BUILD_TAG}" >> "$GITHUB_OUTPUT" - name: Trigger notes updater workflow (only for weekly) if: startsWith(steps.get_tag.outputs.build_tag, 'weekly-') uses: actions/github-script@v7 env: WEEKLY_TAG: ${{ steps.get_tag.outputs.build_tag }} with: script: | const owner = context.repo.owner; const repo = context.repo.repo; // Reusable/dispatchable updater workflow file in .github/workflows/ const workflow_id = 'weekly-compare-link.yml'; // Use the default branch so the workflow file is available const ref = (context.payload?.repository?.default_branch) || 'main'; const current_tag = process.env.WEEKLY_TAG || ''; await github.rest.actions.createWorkflowDispatch({ owner, repo, workflow_id, ref, inputs: { current_tag } }); core.info(`Dispatched ${workflow_id} on ${ref} with current_tag='${current_tag}'.`) - name: Upload Source id: upload_source shell: bash -l {0} env: GH_TOKEN: ${{ github.token }} run: | python3 package/scripts/write_version_info.py ../freecad_version.txt git config user.email '41898282+github-actions[bot]@users.noreply.github.com' git config user.name 'github-actions[bot]' git apply package/disable_git_info.patch git commit -a -m "Disable git info write to Version.h" git archive HEAD -o freecad_source_${BUILD_TAG}.tar git submodule foreach --recursive \ "git archive HEAD --prefix=\$path/ -o \$sha1.tar && \ tar -A -f \$toplevel/freecad_source_${BUILD_TAG}.tar \$sha1.tar && \ rm \$sha1.tar" gzip freecad_source_${BUILD_TAG}.tar sha256sum freecad_source_${BUILD_TAG}.tar.gz > freecad_source_${BUILD_TAG}.tar.gz-SHA256.txt gh release upload --clobber ${BUILD_TAG} "freecad_source_${BUILD_TAG}.tar.gz" "freecad_source_${BUILD_TAG}.tar.gz-SHA256.txt" build: needs: upload_src strategy: matrix: include: - { target: linux-64, os: ubuntu-22.04 } - { target: linux-arm64, os: ubuntu-22.04-arm } - { target: osx-64, os: macos-15-intel, deploy_target: "10.13" } - { target: osx-arm64, os: macos-latest, deploy_target: "11.0" } - { target: osx-arm64, os: macos-latest, deploy_target: "15.0" } - { target: win-64, os: windows-latest } fail-fast: false runs-on: ${{ matrix.os }} environment: weekly-build steps: - name: Harden the runner (Audit all outbound calls) uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 with: egress-policy: audit # prevent running out of disk space on Ubuntu runners. - name: Maximize build space if: runner.os == 'Linux' uses: AdityaGarg8/remove-unwanted-software@90e01b21170618765a73370fcc3abbd1684a7793 # v5 with: verbose: 'true' remove-android: 'true' # (frees ~9 GB) remove-cached-tools: 'true' # (frees ~8.3 GB) - name: Set Platform Environment Variables shell: bash -l {0} env: OPERATING_SYSTEM: ${{ runner.os }} run: | if [[ $OPERATING_SYSTEM == 'Windows' ]]; then echo 'PIXI_CACHE_DIR=D:\rattler' >> "$GITHUB_ENV" echo 'RATTLER_CACHE_DIR=D:\rattler' >> "$GITHUB_ENV" fi - name: Checkout Source uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.sha }} fetch-depth: 2 fetch-tags: true submodules: 'recursive' - uses: prefix-dev/setup-pixi@a0af7a228712d6121d37aba47adf55c1332c9c2e # v0.9.4 with: pixi-version: v0.59.0 cache: false - name: Install the Apple certificate and provisioning profile id: get_cert if: runner.os == 'macOS' env: APP_SPECIFIC_PASSWORD: ${{ secrets.APP_SPECIFIC_PASSWORD }} APPLE_ID: ${{ secrets.APPLE_ID }} BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }} DEVELOPER_TEAM_ID: ${{ secrets.DEVELOPER_TEAM_ID }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} P12_PASSWORD: ${{ secrets.P12_PASSWORD }} run: | if [ -z "$BUILD_CERTIFICATE_BASE64" ]; then echo "has_cert=false" >> $GITHUB_OUTPUT echo "No certificate avalable... skipping" && exit 0 else echo "has_cert=true" >> $GITHUB_OUTPUT fi # create variables CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 PP_PATH=$RUNNER_TEMP/FreeCAD_bundle.provisionprofile KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db export KEYCHAIN_PASSWORD=$(openssl rand -base64 8) # import certificate and provisioning profile from secrets echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH # create temporary keychain security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH security set-keychain-settings -lut 21600 $KEYCHAIN_PATH security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH # import certificate to keychain security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH security list-keychain -d user -s $KEYCHAIN_PATH # apply provisioning profile mkdir -p ~/Library/Provisioning\ Profiles cp $PP_PATH ~/Library/Provisioning\ Profiles xcrun notarytool store-credentials "FreeCAD" --keychain "$KEYCHAIN_PATH" --apple-id "${APPLE_ID}" --password "${APP_SPECIFIC_PASSWORD}" --team-id "${DEVELOPER_TEAM_ID}" - name: Build and Release Packages shell: bash env: GH_TOKEN: ${{ github.token }} SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }} SIGN_RELEASE: ${{ steps.get_cert.outputs.has_cert }} TARGET_PLATFORM: ${{ matrix.target }} MAKE_INSTALLER: "true" UPLOAD_RELEASE: "true" BUILD_TAG: ${{ needs.upload_src.outputs.build_tag }} run: | if [[ "${{ runner.os }}" == "macOS" ]]; then export MACOS_DEPLOYMENT_TARGET="${{ matrix.deploy_target }}" fi python3 package/scripts/write_version_info.py ../freecad_version.txt cd package/rattler-build pixi install pixi run -e package create_bundle ## Needed if running on a self-hosted runner: # - name: Clean up keychain and provisioning profile # if: ${{ always() }} # run: | # security delete-keychain $RUNNER_TEMP/app-signing.keychain-db # rm ~/Library/MobileDevice/Provisioning\ Profiles/build_pp.mobileprovision