Post on 21-Jan-2017
Short info about Gitlab CIdifferences
RunnerA server that processes builds. It receives commands from
GitLab CI.Build
Execution of a particular job.Job
"Wrapped" bash script (before_script, "only" git ref, runner tags,cache...)Stage
Group of jobs. Builds of next stage are run after success ofprevious.
EnvironmentJust a group of deploy jobs for now. Later will have approvement
for each environment in chain.
Custom addonsBadges
Actually they are links to our static WEB server,
where gets exported coverage info, static analysis results
TL;DR: How to create CDprocess
both for beta and prod
Find a tool for working with stores (upload apk, ipa, uploadmetadata of app), get wraps for xcode, gradleExport your secrets (keys, accounts) into servers, make theseservers tagged Gitlab CI runnersCreate a super-tweaked job in .gitlab-ci.yml
Fastlane can (for us)...Run native tests (still a TODO)Build & sign xcode project in a CLI with dozen options (buildsgradle projects for sure)Upload builded bundle (apk, ipa) to store on all 3 channels forGPlay and TestFlight+AppStore for iOSAlso, upload app metadata (screenshots, description,changelogs...) on that storesSend slack messages by the way (may be useless...)
And magic Gitlab CI jobNot so magic, but how to do it?
A Condition: Fastlane lanes are written (build, deploy for android &iOS), remote servers handle it just �ne, they attached to Gitlab CI as
runners and have tags
Build: Job depends on npm test job. run fastlane ios build on abuild stage, capture your XCode archive and ipa as artifactsDeploy: Job depends on build job. run fastlane ios beta on adeploy stage, on some environment beta and prodAlmost same for android
A code snippet for ios buildNotice that react-native packager terrible workaround
ios:build: before_script: - source /etc/profile - export PATH="$CI_PROJECT_DIR/node_modules/.bin:$PATH" - nvm use - npm set progress=false && npm prune && npm install && npm set progress=true stage: build script: - react-native start & - sleep 2 - kill_packager () { kill -9 $(lsof -n -ti4TCP:8081); kill -9 $(lsof -at -c node -c watchman $CI_PROJECT_DIR $CI_PROJECT_DIR/node_modules/react-native/packager); } - fastlane ios build && kill_packager || (kill_packager; exit 2) dependencies: - run:node artifacts: paths: - Break a Сode.ipa - Mastermind.xcarchive tags: - nvm - xcode - fastlane cache: key: "$CI_BUILD_REF_NAME" paths: - node_modules/
Code snippet for ios deploy toTestFlight
ios:deploy:beta: before_script: - source /etc/profile stage: deploy environment: beta script: - export FL_IOS_BUILD_VERSION=$(git describe --tags --abbrev=0 \ --contain --match "v[0-9]*" 2>/dev/null | \ sed 's/.*v\([0-9\.]*\).*/\1/' 2>/dev/null); - '[ "$FL_IOS_BUILD_VERSION" ] \ && echo "Deploy $FL_IOS_BUILD_VERSION to beta" \ || (echo "Skip deploy to beta channel" 1>&2 ; exit 2)' - fastlane ios beta only: - /̂v[0-9\.]+$/ dependencies: - ios:build tags: - xcode - fastlane
About versioningA contract: v1.0 for beta releases, v1.0-production for production
releases
Use git tags for deploymentRestrict executing of deploy jobs for that git tags with a regexp:/^v[0-9\.]+/ for beta and /^v[0-9\.]+-production/Use git commit count as a version code (xcode) or build number(gradle)In a job scripts, capture git tag and use it as version nameIf no git tag speci�ed, use 0.0.1 by default (fallback)
Code for versioningSHORT_VERSION=$(git --git-dir="${PROJECT_DIR}/../.git" describe \ --tags --abbrev=0 --contain --match "v[0-9]*" | \ sed 's/.*v\([0-9\.]*\).*/\1/' 2>/dev/null)
VERSION=$(git --git-dir="${PROJECT_DIR}/../.git" rev-list \ --no-merges --count master)
APP_INFO_PLIST_PATH="${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
defaults write "$APP_INFO_PLIST_PATH" CFBundleShortVersionString $SHORT_VERSION defaults write "$APP_INFO_PLIST_PATH" CFBundleVersion $VERSION
BootstrappinReact Native provides generator which created xcode project and
android project
Next steps: npm install, code and have fun!
Things to use with RNEslint with custom .eslintrcFlow (integrates with Nuclide, RN IDE)Jest (test runner)Redux (mix of �ux, elm...)
Github flowMaster is always stable and deployableFor every feature (or bug�x) new branch is created from masterDeveloper pushes feature branch on a server many timesAfter work seems done, developer creates Pull Request intomasterAfter PR gets merged into master, feature branch is removed
Redux ducksTL;DR; actionCreators, actionTypes, reducers are in one �le
And:
ducks export default a reducer functionexports actionTypes and actionCreators as named exportsactionType naming form: module/actionactionType variable is UPPER_UNDERSCORE_CASE
How my commit getsdeployed?
1. It gets reviewed on Merge Request �rst2. At same time, CI server runs [unit] tests and analyzes coverage3. After commit gets merged into master, CI server runs [unit] tests
for master branch4. After "Green", build job are launched for iOS and android in
parallel, resulting in artifacts (ipa + apk)5. Then, after "Green" build, on a master branch, nothing is
happened6. We download artifacts, launch and test (if you want), then add a
tag on that commit7. Gitlab CI runs all sequence of test+build for tag ref (v1.0)8. Then, �nally, it runs deploy job for git tag ref. Channel (beta, prod)
is selected by tag name (v1.0 for beta, v1.0-production for
is selected by tag name (v1.0 for beta, v1.0-production forproduction)
RollbackStores are immutable, so you need to add a next version with patch
version bump and release itv1.0 ➡ OMG, fail ➡ git bisect to stable or fix a bug ➡ v1.0.1
THE ENDPresentation Max Sysoev. My GitHub: Our organization on GitHub:
github.com/ColChgithub.com/Lingvokot