From 4a0a4b3c663caec2f601d686ca751b73d791e0b2 Mon Sep 17 00:00:00 2001 From: Gilles Grousset Date: Tue, 3 Dec 2019 18:51:59 +0100 Subject: [PATCH] Initial commit --- .gitignore | 1 + README.md | 100 +++++++++++++++++++++ Vagrantfile | 179 +++++++++++++++++++++++++++++++++++++ scripts/start-simulator.sh | 27 ++++++ 4 files changed, 307 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 Vagrantfile create mode 100755 scripts/start-simulator.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..44495a8 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/.vagrant \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..67c5a39 --- /dev/null +++ b/README.md @@ -0,0 +1,100 @@ +# Xcode GitLab runner + +A Vagrantfile to build a fully functional macOS / Xcode GitLab runner + +## TL;DR + +### Build and run the runner +Once VirtualBox and Vagrant are installed, use the following command to build and run the box : + + XCODE_XIP_FILE="/path-to-Xcode.xip" \ + GITLAB_URL="https://gitlab.com/" \ + GITLAB_REGISTRATION_TOKEN="your-token" \ + GITLAB_RUNNER_NAME="macMachine" \ + GITLAB_RUNNER_TAGS="macos,xcode11" \ + vagrant up + +Note that an Xcode .xip install archive is required to perform Xcode installation. + +### Test and anlayse a project +Add and configure a sonar-project.properties as explained [here](https://github.com/Backelite/sonar-swift) + +Then use the following .gitlab-ci.yml file to run the build / test / analysis (and publication to SonarQube): + + analyse: + tags: + - xcode11 + script: + - pod install + - run-sonar-swift.sh -sonarurl=$SONAR_URL -sonarlogin=$SONAR_TOKEN + + SONAR_URL and SONAR_TOKEN are defined as GitLab CI/CD variables + +## What's in the box ? + +Here is a list of tools included in the box : +- Xcode +- fastlane +- sonar-swift +- sonar-scanner +- xcpretty +- gcovr +- CocoaPods +- Carthage +- XCode +- slather +- OCLint +- SwiftLint +- applesimutils + +## Prerequisites + +### VirtualBox + +A recent version of VirtualBox and extension pack is required to run the generated virtual machine. + +VirtualBox can be downloaded from [here](https://www.virtualbox.org/). + +Or installed using [Homebrew](https://brew.sh/): + + brew cask install virtualbox + brew cask install virtualbox-extension-pack + +### Vagrant + +Vagrant and its reload plugin are required to run the Vagrantfile. + +It can be installed using [Homebrew](https://brew.sh/): + + brew cask install vagrant + vagrant plugin install vagrant-reload + +### Xcode .xip file + +A Xcode .xip install archive is required to build the box. + +It can be downloaded from [here](https://developer.apple.com/download/more/) (Apple ID required). + +## Parameters + +Parameters are set as environmeent variables when running "vagrant up" command: + + PARAM1="stringvalue" PARAM2=numbervalue ... vagrant up + +Here is a list of available parameters + +| Parameter | Default value | +|---------------------------|:--------------------:| +| XCODE_XIP_FILE | none (manadatory) | +| GITLAB_URL | https://gitlab.com/ | +| GITLAB_REGISTRATION_TOKEN | none (mandatory) | +| GITLAB_RUNNER_NAME | none (mandatory) | +| GITLAB_RUNNER_TAGS | none (mandatory) | +| CPU_COUNT | 4 | +| RAM_SIZE | 4096 | + +## Reminder : OS X Licensing +Apple's EULA states that you can install your copy on your actual Apple-hardware, plus up to two VMs running on your Apple-hardware. So using this box on another hardware is may be illegal and you should do it on your own risk. + +By using it you agree with all macOS Sierra and XCode license agreements. + diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000..979d6d4 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,179 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# All Vagrant configuration is done below. The "2" in Vagrant.configure +# configures the configuration version (we support older styles for +# backwards compatibility). Please don't change it unless you know what +# you're doing. + +XCODE_XIP_FILE=ENV['XCODE_XIP_FILE'] +GITLAB_URL=ENV['GITLAB_URL'] || "https://gitlab.com/" +GITLAB_REGISTRATION_TOKEN=ENV['GITLAB_REGISTRATION_TOKEN'] +GITLAB_RUNNER_NAME=ENV['GITLAB_RUNNER_NAME'] +GITLAB_RUNNER_TAGS=ENV['GITLAB_RUNNER_TAGS'] +CPU_COUNT=ENV['CPU_COUNT'] || 4 +RAM_SIZE=ENV['RAM_SIZE'] || 4096 + +Vagrant.configure("2") do |config| + + # Get box + config.vm.box = "leav3/macos_mojave" + + # Configuration + config.vm.provider 'virtualbox' do |vb| + vb.customize ["modifyvm", :id, "--ostype", "MacOS_64"] + vb.customize ["modifyvm", :id, "--ioapic", "on"] + vb.customize ["modifyvm", :id, "--nestedpaging", "off"] + vb.gui = false + vb.name = 'mojave-xcode' + vb.cpus = "#{CPU_COUNT}" + vb.memory = "#{RAM_SIZE}" + config.vm.synced_folder ".", "/vagrant", disabled: true + end + + # Set boot timeout to 600 seconds + config.vm.boot_timeout = 600 + + # Copy Xcode install package + config.vm.provision "file", source: "#{XCODE_XIP_FILE}", destination: "/tmp/Xcode.xip" + + # Copy scripts + config.vm.provision "file", source: "./scripts", destination: "/tmp/scripts" + + # Environment variables + config.vm.provision "shell", privileged: true, name: 'environment variables', inline: <<-SHELL + echo export BINARIES_DIRECTORY='/opt/local/bin' >> /etc/profile + echo export BUILD_TOOLS_REPOSITORY=build-ios-simple-shell >> /etc/profile + echo export USERNAME='vagrant' >> /etc/profile + echo export LANG='en_US.UTF-8' >> /etc/profile + echo export LANGUAGE='en_US.UTF-8' >> /etc/profile + echo export LC_ALL='en_US.UTF-8' >> /etc/profile + echo export 'PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin' >> /etc/profile + SHELL + + # Disable sleep mode + config.vm.provision "shell", privileged: false, name: 'disable sleep mode', inline: <<-SHELL + sudo systemsetup -setcomputersleep Never + SHELL + + # Developer mode activation + config.vm.provision "shell", privileged: false, name: 'developer mode activation', inline: <<-SHELL + sudo /usr/sbin/DevToolsSecurity -enable + sudo /usr/sbin/dseditgroup -o edit -t group -a staff _developer + SHELL + + # Install scripts + config.vm.provision "shell", privileged: true, name: 'scripts', inline: <<-SHELL + mkdir -p /usr/local/opt + mv /tmp/scripts/ /usr/local/opt + chmod +x /usr/local/opt/scripts/*.sh + echo export PATH=/usr/local/opt/scripts:\$PATH >> /etc/profile + SHELL + + # Install brew + config.vm.provision "shell", privileged: false, name: 'homebrew with command line tools', inline: <<-SHELL + /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" + SHELL + + # Install command line tools with brew + config.vm.provision "shell", privileged: false, name: 'brew tools', inline: <<-SHELL + /usr/local/bin/brew tap oclint/formulae + /usr/local/bin/brew install xz ruby wget gcovr doxygen graphviz sonar-scanner carthage python@2 imagemagick ghostscript oclint + SHELL + + # Install brew tools path + config.vm.provision "shell", privileged: true, name: 'brew tools path', inline: <<-SHELL + echo export PATH=/usr/local/opt/python@2/libexec/bin:\$PATH >> /etc/profile + SHELL + + # Install Lizard + config.vm.provision "shell", privileged: true, name: 'pip tools', inline: <<-SHELL + pip install lizard + SHELL + + # Install gem tools + config.vm.provision "shell", privileged: false, name: 'gem tools', inline: <<-SHELL + /usr/local/opt/ruby/bin/gem install xcpretty slather cocoapods jazzy + /usr/local/opt/ruby/bin/gem install bundler --force + /usr/local/opt/ruby/bin/gem install xcodeproj + /usr/local/opt/ruby/bin/gem install fileutils + sudo /usr/local/opt/ruby/bin/gem install fastlane -NV + SHELL + + # Install gem tools path + config.vm.provision "shell", privileged: true, name: 'gem tools path', inline: <<-SHELL + GEM_TOOL_BIN_PATH=`/usr/local/opt/ruby/bin/gem environment | awk -F ' *: *' '$1 ~ /EXECUTABLE DIRECTORY/{print $2}'` + echo export PATH=\$GEM_TOOL_BIN_PATH:\$PATH >> /etc/profile + SHELL + + # sonar-swift script + config.vm.provision "shell", privileged: true, name: 'sonar-swift script', env: {"SONAR_PUBLIC_REPOSITORY" => "sonar-swift"}, inline: <<-SHELL + git clone -b master https://github.com/Backelite/$SONAR_PUBLIC_REPOSITORY.git ~/$SONAR_PUBLIC_REPOSITORY + cd ~/$SONAR_PUBLIC_REPOSITORY + git checkout develop + mv ~/$SONAR_PUBLIC_REPOSITORY/sonar-swift-plugin/src/main/shell/ /usr/local/opt/$SONAR_PUBLIC_REPOSITORY + rm -rf ~/$SONAR_PUBLIC_REPOSITORY + chmod +x /usr/local/opt/$SONAR_PUBLIC_REPOSITORY/run-sonar-swift.sh + echo export PATH=/usr/local/opt/$SONAR_PUBLIC_REPOSITORY:\$PATH >> /etc/profile + SHELL + + # Install java + config.vm.provision "shell", privileged: false, name: 'java', inline: <<-SHELL + /usr/local/bin/brew tap caskroom/versions + /usr/local/bin/brew cask install java + SHELL + + # Enable auto login + config.vm.provision "shell", privileged: false, name: 'enable auto login', inline: <<-SHELL + /usr/local/bin/brew tap xfreebird/utils + /usr/local/bin/brew install kcpassword + enable_autologin "${USERNAME}" "${USERNAME}" + SHELL + + # Reboot (to enable auto login) + #config.vm.provision :reload + + # Xcode + config.vm.provision "shell", privileged: false, name: 'xcode installation', inline: <<-SHELL + open -FWga "Archive Utility" --args /tmp/Xcode.xip + # Move Xcode to Applications directory + sudo mv ~/Downloads/Xcode.app /Applications/ + # Clean Xcode installation file + rm /tmp/Xcode.xip + # Accept Xcode licence + sudo xcode-select -s /Applications/Xcode.app/Contents/Developer + sudo xcodebuild -license accept + # Install XCode additional required components + for pkg in /Applications/Xcode.app/Contents/Resources/Packages/*.pkg; do sudo installer -pkg "$pkg" -target /; done + SHELL + + + # Simulator tools (require Xcode to be installed) + config.vm.provision "shell", privileged: false, name: 'ios simulator tools', inline: <<-SHELL + /usr/local/bin/brew tap wix/brew + /usr/local/bin/brew install applesimutils + /usr/local/bin/brew tap facebook/fb + SHELL + + # swiftlint (require Xcode to be installed) + config.vm.provision "shell", privileged: false, name: 'swiftlint installation', inline: <<-SHELL + /usr/local/bin/brew install swiftlint + SHELL + + # Cocoapods repository setup + config.vm.provision "shell", privileged: false, name: 'pod repository setup', inline: <<-SHELL + pod setup + SHELL + + # GitLab runner install + config.vm.provision "shell", privileged: false, name: 'gitlab-runner installation', inline: <<-SHELL + /usr/local/bin/brew install gitlab-runner + /usr/local/bin/brew services start gitlab-runner + # Registration + gitlab-runner register --non-interactive --url "#{GITLAB_URL}" --registration-token "#{GITLAB_REGISTRATION_TOKEN}" --executor "shell" --name "#{GITLAB_RUNNER_NAME}" --tag-list "#{GITLAB_RUNNER_TAGS}" + SHELL + + # Reboot + config.vm.provision :reload + +end diff --git a/scripts/start-simulator.sh b/scripts/start-simulator.sh new file mode 100755 index 0000000..870aee0 --- /dev/null +++ b/scripts/start-simulator.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# This script boots and starts an iOS simulator using its name as parameter +# It requires applesimutils to be installed (https://github.com/wix/AppleSimulatorUtils) + +if [ $# -eq 0 ]; then + echo "Usage $0 [name]" + exit 1 +fi + +simulator_name=$1 + +# Test is simulator is already booted +booted_udid=$(applesimutils --byName "$simulator_name" --booted -l | awk -F"[,:}]" '{for(i=1;i<=NF;i++){if($i~/'udid'\042/){print $(i+1)}}}' | tr -d '"' | sed -n 1p| tr -d '[:space:]') + +# If no : boot it +if [ "$booted_udid" = "" ]; then + udid=$(applesimutils --byName "$simulator_name" -l | awk -F"[,:}]" '{for(i=1;i<=NF;i++){if($i~/'udid'\042/){print $(i+1)}}}' | tr -d '"' | sed -n 1p| tr -d '[:space:]') + if [ "$udid" = "" ]; then + # Device not found + echo "No simulator with name \"$simulator_name\" found" + exit 1 + fi + xcrun simctl boot $udid +fi + +# Then start it +open /Applications/Xcode.app/Contents/Developer/Applications/Simulator.app/ \ No newline at end of file