Skip to content

Instantly share code, notes, and snippets.

@desplesda
Last active March 29, 2021 18:53
Show Gist options
  • Save desplesda/6dac270903b4b8d60ef18abefa31dbee to your computer and use it in GitHub Desktop.
Save desplesda/6dac270903b4b8d60ef18abefa31dbee to your computer and use it in GitHub Desktop.
An example of the Fastfile used to automate builds of Night in the Woods.
# This Fastfile uses the u3d gem to control Unity. You can find it at:
# https://github.com/DragonBox/u3d
# This is the minimum version number required.
# Update this, if you use features of a newer version
fastlane_version "2.117.1"
fastlane_require 'spaceship'
default_platform :ios
platform :ios do
before_all do
# We've encountered some problems with the default upload process when
# uploading from Winnipeg, though not from Hobart; the Fastlane issue
# list suggested that this might help
ENV["DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS"]="-t Signiant"
# Used by the 'slack' action to send messages to our development slack
ENV["SLACK_URL"]="https://hooks.slack.com/services/XXXXXXX"
end
desc "Pulls the most recent version; if it's newer, starts a build."
# This lane is run at (usually) midnight by our script.
lane :scheduled do
# What was the most recent git commit ID?
previous_latest_commit = last_git_commit
# Perform a git pull, to see if anything new has appeared
git_pull
new_latest_commit = last_git_commit
prev = previous_latest_commit[:commit_hash]
now = new_latest_commit[:commit_hash]
# Check to see if there are any new commits. If there aren't, we don't
# need to do a build now.
if prev == now then
UI.success "No changes #{prev} == #{now}; no reason to do a scheduled build."
else
UI.success "New changes. Starting a build."
# Perform the full build process (see the 'beta' action elsewhere)
beta
end
end
desc "Update the local copy, and create a new ad-hoc build."
# This lane is run when we manually instruct our Slack bot to perform a
# build. It just pulls the most recent code and starts the build process,
# without checking to see if there's new code or not.
lane :on_demand do
git_pull
beta
end
desc "Updates the build number to be equal to the number of commits"
desc "in the current branch"
lane :update_build_number do
UI.message "Determining build number from number of commits..."
# Count the number of commits on the current branch
build_number = number_of_commits()
# Update the build number in the Info.plist inside the project.
increment_build_number_in_plist(
build_number: build_number.to_s,
xcodeproj: "./Builds/NITW/iOS/NITW/Unity-iPhone.xcodeproj"
)
UI.success "Updated project build number to #{build_number}!"
end
desc "Performs an iOS build of the game."
desc "This will generate the Xcode project."
lane :unity do |options|
# Use the u3d gem to remote-control Unity into building the Xcode
# project.
#
# EditorMenu.BuildIOS is a method in our source code that gathers the
# scenes we need for this build, and creates the build itself. The
# location of the build is specified in the source; it will end up in
# Builds/NITW/iOS/NITW.
u3d(
raw_logs: options[:raw_logs],
run_args: "-logFile './editor.log' -executeMethod EditorMenu.BuildIOS -quit -batchmode"
)
end
desc "Builds the Xcode project."
lane :build_xcproj do
# We manually specify our provisioning profile, which was retrieved
# from match.
settings_to_override = {
:BUNDLE_IDENTIFIER => "xxxxxxxxx.nightinthewoods",
:PROVISIONING_PROFILE_SPECIFIER => "match AppStore xxxxxxxxx.nightinthewoods",
:DEVELOPMENT_TEAM => "XXXXXXXXXX"
}
# Perform the Xcode build, and archive it using the app store
# provisioning profile.
gym(
xcargs: settings_to_override,
scheme: "Unity-iPhone",
configuration: "Release",
export_options: {
method: "app-store",
provisioningProfiles: {
"xxxxxxxxx.nightinthewoods" => "match AppStore xxxxxxxxx.nightinthewoods"
}
}
)
end
desc "Submit a new build to Apple TestFlight"
lane :beta do |options|
# We use the number of commits on the 'ios' branch as our build number,
# which the App Store requires be a number that always increases.
# Commit count suits this nicely.
# Record this in a variable so that we can post to Slack about it.
version = number_of_commits()
# Notify everyone that a build is starting
slack(
message: "I'm starting build #{version}!",
default_payloads: []
)
# Build the Unity project (see the 'unity' action above)
unity
# Report on progress
slack(
message: "Unity build complete. Starting Xcode build for #{version}.",
default_payloads: []
)
# Update the version number in the generated project (see the
# update_build_number action above)
update_build_number
# Ensure we have the correct code signing assets; we store our code
# signing certificate in encrypted form in a private repo, which means
# that all builds are signed with the same certificate and profile. It
# makes builds much easier.
match(
type: "appstore",
readonly:true
)
# Build the Xcode app (see the build_xcproj action above)
build_xcproj
# Report on our progress
slack(
message: "Build #{version} just finished! Uploading to TestFlight now.",
default_payloads: []
)
# We store our changelog in a text file, which we can manually add to
# when we make changes. Lines above the first '---' will be displayed
# in the "What To Test" section in the TestFlight app.
begin
changelog = File.read("Changelog.txt").split("---")[0].strip
rescue => exception
# use a blank changelog in case the file isn't present
changelog = ""
end
# Upload the built project to TestFlight, and distribute it to our testers.
pilot(
distribute_external: true,
changelog: changelog
)
# Report success!
slack(
message: "Build #{version} was deployed to TestFlight! `*adjusts glasses*`",
default_payloads: []
)
end
# This code runs if any step fails.
error do |lane, exception|
# Report the error to slack
slack(
# message with short human friendly message
message: "Error in build! :( ",
success: false,
# Output containing extended log output
payload: { "Output" => exception.to_s }
)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment