CI/CD macOS Application Bundling .app Artifacts

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.

Gaming in Thailand as a Foreigner

Hey gamers! It's world famous video gamer downthecrop! Back from my Thailand adventure and sharing the wisdom my globe trotting has afforded me!

General Internet Speed

This is going to depend mostly on your accommodation. I had 30/10 internet through Coax in my building which I'd estimate finished construction in the mid 2000's. You can find fiber internet in Bangkok but I'd assume most places are still Coax or DSL instead of fiber. Most internet is routed through Chang Mai anyway from the traceroutes I did while I was there.

Gaming VPN's

While there is a Thai server for League of Legends on Garena a problem you will experience in Thailand is that there just isn't a large enough population to support some games. League of Legends for example I was getting queue times exceeding 15 minutes at peak times (Noon to 11:00PM) in ranked which is extremely long compared to NA/EU/KR. To remedy this you are going to need to select the closest server with an active playerbase for your favorite games! I played mostly on Vietnam for League of Legends. Although you can simply change the region of the Garena Launcher and download any game you want there is IP based region lock for some games. League of Legends falls into these IP locked games. Because of this we are going to need to use a VPN.

Generally VPN's aren't very good for gaming. Due to oversold traffic and a lack of fast localized routers to handle your traffic you are going to be experiencing higher latency playing through a VPN than without one. There are a few VPN providers that SEA use to get their game on!

  • Mudfish
  • VietPN
  • PingBooster

Note: Exitlag and WTFast have very few servers in SEA so I wouldn't recommended them as a first choice for this use case but they will work.

For me I used VietPN and it cost me $5 a month which was a great price. Fast servers to Vietnam which is region locked for League of Legends. I would have preferred to play to China (Ionia probably the worst choice for server because it's so far away but there are many regions in China which are closer and would still have more players than TH or SG server which were the two best choices for ping.

Anyway I'm not spell checking this I just wanted to document for anyone else that is thinking of gaming in Thailand!

Nano for Windows (CMD and PowerShell)

Nano is my preferred editor for quick config changes. It's simple to install or even comes standard on many unix systems but what about Windows?

Install Chocolatey (Run as Administrator in PowerShell)

Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

Install Nano (Run as Administrator)

choco install nano

Now you can run nano to open the editor.

Blog Relaunch

Well well well. Look who’s back to writing a blog that no one will ever read or care about. That’s right! Lil’ Cropster.

As you can see I’ve gone and touched up some of the loading issues and improved the site a little. Goal is the same as it always was. Create more content and hopefully attract more eyeballs to look at it. A growing list of topics continue to overflow from my notes application and “like a bee thats gathered too much honey, needs hands out stretched to take it” or something, whatever Zarathustra said.

I spent some time last year writing a few posts for this which, after careful cringe analysis, seem to actually be good! Hopefully after I private all my posts and scrub this blog from the internet again in the coming months when I have some kind of internal crisis I will look at these posts during the 2020 relaunch with pride.

Your time is valuable

I think it was Bill Clinton who said "If you're good at something never do it for free" or maybe that was the Joker.

Anyway this past week I was approached for contract work so I've had some numbers on my mind. I'll share my opinion on selling your services and pricing your work.

A race to the bottom

There's no getting around the fact that there are plenty of people who are working for far too little pay. Whether that's a lack of confidence in themselves and their work or just wanting to be "nice" and giving their clients a deal they both have the same effect. Every time you take on a job for free, accept lower rates, or work for additional unbilled time you are actively devaluing yourself and those with a similar skillset. Expectations of hourly rates for whatever it is you do is important to have a steady stream of clients. If the competition is willing to work for half of what their time is worth you may find yourself dropping to their level to stay competitive. The quality of work some freelancers push out for minimum wage when they can set their own prices for their time is really sad.

You're skilled at what you do. You have worked for years to learn what you know and practiced to become an expert. That's why people seek out your services. They value your time. They trust your track record and know they can have a great product delivered. If you have a skillset of any kind you should at the absolute least be charging 2.5x minimum wage.

If you're an artist/professional and self employed I know the business side of things can be hard. I hate email and I hate talking money with clients. Of course hating something doesn't mean it's not important. Spend the time to learn to manage your business. Spend the time to REALLY think what your time is worth. In both the long run and the short run higher rates make it easier to turn down work or clients you don't like. Pricing yourself appropriately helps you and everyone else in your field push for a better quality of life inside and outside of work.

When sifting potential clients have a keen eye to spot any questioning of your prices. An "OUCH! Very expensive" comment immediately drops you to low priority brain processing and 1 to 3 business days for email communication. These are the people you waste time thinking about. These are the people who find someone who's services fit their budget last minute after you've sent 10 emails back and forth. By spending less time on people who are less willing to step up and pay a fair price for great work you're going to have a lot less stress in your life

Find a number that's higher than what you, as a professional in the field, would be willing to pay your competitors. If it feels too high you're in the right ballpark.

Anyway whatever I just needed to write something here to fill the gap. Thanks!