-Поиск по дневнику

Поиск сообщений в rss_rss_hh_new

 -Подписка по e-mail

 

 -Статистика

Статистика LiveInternet.ru: показано количество хитов и посетителей
Создан: 17.03.2011
Записей:
Комментариев:
Написано: 51


Travis CI: автоматическая загрузка собранных модулей на GitHub

Понедельник, 18 Сентября 2017 г. 01:07 + в цитатник
mkulesh сегодня в 01:07 Разработка

Travis CI: автоматическая загрузка собранных модулей на GitHub


    В этой очень небольшой заметке я расскажу об очень небольшом усовершенствовании процесса автоматической сборки приложения в Travis CI. Я это проделал на примере Андроид-приложения, но, естественно, это будет работать и для других языков. Постановка задачи очень проста — участники сообщества попросили автоматически собирать в выкладывать приложение после каждого коммита в репозитории на GitHub. То есть речь идёт не о сборке фиксированных версий, а именно о «ежедневных» сборках, которые можно сразу же установить и тестировать, не дожидаясь официальной версии. Я, как разработчик, подобную заинтересованность могу только приветствовать, так как это сильно повышает качество обратной связи. Реализация этого процесса очень проста, только штатные средства GitHub и Travis CI, никакой магии. Так что я до сих пор сомневаюсь, стоит ли вообще о таком писать и отвлекать уважаемых хаброжителей от более серьёзных тем. Но если кто заинтересовался — прошу под кат.


    Я, как разработчик под Android, с интересом и удовольствием мониторю некоторые Open Source проекты на GitHub, которые прошли успешное испытание временем и активно развиваются, например: good-weather, AFWall+, Timber, Pedometer, AmazeFileManager, ConnectBot, K-9 Mail.


    У всех этих репозиториев есть два общих момента — в них настроена автоматическая сборка приложения на сервере Travis CI после каждого коммита, и результаты этой автоматической сборки так и остаются на сервере Travis CI, то есть собранное проложение просто удаляется. Я же, как уже сказал во введении, хочу извлечь пользу из этого собранного APK-файла и поместить его обратно в GitHub репозиторий, чтобы он был сразу же доступен участникам сообщества для тестирования.


    Travis CI предоставляет штатный метод загрузки собранного приложения на GitHub, но он предназначен для работы с тегами, то есть эта сборка, во первых, запускается при создании нового тега в GitHub-репозитории, и, во-вторых, позволяет загрузить APK-файл только в раздел GitHub Releases, но не в ветку репозитория. Так как создавать тег для каждого коммита — это, на мой взгляд, насилие над здравым смыслом, то этот метод я отбросил как несоответствующий духу и сути задачи.


    Командный файл Travis CI (.travis.yml), расположенный в корне репозитория, имеет простую структуру:


    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

    Этот скрипт выполняется на виртуальной машине в корне git-репозитория, который клонирован в т.н. "detached HEAD" режиме, то есть не позволяет напрямую закоммитить что-либо в мастер-ветку удалённого (то есть оригинального) GitHub-репозитория.
    Если внимательно посмотреть лог выполнения этого скрипта на виртуальной мишине, то в самом начале (секция git скрипта, которая в данном примере не сконфигурирована) Travis делает вот что:


    $ 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

    Именно git checkout -qf и переводит локальную ветку в "detached HEAD" режим.
    После того, как секция script отработала (в моём примере ./gradlew clean assembleDebug), и в директории ./app/build/outputs/apk появился сгенерированный APK-файл, вызывается секция after_success, где можно средствами Git закоммитить этот файл. Вопрос только, куда?


    Есть несколько вариантов.


    1) Можно использовать GitHub-Pages и помещать APK-файл туда, то есть коммитить в ветку gh-pages. Основной минус такого подхода в том, что GitHub-Pages рассчитаны на конечных пользователей, которые должны загружать приложение из официальных магазинов. Участники сообщества работают всё же с самим репозиторием, а не с GitHub-Pages. Поэтому я такой вариант не рассматриваю.


    2) Можно коммитить обратно в мастер-ветку GitHub-репозитория, например, в папку autobuild. В этом случае, нужно деактивировать "detached HEAD", закоммитить файл, авторизоваться в удалённом репозитории и выполнить push.


    install:
      - git checkout master
      - chmod +x ./autobuild/push-apk.sh
    after_success:
      - ./autobuild/push-apk.sh

    где push-apk.sh выглядит так:


    #!/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

    В данном варианте после каждого коммита в мастер-ветке GitHub-репозитория Travis будет делать ещё один коммит, где файл snapshot.apk будет также помещён в мастер-ветку. С одной стороны, удобно, что все в одном месте. С другой, этот файл также нужно постоянно синхронизировать в локальных репозиториях, что не очень удобно для разработчиков.


    3) Посте всех экспериментов мне больше всего понравился третий вариант. В репозитории создаётся ветка autobuild, но из неё удаляются все файлы и директории за исключением папки autobuild. Этот огрызок полноценной веткой не является, так как её нельзя синхронизировать с мастер-веткой. Скрипт push-apk.sh будет выглядеть в этом случае так:


    #!/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

    Последняя пара слов про авторизацию. За неё отвечает переменная окружения AUTOBUILD_TOKEN. Эта переменная задаётся в разделе


    env:
      global:
        secure: 

    Данный раздел содержит зашифрованный персональный ключ, который нужно сгенерировать на странице Personal access tokens. После чего он шифруется и добавляется в файл .travis.yml с помощью утилиты travis:


    sudo gem install travis
    echo AUTOBUILD_TOKEN= | travis encrypt --add -r user/repo

    Вот такое небольшое усовершенствование. Кому интересно, можно посмотреть рабочий вариант в этом репозитории.
    Удачного всем прогрева серверов непрерывной интеграции!

    Original source: habrahabr.ru (comments, light).

    https://habrahabr.ru/post/338126/

    Метки:  

     

    Добавить комментарий:
    Текст комментария: смайлики

    Проверка орфографии: (найти ошибки)

    Прикрепить картинку:

     Переводить URL в ссылку
     Подписаться на комментарии
     Подписать картинку