Skip to content

Instantly share code, notes, and snippets.

@seanwolter
Last active January 4, 2017 15:42
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seanwolter/9195007 to your computer and use it in GitHub Desktop.
Save seanwolter/9195007 to your computer and use it in GitHub Desktop.
Scripts we use on our Xcode Bots CI server

The following plists and scripts are used on VOKAL's iOS build server. Thanks to the magic of launchd the backup script runs once a day and the dropoff script runs as needed. The dropoff script imports p12 files to the system keychain and moves provisioning files to correct folder.

To use these scripts put them somewhere safe, then put the plist files in /Library/LaunchDaemons Update the paths to the scripts, fix the ACCESS_KEY_ID and SECRET_ACCESS_KEY variables, and you're on your way.

If you have questions about Daemons and Agents look at Apple's technote: https://developer.apple.com/library/mac/technotes/tn2083/_index.html

More docs: https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/Introduction.html#//apple_ref/doc/uid/10000172i-SW1-SW1

UPDATE: I've found WatchPaths works intermittently. I'm not sure why.

#! /usr/bin/python
# Created by Sean Wolter on 21 Feb 2014
#
import boto
import tarfile
import os
from datetime import datetime
ACCESS_KEY_ID = "XXXXXXX"
SECRET_ACCESS_KEY = "XXXXXXX"
VAULT_NAME = "iosBuildBackup"
FOLDERS_TO_BACKUP = ("/Library/Server/Xcode/Data/ProvisioningProfiles", "/Users/vokal/bin", "/Library/Server/Xcode/Config")
glacier_connection = boto.connect_glacier(aws_access_key_id=ACCESS_KEY_ID, aws_secret_access_key=SECRET_ACCESS_KEY)
def gzipFiles(folder_path):
tar_filename = "{0}{1}.tgz".format(folder_path.split("/")[-1], datetime.now().toordinal())
tar = tarfile.open(tar_filename, "w:gz" )
for name in os.listdir( folder_path ):
tar.add("{0}/{1}".format(folder_path, name))
tar.close()
return tar_filename
if __name__ == "__main__":
vault = glacier_connection.get_vault(VAULT_NAME)
for folder in FOLDERS_TO_BACKUP:
file_to_upload_path = gzipFiles(folder)
archive_id = vault.upload_archive(file_to_upload_path)
print("uploaded {0}".format(archive_id))
os.remove(file_to_upload_path)
#!/usr/bin/perl
# launchd watches the dropoff folder then runs this script
# checks the dropoff folder for .p12 and .mobileprovision files
# http://www.splinter.com.au/using-launchd-to-run-a-script-every-5-mins-on/
# Created by Sean Wolter on 5 December 2013
#
use strict;
use warnings;
use File::Copy;
my $source_directory = "/ProfileCertKeyDropOff/";
my $profile_destination = "/Library/Server/Xcode/Data/ProvisioningProfiles/";
my @profiles = glob "$source_directory*.mobileprovision";
my @certs = glob "$source_directory*.p12";
foreach (@profiles) {
move($_, $profile_destination);
}
foreach (@certs) {
# This assumes the password to your p12 file is 1234. Change it as needed.
system("security import $_ -k /Library/Keychains/System.keychain -P 1234 -A");
unlink $_;
}
my @profilesInPlace = glob "$profile_destination*.mobileprovision";
foreach (@profilesInPlace) {
my $mode = 0777;
chmod $mode, $_;
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SessionCreate</key>
<true/>
<key>Label</key>
<string>com.vokal.checkPublicFolder</string>
<key>ProgramArguments</key>
<array>
<string>/Users/vokal/bin/backup.py</string>
</array>
<key>StartInterval</key>
<integer>86400</integer>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SessionCreate</key>
<true/>
<key>Label</key>
<string>com.vokal.checkPublicFolder</string>
<key>ProgramArguments</key>
<array>
<string>/Users/vokal/bin/checkPublicFolder.pl</string>
</array>
<key>WatchPaths</key>
<array>
<string>/ProfileCertKeyDropOff</string>
</array>
<key>ThrottleInterval</key>
<integer>60</integer>
</dict>
</plist>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment