name: Development Build on: workflow_dispatch: inputs: release-new-build: type: boolean default: false description: 'Release new dev build' required: true jobs: pre-release: name: Development Build runs-on: macos-26 permissions: contents: write pull-requests: write steps: - name: โฌ‡๏ธ Checkout repository uses: actions/checkout@v5 with: fetch-depth: 0 - name: ๐Ÿงช Set Version and Build number run: | # CHANGE EVERY RELEASE: APP_VERSION="๐Ÿงช 1.4.3" APP_BUILD=$(git rev-list --count HEAD) FROM_TAG=$(git describe --tags --abbrev=0 --exclude='prerelease') # Set VERSION latest_tag=$APP_VERSION echo "Latest tag: $latest_tag" sed -i -e "/VERSION =/ s/= .*/= $latest_tag/" Loop/Config.xcconfig # Set BUILD_NUMBER latest_commit_number=$APP_BUILD echo "Latest commit number: $latest_commit_number" sed -i -e "/BUILD_NUMBER =/ s/= .*/= $latest_commit_number/" Loop/Config.xcconfig echo "APP_VERSION=$APP_VERSION" >> $GITHUB_ENV echo "APP_BUILD=$APP_BUILD" >> $GITHUB_ENV echo "FROM_TAG=$FROM_TAG" >> $GITHUB_ENV - name: ๐Ÿ”ง Select Xcode run: sudo xcode-select -s "/Applications/Xcode_26.2.app" - name: ๐ŸŽŸ๏ธ Install Development & Developer ID Certificate env: DEVELOPMENT_CERT_BASE64: ${{ secrets.DEVELOPMENT_CERT_BASE64 }} DEVELOPER_ID_CERT_BASE64: ${{ secrets.DEVELOPER_ID_CERT_BASE64 }} P12_PASSWORD: ${{ secrets.P12_PASSWORD }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | DEVELOPMENT_CERT_PATH=$RUNNER_TEMP/dev.p12 DEVELOPER_ID_CERT_PATH=$RUNNER_TEMP/devid.p12 KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db echo -n "$DEVELOPMENT_CERT_BASE64" | base64 --decode -o $DEVELOPMENT_CERT_PATH echo -n "$DEVELOPER_ID_CERT_BASE64" | base64 --decode -o $DEVELOPER_ID_CERT_PATH security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH security set-keychain-settings -lut 21600 $KEYCHAIN_PATH security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH security import $DEVELOPMENT_CERT_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH security import $DEVELOPER_ID_CERT_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH security list-keychain -d user -s $KEYCHAIN_PATH - name: ๐ŸŽŸ๏ธ Install Provision Profile if: false env: PROVISION_PROFILE_BASE64: ${{ secrets.PROVISION_PROFILE_BASE64 }} run: | PP_PATH=$RUNNER_TEMP/Loop.provisionprofile echo -n "$PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles - name: ๐Ÿ› ๏ธ Build Loop run: | set -o pipefail && xcodebuild \ archive \ -project Loop.xcodeproj/ \ -scheme "Loop (GH ACTIONS)" \ -destination 'generic/platform=macOS' \ -archivePath dist/Loop.xcarchive \ -allowProvisioningUpdates \ -skipMacroValidation \ -skipPackagePluginValidation \ -showBuildTimingSummary \ | xcbeautify - name: ๐Ÿฅก Export Loop.app run: | xcodebuild \ -exportArchive \ -archivePath dist/Loop.xcarchive \ -exportPath dist/ \ -exportOptionsPlist assets/ExportOptions.plist \ -allowProvisioningUpdates - name: ๐Ÿค Compress Loop for notarization run: | ditto -c -k --sequesterRsrc --keepParent "dist/Loop.app" "dist/Loop.zip" - name: โœ… Notarize Loop env: APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_ID_PWD: ${{ secrets.APPLE_ID_PWD }} run: | xcrun notarytool store-credentials Loop --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM_ID" --password "$APPLE_ID_PWD" xcrun notarytool submit "dist/Loop.zip" --keychain-profile "Loop" --wait xcrun stapler staple "dist/Loop.app" - name: ๐Ÿค Compress notarized Loop run: | rm dist/Loop.zip ditto -c -k --sequesterRsrc --keepParent "dist/Loop.app" "dist/Loop.zip" - name: โฌ†๏ธ Upload Loop uses: actions/upload-artifact@v4 with: name: Loop path: dist/Loop.zip - name: ๐Ÿ’ฌ Comment on PR with build link if: "${{ !inputs.release-new-build }}" uses: actions/github-script@v7 with: script: | const branch = context.ref.replace('refs/heads/', ''); // Find PRs for this branch const { data: pulls } = await github.rest.pulls.list({ owner: context.repo.owner, repo: context.repo.repo, head: `${context.repo.owner}:${branch}` }); if (pulls.length === 0) { console.log(`No open PR found for branch: ${branch}`); return; } const pr = pulls[0]; const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; const body = [ '๐Ÿšง **Development Build Finished**', '', `- Version: ${process.env.APP_VERSION} (${process.env.APP_BUILD})`, `- Workflow: [View build logs & artifacts](${runUrl})` ].join('\n'); await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: pr.number, body }); console.log(`Commented on PR #${pr.number}`); - name: ๐Ÿท๏ธ Create/update tag uses: actions/github-script@v7 if: "${{ inputs.release-new-build }}" with: script: | github.rest.git.createRef({ owner: context.repo.owner, repo: context.repo.repo, ref: 'refs/tags/prerelease', sha: context.sha }).catch(err => { if (err.status !== 422) throw err; github.rest.git.updateRef({ owner: context.repo.owner, repo: context.repo.repo, ref: 'tags/prerelease', sha: context.sha }); }) - name: ๐Ÿ“ฐ Build Changelog uses: mikepenz/release-changelog-builder-action@v4 if: "${{ inputs.release-new-build }}" with: outputFile: CHANGELOG.md fromTag: ${{ env.FROM_TAG }} toTag: "prerelease" configurationJson: | { "template": "## ๐Ÿ“ฐ Development News\n- ๐Ÿ’ธ Support Loop by [sponsoring the project](https://github.com/sponsors/MrKai77)!\n- ๐ŸŒ Let us know if you are interested in localizing Loop to your language :)\n- ๐Ÿ’ฌ Join our [Discord server](https://discord.gg/2CZ2N6PKjq)!\n#{{CHANGELOG}}\n## ๐Ÿ’ญ Uncategorized\n#{{UNCATEGORIZED}}\n---\nMinimum macOS version: 13.0", "pr_template": "- #{{TITLE}} ##{{NUMBER}}", "categories": [ { "title": "## โœจ New Features", "labels": ["Feature", "Luminare", "Improvement"] }, { "title": "## ๐Ÿž Bug Fixes", "labels": ["Bug"] }, { "title": "## ๐ŸŒ Localization", "labels": ["Localization"] } ], "empty_template": "- โŒ No changes found" } env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: ๐Ÿฅณ Publish Dev Build uses: ncipollo/release-action@v1 if: "${{ inputs.release-new-build }}" with: allowUpdates: true artifacts: dist/Loop.zip commit: develop bodyFile: CHANGELOG.md name: "${{ env.APP_VERSION }} (${{ env.APP_BUILD }})" prerelease: true tag: "prerelease" - name: ๐Ÿงน Cleanup run: | security delete-keychain "$RUNNER_TEMP/app-signing.keychain-db"