CI/CD macOS Application Bundling .app Artifacts
1. macOS Application Bundle Structure
1.1 The .app
Bundle Format
In macOS, applications are distributed as bundles, a directory structure that contains executable code and related resources. Here's the typical structure of a .app
bundle:
MyApp.app/
Contents/
Info.plist
MacOS/
MyApp
Resources/
MyApp.icns
Info.plist
: Metadata and configuration information.MacOS/
: Main executable file.Resources/
: Stores resource files, such as images and localized content.
1.2 Understanding the Info.plist File
A .app
bundle is really just a directory. The Info.plist
file is critical to the .app
bundle as it is what defines how to use this folder as a launcher instead of a folder. It contains key-value pairs that macOS uses to index the application. Key elements include:
CFBundleExecutable
: Specifies the main executable file.CFBundleIconFile
: Defines the icon file.
Here's an example snippet:
<dict>
<key>CFBundleExecutable</key>
<string>MyApp</string>
<key>CFBundleIconFile</key>
<string>MyApp.icns</string>
</dict>
2. ICNS Conversion
macOS uses the ICNS file format for icons. A convenient conversion tool is png-to-icns-right-click-converter. This tool allows for seamless conversion from PNG to ICNS, suitable for inclusion in the application bundle's Resources directory.
3. CI/CD Integration
3.1 YAML Configuration for Packaging macOS Application
Continuous Integration and Continuous Deployment (CI/CD) streamline the development workflow. Below is a YAML script that demonstrates how to package a macOS application binary:
pack_macos_app:
stage: package_stage
dependencies:
- build_stage
script:
- INFO_PLIST="$APP_NAME.app/Contents/Info.plist"
- echo "Packing self-contained build for macOS x64..."
- mkdir -p $APP_NAME.app/Contents/MacOS
- mkdir -p $APP_NAME.app/Contents/Resources
- cp Resources/Icons/icon.icns $APP_NAME.app/Contents/Resources/
- cp $BUILD_DIR/$BINARY_NAME $APP_NAME.app/Contents/MacOS/
- chmod +x $APP_NAME.app/Contents/MacOS/$BINARY_NAME
- echo '<?xml version="1.0" encoding="UTF-8"?>' > $INFO_PLIST
- echo '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">' >> $INFO_PLIST
- echo '<plist version="1.0">' >> $INFO_PLIST
- echo '<dict>' >> $INFO_PLIST
- echo ' <key>CFBundleExecutable</key>' >> $INFO_PLIST
- echo " <string>$BINARY_NAME</string>" >> $INFO_PLIST
- echo ' <key>CFBundleIconFile</key>' >> $INFO_PLIST
- echo ' <string>icon.icns</string>' >> $INFO_PLIST
- echo '</dict>' >> $INFO_PLIST
- echo '</plist>' >> $INFO_PLIST
artifacts:
name: "macOS x64 (self-contained)"
paths:
- $BUILD_DIR/$APP_NAME.app
expire_in: 1 week
TL;DR
macOS applications rely on a bundle structure, where an application is organized as a directory with the .app extension. This structure includes executable code, resources, and metadata, all defined within specific subdirectories and files such as .plist and ICNS icon files. Understanding these aspects allows developers to create CI/CD bundling stages for any macOS app.