package-macos 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #!/usr/bin/env zsh
  2. builtin emulate -L zsh
  3. setopt EXTENDED_GLOB
  4. setopt PUSHD_SILENT
  5. setopt ERR_EXIT
  6. setopt ERR_RETURN
  7. setopt NO_UNSET
  8. setopt PIPE_FAIL
  9. setopt NO_AUTO_PUSHD
  10. setopt NO_PUSHD_IGNORE_DUPS
  11. setopt FUNCTION_ARGZERO
  12. ## Enable for script debugging
  13. # setopt WARN_CREATE_GLOBAL
  14. # setopt WARN_NESTED_VAR
  15. # setopt XTRACE
  16. if (( ! ${+CI} )) {
  17. print -u2 -PR "%F{1} ✖︎ ${ZSH_ARGZERO:t:r} requires CI environment%f"
  18. exit 1
  19. }
  20. autoload -Uz is-at-least && if ! is-at-least 5.9; then
  21. print -u2 -PR "${CI:+::error::}%F{1}${funcstack[1]##*/}:%f Running on Zsh version %B${ZSH_VERSION}%b, but Zsh %B5.2%b is the minimum supported version. Upgrade Zsh to fix this issue."
  22. exit 1
  23. fi
  24. TRAPZERR() {
  25. print -u2 -PR "::error::%F{1} ✖︎ script execution error%f"
  26. print -PR -e "
  27. Callstack:
  28. ${(j:\n :)funcfiletrace}
  29. "
  30. exit 2
  31. }
  32. package() {
  33. if (( ! ${+SCRIPT_HOME} )) typeset -g SCRIPT_HOME=${ZSH_ARGZERO:A:h}
  34. local host_os='macos'
  35. local project_root=${SCRIPT_HOME:A:h:h}
  36. local buildspec_file=${project_root}/buildspec.json
  37. fpath=("${SCRIPT_HOME}/utils.zsh" ${fpath})
  38. autoload -Uz log_group log_error log_output check_macos
  39. if [[ ! -r ${buildspec_file} ]] {
  40. log_error \
  41. 'No buildspec.json found. Please create a build specification for your project.'
  42. return 2
  43. }
  44. local -i debug=0
  45. local config='RelWithDebInfo'
  46. local -r -a _valid_configs=(Debug RelWithDebInfo Release MinSizeRel)
  47. local -i codesign=0
  48. local -i notarize=0
  49. local -i package=0
  50. local -a args
  51. while (( # )) {
  52. case ${1} {
  53. -c|--config)
  54. if (( # == 1 )) || [[ ${2:0:1} == '-' ]] {
  55. log_error "Missing value for option %B${1}%b"
  56. exit 2
  57. }
  58. ;;
  59. }
  60. case ${1} {
  61. --) shift; args+=($@); break ;;
  62. -c|--config)
  63. if (( !${_valid_configs[(Ie)${2}]} )) {
  64. log_error "Invalid value %B${2}%b for option %B${1}%b"
  65. exit 2
  66. }
  67. config=${2}
  68. shift 2
  69. ;;
  70. -s|--codesign) typeset -g codesign=1; shift ;;
  71. -n|--notarize) typeset -g notarize=1; typeset -g codesign=1; shift ;;
  72. -p|--package) typeset -g package=1; shift ;;
  73. --debug) debug=1; shift ;;
  74. *) log_error "Unknown option: %B${1}%b"; exit 2 ;;
  75. }
  76. }
  77. set -- ${(@)args}
  78. check_macos
  79. local product_name
  80. local product_version
  81. read -r product_name product_version <<< \
  82. "$(jq -r '. | {name, version} | join(" ")' ${buildspec_file})"
  83. local output_name="${product_name}-${product_version}-${host_os}-universal"
  84. if [[ ! -d ${project_root}/release/${config}/${product_name}.plugin ]] {
  85. log_error 'No release artifact found. Run the build script or the CMake install procedure first.'
  86. return 2
  87. }
  88. if (( package )) {
  89. if [[ ! -f ${project_root}/release/${config}/${product_name}.pkg ]] {
  90. log_error 'Installer Package not found. Run the build script or the CMake build and install procedures first.'
  91. return 2
  92. }
  93. log_group "Packaging ${product_name}..."
  94. pushd ${project_root}
  95. typeset -gx CODESIGN_IDENT="${CODESIGN_IDENT:--}"
  96. typeset -gx CODESIGN_IDENT_INSTALLER="${CODESIGN_IDENT_INSTALLER:--}"
  97. typeset -gx CODESIGN_TEAM="$(print "${CODESIGN_IDENT}" | /usr/bin/sed -En 's/.+\((.+)\)/\1/p')"
  98. if (( codesign )) {
  99. productsign \
  100. --sign "${CODESIGN_IDENT_INSTALLER}" \
  101. ${project_root}/release/${config}/${product_name}.pkg \
  102. ${project_root}/release/${output_name}.pkg
  103. rm ${project_root}/release/${config}/${product_name}.pkg
  104. } else {
  105. mv ${project_root}/release/${config}/${product_name}.pkg \
  106. ${project_root}/release/${output_name}.pkg
  107. }
  108. if (( codesign && notarize )) {
  109. if ! [[ ${CODESIGN_IDENT} != '-' && ${CODESIGN_TEAM} && {CODESIGN_IDENT_USER} && ${CODESIGN_IDENT_PASS} ]] {
  110. log_error "Notarization requires Apple ID and application password."
  111. return 2
  112. }
  113. if [[ ! -f ${project_root}/release/${output_name}.pkg ]] {
  114. log_error "No package for notarization found."
  115. return 2
  116. }
  117. xcrun notarytool store-credentials "${product_name}-Codesign-Password" --apple-id "${CODESIGN_IDENT_USER}" --team-id "${CODESIGN_TEAM}" --password "${CODESIGN_IDENT_PASS}"
  118. xcrun notarytool submit ${project_root}/release/${output_name}.pkg --keychain-profile "${product_name}-Codesign-Password" --wait
  119. local -i _status=0
  120. xcrun stapler staple ${project_root}/release/${output_name}.pkg || _status=1
  121. if (( _status )) {
  122. log_error "Notarization failed. Use 'xcrun notarytool log <submission ID>' to check for errors."
  123. return 2
  124. }
  125. }
  126. popd
  127. } else {
  128. log_group "Archiving ${product_name}..."
  129. pushd ${project_root}/release/${config}
  130. XZ_OPT=-T0 tar -cvJf ${project_root}/release/${output_name}.tar.xz ${product_name}.plugin
  131. popd
  132. }
  133. if [[ ${config} == Release ]] {
  134. log_group "Archiving ${product_name} Debug Symbols..."
  135. pushd ${project_root}/release/${config}
  136. XZ_OPT=-T0 tar -cvJf ${project_root}/release/${output_name}-dSYMs.tar.xz ${product_name}.plugin.dSYM
  137. popd
  138. }
  139. log_group
  140. }
  141. package ${@}