main.yml 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. name: 'BUILD'
  2. on:
  3. push:
  4. paths-ignore: ['**.md']
  5. branches:
  6. - master
  7. - 'release/**'
  8. tags: ['*']
  9. pull_request:
  10. paths-ignore: ['**.md']
  11. branches: [master]
  12. merge_group:
  13. branches: [master]
  14. env:
  15. CACHE_REVISION: '006'
  16. CEF_BUILD_VERSION_LINUX: '5060'
  17. CEF_BUILD_VERSION_WIN: '5060'
  18. QT_VERSION_MAC: '6.4.3'
  19. QT_VERSION_WIN: '6.4.3'
  20. DEPS_VERSION_WIN: '2023-06-01'
  21. VLC_VERSION_WIN: '3.0.0-git'
  22. TWITCH_CLIENTID: ${{ secrets.TWITCH_CLIENT_ID }}
  23. TWITCH_HASH: ${{ secrets.TWITCH_HASH }}
  24. RESTREAM_CLIENTID: ${{ secrets.RESTREAM_CLIENTID }}
  25. RESTREAM_HASH: ${{ secrets.RESTREAM_HASH }}
  26. YOUTUBE_CLIENTID: ${{ secrets.YOUTUBE_CLIENTID }}
  27. YOUTUBE_CLIENTID_HASH: ${{ secrets.YOUTUBE_CLIENTID_HASH }}
  28. YOUTUBE_SECRET: ${{ secrets.YOUTUBE_SECRET }}
  29. YOUTUBE_SECRET_HASH: ${{ secrets.YOUTUBE_SECRET_HASH }}
  30. GPU_PRIORITY_VAL: ${{ secrets.GPU_PRIORITY_VAL }}
  31. concurrency:
  32. group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
  33. cancel-in-progress: true
  34. jobs:
  35. clang_check:
  36. name: '01 - Code Format Check'
  37. runs-on: [ubuntu-22.04]
  38. steps:
  39. - name: 'Checkout'
  40. uses: actions/checkout@v3
  41. with:
  42. submodules: 'recursive'
  43. - name: 'Install clang-format'
  44. run: sudo apt-get install -y clang-format-13
  45. - name: 'Run clang-format'
  46. run: |
  47. ./CI/check-format.sh
  48. ./CI/check-changes.sh
  49. - name: 'Install cmake-format'
  50. run: sudo pip install cmakelang
  51. - name: 'Run cmake-format'
  52. run: |
  53. ./CI/check-cmake.sh
  54. - name: 'Run format-manifest.py'
  55. run: |
  56. python3 ./build-aux/format-manifest.py
  57. ./CI/check-changes.sh
  58. config:
  59. name: '01 - Configure Build Jobs'
  60. runs-on: [ubuntu-22.04]
  61. outputs:
  62. create_artifacts: ${{ steps.config.outputs.create_artifacts }}
  63. cache_date: ${{ steps.config.outputs.cache_date }}
  64. steps:
  65. - name: 'Configure Build Jobs'
  66. id: config
  67. run: |
  68. if [[ "${{ github.event_name == 'pull_request' }}" == "true" ]]; then
  69. if test -n "$(curl -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -s "${{ github.event.pull_request.url }}" | jq -e '.labels[] | select(.name == "Seeking Testers")')"; then
  70. echo 'create_artifacts=true' >> $GITHUB_OUTPUT
  71. else
  72. echo 'create_artifacts=false' >> $GITHUB_OUTPUT
  73. fi
  74. else
  75. echo 'create_artifacts=true' >> $GITHUB_OUTPUT
  76. fi
  77. echo "cache_date=$(date +"%Y-%m-%d")" >> $GITHUB_OUTPUT
  78. macos_build:
  79. name: '02 - macOS'
  80. runs-on: [macos-12]
  81. strategy:
  82. matrix:
  83. arch: ['x86_64', 'arm64']
  84. if: always()
  85. needs: [config, clang_check]
  86. env:
  87. BLOCKED_FORMULAS: 'speexdsp curl php composer'
  88. defaults:
  89. run:
  90. shell: bash
  91. working-directory: 'obs-studio'
  92. steps:
  93. - name: 'Checkout'
  94. uses: actions/checkout@v3
  95. with:
  96. submodules: 'recursive'
  97. path: 'obs-studio'
  98. fetch-depth: 0
  99. - name: 'Check for GitHub Labels'
  100. id: github-check
  101. run: |
  102. if [[ "${GITHUB_EVENT_NAME}" == 'pull_request' ]]; then
  103. if test -n "$(curl -H "Authorization: Bearer ${{ github.token }}" -s "${{ github.event.pull_request.url }}" | jq -e '.labels[] | select(.name == "Seeking Testers")')"; then
  104. echo "generator=Xcode" >> $GITHUB_OUTPUT
  105. else
  106. echo "generator=Ninja" >> $GITHUB_OUTPUT
  107. fi
  108. elif [[ "${GITHUB_EVENT_NAME}" == 'push' ]]; then
  109. if [[ ${GITHUB_REF_NAME} =~ [0-9]+.[0-9]+.[0-9]+(-(rc|beta).+)? ]]; then
  110. echo "generator=Xcode" >> $GITHUB_OUTPUT
  111. else
  112. echo "generator=Ninja" >> $GITHUB_OUTPUT
  113. fi
  114. else
  115. echo "generator=Ninja" >> $GITHUB_OUTPUT
  116. fi
  117. - name: 'Restore ccache from cache'
  118. id: ccache-cache
  119. uses: actions/cache@v3
  120. with:
  121. path: ${{ github.workspace }}/.ccache
  122. key: ${{ runner.os }}-ccache-${{ steps.github-check.outputs.generator }}-${{ matrix.arch }}-${{ github.event_name }}-${{ github.head_ref }}
  123. restore-keys: |
  124. ${{ runner.os }}-ccache-${{ steps.github-check.outputs.generator }}-${{ matrix.arch }}-push-
  125. - name: 'Setup build environment'
  126. id: setup
  127. run: |
  128. REMOVE_FORMULAS=""
  129. for FORMULA in ${{ env.BLOCKED_FORMULAS }}; do
  130. if [ -d "/usr/local/opt/${FORMULA}" ]; then
  131. REMOVE_FORMULAS="${REMOVE_FORMULAS}${FORMULA} "
  132. fi
  133. done
  134. if [ -n "${REMOVE_FORMULAS}" ]; then
  135. brew uninstall ${REMOVE_FORMULAS}
  136. fi
  137. echo "commitHash=$(git rev-parse --short=9 HEAD)" >> $GITHUB_OUTPUT
  138. - name: 'Install dependencies'
  139. run: CI/macos/01_install_dependencies.sh --architecture "${{ matrix.arch }}"
  140. - name: 'Install Apple Developer Certificate'
  141. id: macos-codesign
  142. env:
  143. MACOS_SIGNING_IDENTITY: ${{ secrets.MACOS_SIGNING_IDENTITY }}
  144. MACOS_SIGNING_CERT: ${{ secrets.MACOS_SIGNING_CERT }}
  145. MACOS_SIGNING_CERT_PASSWORD: ${{ secrets.MACOS_SIGNING_CERT_PASSWORD }}
  146. MACOS_KEYCHAIN_PASSWORD: ${{ secrets.MACOS_KEYCHAIN_PASSWORD }}
  147. MACOS_PROVISIONING_PROFILE: ${{ secrets.MACOS_SIGNING_PROVISIONING_PROFILE }}
  148. run: |
  149. if [[ "${MACOS_SIGNING_IDENTITY}" && "${MACOS_SIGNING_CERT}" ]]; then
  150. CERTIFICATE_PATH="${RUNNER_TEMP}/build_certificate.p12"
  151. KEYCHAIN_PATH="${RUNNER_TEMP}/app-signing.keychain-db"
  152. echo -n "${MACOS_SIGNING_CERT}" | base64 --decode --output "${CERTIFICATE_PATH}"
  153. : "${MACOS_KEYCHAIN_PASSWORD:="$(echo ${RANDOM} | sha1sum | head -c 32)"}"
  154. security create-keychain -p "${MACOS_KEYCHAIN_PASSWORD}" "${KEYCHAIN_PATH}"
  155. security set-keychain-settings -lut 21600 "${KEYCHAIN_PATH}"
  156. security unlock-keychain -p "${MACOS_KEYCHAIN_PASSWORD}" "${KEYCHAIN_PATH}"
  157. security import "${CERTIFICATE_PATH}" -P "${MACOS_SIGNING_CERT_PASSWORD}" -A \
  158. -t cert -f pkcs12 -k "${KEYCHAIN_PATH}" \
  159. -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/xcrun
  160. security set-key-partition-list -S 'apple-tool:,apple:' -k "${MACOS_KEYCHAIN_PASSWORD}" \
  161. "${KEYCHAIN_PATH}" &> /dev/null
  162. security list-keychain -d user -s "${KEYCHAIN_PATH}" 'login-keychain'
  163. echo "CODESIGN_IDENT=${MACOS_SIGNING_IDENTITY}" >> $GITHUB_ENV
  164. echo "MACOS_KEYCHAIN_PASSWORD=${MACOS_KEYCHAIN_PASSWORD}" >> $GITHUB_ENV
  165. echo "haveCodesignIdent=true" >> $GITHUB_OUTPUT
  166. else
  167. echo "CODESIGN_IDENT=-" >> $GITHUB_ENV
  168. echo "haveCodesignIdent=false" >> $GITHUB_OUTPUT
  169. fi
  170. if [[ "${MACOS_PROVISIONING_PROFILE}" ]]; then
  171. PROFILE_PATH="${RUNNER_TEMP}/build_profile.provisionprofile"
  172. echo -n "${MACOS_PROVISIONING_PROFILE}" | base64 --decode --output "${PROFILE_PATH}"
  173. mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
  174. security cms -D -i "${PROFILE_PATH}" -o "${RUNNER_TEMP}/build_profile.plist"
  175. UUID="$(plutil -extract UUID raw "${RUNNER_TEMP}/build_profile.plist")"
  176. TEAM_ID="$(plutil -extract TeamIdentifier.0 raw -expect string "${RUNNER_TEMP}/build_profile.plist")"
  177. cp "${PROFILE_PATH}" ~/Library/MobileDevice/Provisioning\ Profiles/${UUID}.provisionprofile
  178. echo "provisionprofileUUID=${UUID}" >> $GITHUB_OUTPUT
  179. echo "haveProvisioningProfile=true" >> $GITHUB_OUTPUT
  180. echo "CODESIGN_TEAM=${TEAM_ID}" >> $GITHUB_ENV
  181. else
  182. echo "haveProvisioningProfile=false" >> $GITHUB_OUTPUT
  183. fi
  184. if [[ "${MACOS_NOTARIZATION_USERNAME}" && "${MACOS_NOTARIZATION_PASSWORD}" ]]; then
  185. echo "haveNotarizationUser=true" >> $GITHUB_OUTPUT
  186. else
  187. echo "haveNotarizationUser=false" >> $GITHUB_OUTPUT
  188. fi
  189. - name: 'Build OBS'
  190. env:
  191. PROVISIONING_PROFILE: ${{ steps.macos-codesign.outputs.provisionprofileUUID }}
  192. run: |
  193. if [[ '${{ steps.github-check.outputs.generator }}' == 'Xcode' ]]; then
  194. SEEKING_TESTERS=1 CI/macos/02_build_obs.sh --codesign --architecture "${{ matrix.arch }}"
  195. else
  196. CI/macos/02_build_obs.sh --codesign --architecture "${{ matrix.arch }}"
  197. fi
  198. - name: 'Create build artifact'
  199. if: ${{ fromJSON(needs.config.outputs.create_artifacts) }}
  200. run: |
  201. : ${PACKAGE:=}
  202. case "${GITHUB_EVENT_NAME}" in
  203. push) if [[ ${GITHUB_REF_NAME} =~ [0-9]+.[0-9]+.[0-9]+(-(rc|beta).+)? ]]; then PACKAGE=1; fi ;;
  204. pull_request) PACKAGE=1 ;;
  205. esac
  206. if [[ "${PACKAGE}" ]]; then
  207. CI/macos/03_package_obs.sh --codesign --architecture "${{ matrix.arch }}"
  208. ARTIFACT_NAME=$(basename $(/usr/bin/find build_${{ matrix.arch }} -type f -name "obs-studio-*.dmg" -depth 1 | head -1))
  209. echo "FILE_NAME=${ARTIFACT_NAME}" >> $GITHUB_ENV
  210. fi
  211. - name: 'Upload build Artifact'
  212. if: ${{ fromJSON(needs.config.outputs.create_artifacts) && env.FILE_NAME != '' }}
  213. uses: actions/upload-artifact@v3
  214. with:
  215. name: 'obs-studio-macos-${{ matrix.arch }}-${{ steps.setup.outputs.commitHash }}'
  216. path: '${{ github.workspace }}/obs-studio/build_${{ matrix.arch }}/${{ env.FILE_NAME }}'
  217. linux_build:
  218. name: '02 - Linux'
  219. runs-on: ${{ matrix.ubuntu }}
  220. strategy:
  221. matrix:
  222. ubuntu: ['ubuntu-20.04', 'ubuntu-22.04']
  223. include:
  224. - ubuntu: 'ubuntu-20.04'
  225. script_options: '--disable-pipewire'
  226. if: always()
  227. needs: [config, clang_check]
  228. defaults:
  229. run:
  230. shell: bash
  231. working-directory: 'obs-studio'
  232. env:
  233. BUILD_FOR_DISTRIBUTION: ${{ startsWith(github.ref, 'refs/tags/') && github.event_name != 'pull_request' }}
  234. steps:
  235. - name: 'Checkout'
  236. uses: actions/checkout@v3
  237. with:
  238. submodules: 'recursive'
  239. path: 'obs-studio'
  240. fetch-depth: 0
  241. - name: 'Restore ccache from cache'
  242. id: ccache-cache
  243. uses: actions/cache@v3
  244. env:
  245. CACHE_NAME: 'ccache-cache'
  246. with:
  247. path: ${{ github.workspace }}/.ccache
  248. key: ${{ runner.os }}-ccache-${{ matrix.ubuntu }}-${{ github.event_name }}-${{ github.head_ref }}
  249. restore-keys: |
  250. ${{ runner.os }}-ccache-${{ matrix.ubuntu }}-push-
  251. - name: 'Restore Chromium Embedded Framework from cache'
  252. id: cef-cache
  253. uses: actions/cache@v3
  254. env:
  255. CACHE_NAME: 'cef-cache'
  256. with:
  257. path: ${{ github.workspace }}/obs-build-dependencies/cef_binary_${{ env.CEF_BUILD_VERSION_LINUX }}_linux64
  258. key: ${{ runner.os }}-pr-${{ env.CACHE_NAME }}-${{ env.CEF_BUILD_VERSION_LINUX }}-${{ env.CACHE_REVISION }}
  259. - name: 'Setup build environment'
  260. id: setup
  261. run: |
  262. echo "commitHash=$(git rev-parse --short=9 HEAD)" >> $GITHUB_OUTPUT
  263. - name: 'Install dependencies'
  264. env:
  265. RESTORED_CEF: ${{ steps.cef-cache.outputs.cache-hit }}
  266. run: CI/linux/01_install_dependencies.sh ${{ matrix.script_options }}
  267. - name: 'Build OBS'
  268. run: CI/linux/02_build_obs.sh ${{ matrix.script_options }}
  269. - name: 'Run tests'
  270. if: success()
  271. run: cmake --build build -t test
  272. - name: 'Create build artifact'
  273. if: ${{ success() && fromJSON(needs.config.outputs.create_artifacts) }}
  274. run: |
  275. CI/linux/03_package_obs.sh
  276. ARTIFACT_NAME=$(basename $(/usr/bin/find build -maxdepth 1 -type f -name "obs-studio-*.deb" | sort -rn | head -1))
  277. echo "FILE_NAME=${ARTIFACT_NAME}" >> $GITHUB_ENV
  278. echo "DEBUG_FILE_NAME=${ARTIFACT_NAME//.deb/-dbgsym.ddeb}" >> $GITHUB_ENV
  279. - name: 'Upload build Artifact'
  280. if: ${{ success() && fromJSON(needs.config.outputs.create_artifacts) }}
  281. uses: actions/upload-artifact@v3
  282. with:
  283. name: 'obs-studio-${{ matrix.ubuntu }}-${{ steps.setup.outputs.commitHash }}'
  284. path: '${{ github.workspace }}/obs-studio/build/${{ env.FILE_NAME }}'
  285. - name: 'Upload debug symbol Artifact'
  286. if: ${{ success() && fromJSON(needs.config.outputs.create_artifacts) }}
  287. uses: actions/upload-artifact@v3
  288. with:
  289. name: 'obs-studio-${{ matrix.ubuntu }}-${{ steps.setup.outputs.commitHash }}-dbgsym'
  290. path: '${{ github.workspace }}/obs-studio/build/${{ env.DEBUG_FILE_NAME }}'
  291. windows_build:
  292. name: '02 - Windows'
  293. runs-on: [windows-2022]
  294. needs: [config, clang_check]
  295. if: always()
  296. strategy:
  297. matrix:
  298. arch: [x64, x86]
  299. env:
  300. CMAKE_GENERATOR: 'Visual Studio 17 2022'
  301. CMAKE_SYSTEM_VERSION: '10.0.18363.657'
  302. VIRTUALCAM-GUID: 'A3FCE0F5-3493-419F-958A-ABA1250EC20B'
  303. BUILD_FOR_DISTRIBUTION: ${{ startsWith(github.ref, 'refs/tags/') && github.event_name != 'pull_request' }}
  304. defaults:
  305. run:
  306. working-directory: 'obs-studio'
  307. steps:
  308. - name: 'Checkout'
  309. uses: actions/checkout@v3
  310. with:
  311. submodules: 'recursive'
  312. path: 'obs-studio'
  313. fetch-depth: 0
  314. - name: 'Add msbuild to PATH'
  315. uses: microsoft/[email protected]
  316. - name: 'Restore VLC dependency from cache'
  317. id: vlc-cache
  318. uses: actions/cache@v3
  319. env:
  320. CACHE_NAME: 'vlc-cache'
  321. with:
  322. path: ${{ github.workspace }}/obs-build-dependencies/vlc-${{ env.VLC_VERSION_WIN }}
  323. key: ${{ runner.os }}-pr-${{ env.CACHE_NAME }}-${{ env.VLC_VERSION_WIN }}-${{ env.CACHE_REVISION }}
  324. - name: 'Restore Chromium Embedded Framework from cache'
  325. id: cef-cache
  326. uses: actions/cache@v3
  327. env:
  328. CACHE_NAME: 'cef-cache'
  329. with:
  330. path: ${{ github.workspace }}/obs-build-dependencies/cef_binary_${{ env.CEF_BUILD_VERSION_WIN }}_windows_${{ matrix.arch }}
  331. key: ${{ runner.os }}-pr-${{ env.CACHE_NAME }}-${{ env.CEF_BUILD_VERSION_WIN }}-${{ matrix.arch }}-${{ env.CACHE_REVISION }}
  332. - name: Setup Environment
  333. id: setup
  334. run: |
  335. $CommitHash = git rev-parse --short=9 HEAD
  336. "commitHash=${CommitHash}" >> $env:GITHUB_OUTPUT
  337. - name: 'Install dependencies'
  338. env:
  339. RESTORED_VLC: ${{ steps.vlc-cache.outputs.cache-hit }}
  340. RESTORED_CEF: ${{ steps.cef-cache.outputs.cache-hit }}
  341. run: CI/windows/01_install_dependencies.ps1 -BuildArch ${{ matrix.arch }}
  342. - name: 'Build OBS'
  343. run: CI/windows/02_build_obs.ps1 -BuildArch ${{ matrix.arch }}
  344. - name: 'Create build artifact'
  345. if: ${{ success() && fromJSON(needs.config.outputs.create_artifacts) }}
  346. run: |
  347. CI/windows/03_package_obs.ps1 -BuildArch ${{ matrix.arch }} -Package
  348. $ArtifactName = Get-ChildItem -filter "obs-studio-*-windows-${{ matrix.arch }}.zip" -File
  349. Write-Output "FILE_NAME=${ArtifactName}" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
  350. - name: 'Upload build artifact'
  351. if: ${{ success() && fromJSON(needs.config.outputs.create_artifacts) }}
  352. uses: actions/upload-artifact@v3
  353. with:
  354. name: 'obs-studio-windows-${{ matrix.arch }}-${{ steps.setup.outputs.commitHash }}'
  355. path: '${{ env.FILE_NAME }}'
  356. linux_package:
  357. name: '02 - Flatpak'
  358. runs-on: [ubuntu-latest]
  359. needs: [config, clang_check]
  360. defaults:
  361. run:
  362. shell: bash
  363. container:
  364. image: bilelmoussaoui/flatpak-github-actions:kde-6.4
  365. options: --privileged
  366. steps:
  367. - name: 'Checkout'
  368. uses: actions/checkout@v3
  369. with:
  370. submodules: 'recursive'
  371. fetch-depth: 0
  372. - name: 'Setup build environment'
  373. id: setup
  374. env:
  375. GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  376. CACHE_KEY: flatpak-builder-${{ hashFiles('build-aux/**/*.json') }}
  377. run: |
  378. dnf install -y -q gh
  379. gh extension install actions/gh-actions-cache
  380. git config --global --add safe.directory $GITHUB_WORKSPACE
  381. KEY="$CACHE_KEY-x86_64"
  382. CACHE_HIT=$(gh actions-cache list -B master --key $KEY | grep -q $KEY && echo 'true' || echo 'false')
  383. echo "git_hash=$(git rev-parse --short=9 HEAD)" >> $GITHUB_OUTPUT
  384. echo "cache_key=$CACHE_KEY" >> $GITHUB_OUTPUT
  385. echo "cache_hit=$CACHE_HIT" >> $GITHUB_OUTPUT
  386. - name: Build Flatpak Manifest
  387. uses: flatpak/flatpak-github-actions/[email protected]
  388. with:
  389. build-bundle: ${{ fromJSON(needs.config.outputs.create_artifacts) }}
  390. bundle: obs-studio-flatpak-${{ steps.setup.outputs.git_hash }}.flatpak
  391. manifest-path: build-aux/com.obsproject.Studio.json
  392. cache: ${{ fromJSON(steps.setup.outputs.cache_hit) || (github.event_name == 'push' && github.ref == 'refs/heads/master') }}
  393. restore-cache: ${{ fromJSON(steps.setup.outputs.cache_hit) }}
  394. cache-key: ${{ steps.setup.outputs.cache_key }}
  395. windows_package:
  396. name: '03 - Windows Installer'
  397. runs-on: [windows-latest]
  398. needs: [windows_build]
  399. if: ${{ startsWith(github.ref, 'refs/tags/') && github.event_name != 'pull_request' }}
  400. env:
  401. BUILD_FOR_DISTRIBUTION: 'ON'
  402. steps:
  403. - name: 'Checkout'
  404. uses: actions/checkout@v3
  405. - name: Setup Environment
  406. id: setup
  407. run: |
  408. $CommitHash = git rev-parse --short=9 HEAD
  409. "commitHash=${CommitHash}" >> $env:GITHUB_OUTPUT
  410. - name: 'Add msbuild to PATH'
  411. uses: microsoft/[email protected]
  412. - name: 'Download 64-bit artifact'
  413. uses: actions/download-artifact@v3
  414. with:
  415. name: 'obs-studio-windows-x64-${{ steps.setup.outputs.commitHash }}'
  416. - name: 'Download 32-bit artifact'
  417. uses: actions/download-artifact@v3
  418. with:
  419. name: 'obs-studio-windows-x86-${{ steps.setup.outputs.commitHash }}'
  420. - name: 'Unpack Windows build artifacts'
  421. id: unpack
  422. run: |
  423. if (!(Test-Path install_temp)) {
  424. $null = New-Item -ItemType Directory -Force -Path install_temp
  425. }
  426. Expand-Archive -Path "$(Get-ChildItem -filter "obs-studio-*-windows-x86.zip" -File)" -DestinationPath install_temp
  427. Expand-Archive -Path "$(Get-ChildItem -filter "obs-studio-*-windows-x64.zip" -File)" -Force -DestinationPath install_temp
  428. CI/windows/03_package_obs.ps1 -CombinedArchs -Package
  429. $ArtifactName = (Get-ChildItem -filter "obs-studio-*-windows-x86+x64.zip" -File).Name
  430. "filename=${ArtifactName}" >> $env:GITHUB_OUTPUT
  431. - name: 'Upload build artifact'
  432. uses: actions/upload-artifact@v3
  433. with:
  434. name: 'obs-studio-windows-installer'
  435. path: '${{ steps.unpack.outputs.filename }}'
  436. macos_release:
  437. name: '03 - macOS notarized image'
  438. runs-on: [macos-12]
  439. needs: [macos_build]
  440. env:
  441. BUILD_FOR_DISTRIBUTION: 'ON'
  442. HAVE_SPARKLE_KEY: ${{ secrets.SPARKLE_PRIVATE_KEY != '' }}
  443. outputs:
  444. run_sparkle: ${{ steps.sparkle_check.outputs.run_sparkle }}
  445. if: ${{ startsWith(github.ref, 'refs/tags/') && github.event_name != 'pull_request' }}
  446. strategy:
  447. matrix:
  448. arch: ['x86_64', 'arm64']
  449. defaults:
  450. run:
  451. shell: bash
  452. steps:
  453. - name: 'Install Apple Developer Certificate'
  454. id: macos-codesign
  455. env:
  456. MACOS_SIGNING_IDENTITY: ${{ secrets.MACOS_SIGNING_IDENTITY }}
  457. MACOS_SIGNING_CERT: ${{ secrets.MACOS_SIGNING_CERT }}
  458. MACOS_SIGNING_CERT_PASSWORD: ${{ secrets.MACOS_SIGNING_CERT_PASSWORD }}
  459. MACOS_KEYCHAIN_PASSWORD: ${{ secrets.MACOS_KEYCHAIN_PASSWORD }}
  460. MACOS_PROVISIONING_PROFILE: ${{ secrets.MACOS_SIGNING_PROVISIONING_PROFILE }}
  461. MACOS_NOTARIZATION_USERNAME: ${{ secrets.MACOS_NOTARIZATION_USERNAME }}
  462. MACOS_NOTARIZATION_PASSWORD: ${{ secrets.MACOS_NOTARIZATION_PASSWORD }}
  463. run: |
  464. if [[ "${MACOS_SIGNING_IDENTITY}" && "${MACOS_SIGNING_CERT}" ]]; then
  465. CERTIFICATE_PATH="${RUNNER_TEMP}/build_certificate.p12"
  466. KEYCHAIN_PATH="${RUNNER_TEMP}/app-signing.keychain-db"
  467. echo -n "${MACOS_SIGNING_CERT}" | base64 --decode --output "${CERTIFICATE_PATH}"
  468. : "${MACOS_KEYCHAIN_PASSWORD:="$(echo ${RANDOM} | sha1sum | head -c 32)"}"
  469. security create-keychain -p "${MACOS_KEYCHAIN_PASSWORD}" "${KEYCHAIN_PATH}"
  470. security set-keychain-settings -lut 21600 "${KEYCHAIN_PATH}"
  471. security unlock-keychain -p "${MACOS_KEYCHAIN_PASSWORD}" "${KEYCHAIN_PATH}"
  472. security import "${CERTIFICATE_PATH}" -P "${MACOS_SIGNING_CERT_PASSWORD}" -A \
  473. -t cert -f pkcs12 -k "${KEYCHAIN_PATH}" \
  474. -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/xcrun
  475. security set-key-partition-list -S 'apple-tool:,apple:' -k "${MACOS_KEYCHAIN_PASSWORD}" \
  476. "${KEYCHAIN_PATH}" &> /dev/null
  477. security list-keychain -d user -s "${KEYCHAIN_PATH}" 'login-keychain'
  478. echo "CODESIGN_IDENT=${MACOS_SIGNING_IDENTITY}" >> $GITHUB_ENV
  479. echo "MACOS_KEYCHAIN_PASSWORD=${MACOS_KEYCHAIN_PASSWORD}" >> $GITHUB_ENV
  480. echo "haveCodesignIdent=true" >> $GITHUB_OUTPUT
  481. else
  482. echo "CODESIGN_IDENT=-" >> $GITHUB_ENV
  483. echo "haveCodesignIdent=false" >> $GITHUB_OUTPUT
  484. fi
  485. if [[ "${MACOS_PROVISIONING_PROFILE}" ]]; then
  486. PROFILE_PATH="${RUNNER_TEMP}/build_profile.provisionprofile"
  487. echo -n "${MACOS_PROVISIONING_PROFILE}" | base64 --decode --output "${PROFILE_PATH}"
  488. mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
  489. security cms -D -i "${PROFILE_PATH}" -o "${RUNNER_TEMP}/build_profile.plist"
  490. UUID="$(plutil -extract UUID raw "${RUNNER_TEMP}/build_profile.plist")"
  491. TEAM_ID="$(plutil -extract TeamIdentifier.0 raw -expect string "${RUNNER_TEMP}/build_profile.plist")"
  492. cp "${PROFILE_PATH}" ~/Library/MobileDevice/Provisioning\ Profiles/${UUID}.provisionprofile
  493. echo "provisionprofileUUID=${UUID}" >> $GITHUB_OUTPUT
  494. echo "haveProvisioningProfile=true" >> $GITHUB_OUTPUT
  495. echo "CODESIGN_TEAM=${TEAM_ID}" >> $GITHUB_ENV
  496. else
  497. echo "haveProvisioningProfile=false" >> $GITHUB_OUTPUT
  498. fi
  499. if [[ "${MACOS_NOTARIZATION_USERNAME}" && "${MACOS_NOTARIZATION_PASSWORD}" ]]; then
  500. echo "haveNotarizationUser=true" >> $GITHUB_OUTPUT
  501. else
  502. echo "haveNotarizationUser=false" >> $GITHUB_OUTPUT
  503. fi
  504. - name: 'Checkout'
  505. if: ${{ fromJSON(steps.macos-codesign.outputs.haveCodesignIdent) && fromJSON(steps.macos-codesign.outputs.haveNotarizationUser) }}
  506. uses: actions/checkout@v3
  507. - name: 'Setup build environment'
  508. if: ${{ fromJSON(steps.macos-codesign.outputs.haveCodesignIdent) && fromJSON(steps.macos-codesign.outputs.haveNotarizationUser) }}
  509. id: setup
  510. run: |
  511. echo "commitHash=$(git rev-parse --short=9 HEAD)" >> $GITHUB_OUTPUT
  512. - name: 'Determine if Sparkle should run'
  513. if: env.HAVE_CODESIGN_IDENTITY == 'true'
  514. id: sparkle_check
  515. run: |
  516. echo 'run_sparkle=${{ env.HAVE_SPARKLE_KEY }}' >> $GITHUB_OUTPUT
  517. - name: 'Download artifact'
  518. if: ${{ fromJSON(steps.macos-codesign.outputs.haveCodesignIdent) && fromJSON(steps.macos-codesign.outputs.haveNotarizationUser) }}
  519. uses: actions/download-artifact@v3
  520. with:
  521. name: 'obs-studio-macos-${{ matrix.arch }}-${{ steps.setup.outputs.commitHash }}'
  522. - name: 'Create disk image for distribution'
  523. if: ${{ fromJSON(steps.macos-codesign.outputs.haveCodesignIdent) && fromJSON(steps.macos-codesign.outputs.haveNotarizationUser) }}
  524. env:
  525. CODESIGN_IDENT_USER: ${{ secrets.MACOS_NOTARIZATION_USERNAME }}
  526. CODESIGN_IDENT_PASS: ${{ secrets.MACOS_NOTARIZATION_PASSWORD }}
  527. run: |
  528. ARTIFACT_NAME=$(/usr/bin/find . -type f -name "obs-studio-*.dmg" -depth 1 | head -1)
  529. CI/macos/03_package_obs.sh --notarize-image ${ARTIFACT_NAME}
  530. echo "FILE_NAME=$(basename ${ARTIFACT_NAME})" >> $GITHUB_ENV
  531. - name: 'Upload build Artifact'
  532. if: ${{ fromJSON(steps.macos-codesign.outputs.haveCodesignIdent) && fromJSON(steps.macos-codesign.outputs.haveNotarizationUser) }}
  533. uses: actions/upload-artifact@v3
  534. with:
  535. name: 'obs-studio-macos-${{ matrix.arch }}-notarized'
  536. path: '${{ github.workspace }}/${{ env.FILE_NAME }}'
  537. macos_sparkle:
  538. name: '04 - macOS Sparkle Updates'
  539. runs-on: [macos-12]
  540. needs: [macos_release]
  541. if: fromJSON(needs.macos_release.outputs.run_sparkle)
  542. strategy:
  543. matrix:
  544. arch: ['x86_64', 'arm64']
  545. env:
  546. SPARKLE_VERSION: '2.3.2'
  547. SPARKLE_HASH: '2b3fe6918ca20a83729aad34f8f693a678b714a17d33b5f13ca2d25edfa7eed3'
  548. defaults:
  549. run:
  550. shell: bash
  551. steps:
  552. - name: 'Checkout'
  553. uses: actions/checkout@v3
  554. with:
  555. path: 'repo'
  556. ref: ${{ github.ref }}
  557. - name: 'Download artifact'
  558. uses: actions/download-artifact@v3
  559. with:
  560. name: 'obs-studio-macos-${{ matrix.arch }}-notarized'
  561. path: 'artifacts'
  562. - name: 'Install Python requirements'
  563. run: pip3 install requests xmltodict
  564. - name: 'Install Brew requirements'
  565. run: brew install coreutils pandoc
  566. - name: 'Setup Sparkle'
  567. run: |
  568. curl -L "https://github.com/sparkle-project/Sparkle/releases/download/${{ env.SPARKLE_VERSION }}/Sparkle-${{ env.SPARKLE_VERSION }}.tar.xz" -o Sparkle.tar.xz
  569. if [[ '${{ env.SPARKLE_HASH }}' != "$(sha256sum Sparkle.tar.xz | cut -d " " -f 1)" ]]; then
  570. echo "Sparkle download hash does not match!"
  571. exit 1
  572. fi
  573. mkdir sparkle && cd sparkle
  574. tar -xf ../Sparkle.tar.xz
  575. - name: 'Setup folder structure'
  576. run: |
  577. mkdir builds
  578. mkdir -p output/appcasts/stable
  579. mkdir -p output/sparkle_deltas/${{ matrix.arch }}
  580. - name: 'Determine branch and tag'
  581. id: branch
  582. run: |
  583. pushd repo
  584. GIT_TAG="$(git describe --tags --abbrev=0)"
  585. if [[ ${GIT_TAG} == *'beta'* || ${GIT_TAG} == *'rc'* ]]; then
  586. echo "branch=beta" >> $GITHUB_OUTPUT
  587. echo "deltas=1" >> $GITHUB_OUTPUT
  588. else
  589. echo "branch=stable" >> $GITHUB_OUTPUT
  590. echo "deltas=1" >> $GITHUB_OUTPUT
  591. fi
  592. # Write tag description to file
  593. git tag -l --format='%(contents)' ${GIT_TAG} >> ../notes.rst
  594. - name: 'Download existing Appcast and builds'
  595. run: python3 repo/CI/macos/appcast_download.py --branch "${{ steps.branch.outputs.branch }}" --max-old-versions ${{ steps.branch.outputs.deltas }}
  596. - name: 'Prepare release notes'
  597. run: |
  598. # Insert underline at line 2 to turn first line into heading
  599. sed -i '' '2i\'$'\n''###################################################' notes.rst
  600. pandoc -f rst -t html notes.rst -o output/appcasts/notes_${{ steps.branch.outputs.branch }}.html
  601. - name: 'Setup Sparkle key'
  602. run: echo -n "${{ secrets.SPARKLE_PRIVATE_KEY }}" >> eddsa_private.key
  603. - name: 'Generate Appcast'
  604. run: |
  605. mv artifacts/*.dmg builds/
  606. ./sparkle/bin/generate_appcast \
  607. --verbose \
  608. --ed-key-file ./eddsa_private.key \
  609. --download-url-prefix "https://cdn-fastly.obsproject.com/downloads/" \
  610. --full-release-notes-url "https://obsproject.com/osx_update/notes_${{ steps.branch.outputs.branch }}.html" \
  611. --maximum-versions 0 \
  612. --maximum-deltas ${{ steps.branch.outputs.deltas }} \
  613. --channel "${{ steps.branch.outputs.branch }}" builds/
  614. # Move deltas, if any
  615. if compgen -G "builds/*.delta" > /dev/null; then
  616. mv builds/*.delta output/sparkle_deltas/${{ matrix.arch }}
  617. fi
  618. # Move appcasts
  619. mv builds/*.xml output/appcasts/
  620. - name: 'Create 1.x Appcast'
  621. run: python3 repo/CI/macos/appcast_convert.py
  622. - name: 'Upload Appcast and Deltas'
  623. uses: actions/upload-artifact@v3
  624. with:
  625. name: 'macos-sparkle-updates'
  626. path: '${{ github.workspace }}/output'