In this very small article I will talk about a very small improvement in the process of automatically assembling an application in Travis CI. I did this on the example of an Android application, but, of course, it will work for other languages ​​as well. Setting a task is very simple - community members are asked to automatically build in the upload application after each commit in the repository on GitHub. That is, we are not talking about the assembly of fixed versions, namely, the “daily” assemblies, which can be immediately installed and tested without waiting for the official version. I, as a developer, can only welcome such an interest, as this greatly improves the quality of feedback. The implementation of this process is very simple, only regular GitHub and Travis CI tools, no magic. So I still doubt whether it is worthwhile to write and divert respected habitues from more serious topics about this at all. But if anyone is interested - I ask under the cat.
I, as a developer for Android, with interest and pleasure, monitor some Open Source projects on GitHub that have passed the successful test of time and are actively developing, for example: good-weather , AFWall + , Timber , Pedometer , AmazeFileManager , ConnectBot , K-9 Mail .
All of these repositories have two common points - they automatically configure the application on the Travis CI server after each commit, and the results of this automatic assembly remain on the Travis CI server, that is, the assembled location is simply deleted. I, as I said in the introduction, want to take advantage of this compiled APK file and put it back into the GitHub repository so that it will be immediately available to community members for testing.
Travis CI provides a regular method for loading an assembled application on GitHub, but it is designed to work with tags, that is, this assembly, firstly, is launched when creating a new tag in the GitHub repository, and, secondly, allows you to download the APK file only section GitHub Releases, but not in the repository branch. Since creating a tag for each commit is, in my opinion, common sense violence, I rejected this method as inappropriate to the spirit and essence of the task.
The Travis CI command file (.travis.yml), located in the repository root, has a simple structure:
language: android jdk: oraclejdk8 android: components: - platform-tools - tools - build-tools-25.0.2 - android-25 - extra-android-m2repository branches: only: - master install: - chmod +x ./gradlew script: ./gradlew clean assembleDebug notifications: email: on_success: change on_failure: always
This script runs on a virtual machine in the root of the git repository, which is cloned into a so-called. The "detached HEAD" mode, that is, does not allow directly committing anything to the master branch of the remote (that is, original) GitHub repository.
If you look closely at the execution log of this script on the virtual target, then at the very beginning (the git section of the script, which is not configured in this example), Travis does this:
$ git clone --depth=50 --branch=master https://github.com/user/repo.git user/repo Cloning into 'user/repo'... $ cd user/repo $ git checkout -qf d7d29a59cef70bfce87dc4779e5cdc1e6356313a
It is git checkout -qf that puts the local branch in "detached HEAD" mode.
After the script section has completed (in my example ./gradlew clean assembleDebug), and a generated APK file appeared in the ./app/build/outputs/apk directory, the after_success section is called, where you can commit this file using Git. The only question is where?
There are several options.
1) You can use GitHub-Pages and put the APK file there, that is, commit it to the gh-pages branch. The main disadvantage of this approach is that GitHub-Pages are designed for end users who need to download the application from official stores. Community members work with the repository itself, not with GitHub-Pages. Therefore, I do not consider this option.
2) You can commit back to the master branch of the GitHub repository, for example, to the autobuild folder. In this case, you need to deactivate "detached HEAD", commit the file, log in to the remote repository and push.
install: - git checkout master - chmod +x ./autobuild/push-apk.sh after_success: - ./autobuild/push-apk.sh
where push-apk.sh looks like this:
#!/bin/sh mv ./app/build/outputs/apk/snapshot.apk ./autobuild/ git config --global user.email "travis@travis-ci.org" git config --global user.name "Travis CI" git remote add origin-master https://${AUTOBUILD_TOKEN}@github.com/user/repo > /dev/null 2>&1 git add ./autobuild/snapshot.apk # We don't want to run a build for a this commit in order to avoid circular builds: # add [ci skip] to the git commit message git commit --message "Snapshot autobuild N.$TRAVIS_BUILD_NUMBER [ci skip]" git push origin-master
In this variant, after each commit in the master branch of the GitHub repository, Travis will make another commit, where the snapshot.apk file will also be placed in the master branch. On the one hand, it is convenient that everything is in one place. On the other hand, this file also needs to be constantly synchronized in local repositories, which is not very convenient for developers.
3) After all experiments, I liked the third option the most. The autobuild branch is created in the repository, but all files and directories are deleted from it, with the exception of the autobuild folder. This stub is not a full-fledged branch, since it cannot be synchronized with the master branch. The push-apk.sh script will look like this in this case:
#!/bin/sh # Checkout autobuild branch cd .. git clone https://github.com/user/repo.git --branch autobuild --single-branch repo_autobuild cd repo_autobuild # Copy newly created APK into the target directory mv ../repo/app/build/outputs/apk/snapshot.apk ./autobuild # Setup git for commit and push git config --global user.email "travis@travis-ci.org" git config --global user.name "Travis CI" git remote add origin-master https://${AUTOBUILD_TOKEN}@github.com/user/repo > /dev/null 2>&1 git add ./autobuild/snapshot.apk # We don't want to run a build for a this commit in order to avoid circular builds: # add [ci skip] to the git commit message git commit --message "Snapshot autobuild N.$TRAVIS_BUILD_NUMBER [ci skip]" git push origin-master
Last couple of words about authorization. The environment variable AUTOBUILD_TOKEN is responsible for it. This variable is set in section
env: global: secure:
This section contains an encrypted private key that must be generated on the Personal access tokens page. After that, it is encrypted and added to the .travis.yml file using the travis utility:
sudo gem install travis echo AUTOBUILD_TOKEN=<Personal access token> | travis encrypt --add -r user/repo
Here is a little improvement. Who cares, you can see the working version in this repository .
Successful to all the warm-up servers for continuous integration!
Source: https://habr.com/ru/post/338126/
All Articles