React Native - автоматическое имя версии из package.json для манифеста сборки Android

В настоящее время у меня есть собственное приложение реагирования, и проблема в том, что обновление версии при каждой сборке или фиксации занимает очень много времени.

Кроме того, у меня включен Sentry, поэтому каждый раз, когда я строю, некоторые сборки получают одну и ту же версию, поэтому некоторые сбои трудно определить, откуда они взялись.

Наконец, обновление версии вручную подвержено ошибкам.

Как я могу настроить свои сборки так, чтобы они генерировали автоматическую версию каждый раз, когда я собираюсь и забываю обо всем этом ручном задании?

1 ответ

Хотя принятый в настоящее время ответ будет работать, существует гораздо более простой и, следовательно, более надежный способ сделать это. Вы можете фактически прочитать значение, установленное в package.json прямо из build.gradle,

Изменить ваш android/app/build.gradle:

// On top of your file import a JSON parser
import groovy.json.JsonSlurper

// Create an easy to use function
def getVersionFromNpm() {
    //  Read and parse package.json file from project root
    def inputFile = new File("$rootDir/../package.json")
    def packageJson = new JsonSlurper().parseText(inputFile.text)

    // Return the version, you can get any value this way
    return packageJson["version"]
}

android {
    defaultConfig {
        applicationId "your.app.id"
        versionName getVersionFromNpm()
    }
}

Таким образом, вам не понадобится сценарий предварительной сборки или что-то еще, он просто будет работать.

Поскольку я работал с этим в течение нескольких дней, я решил поделиться со всеми, как я это сделал, потому что это может помочь другим.

Используемые инструменты:

  1. GitVersion: мы будем использовать GitVersion для автоматической генерации семантической версии в зависимости от многих факторов, таких как текущая ветвь, теги, коммиты и т. Д. Toold делает отличную работу, и вы можете забыть об именовании ваших версий. Конечно, если вы установите тег для коммита, он будет использовать этот тег в качестве имени.
  2. PowerShell: эта ОС командной строки, созданная Microsoft, может работать на Mac, Linux или Windows, и я выбрал ее, потому что сборки могут не зависеть от версии ОС. Например, я занимаюсь разработкой под Windows, но на сборочной машине установлен MacOS.

Редактировать приложение build.gradle

Приложение Gradle нуждается только в одной строке, добавленной в конце. В моем случае у меня есть Gradle Google Play Services, и я добавил его после этого.

apply from: 'version.gradle'

version.gradle

Этот файл должен находиться в той же папке, что и приложение, и это содержимое:

task updatePackage(type: Exec, description: 'Updating package.json') {
    commandLine 'powershell', ' -command ' , '$semver=(gitversion /showvariable Semver); Set-Content -path version.properties -value semver=$semver; npm version --no-git-tag-version --allow-same-version $semver'  
}
preBuild.dependsOn updatePackage

task setVariantVersion {

    doLast {

        if (plugins.hasPlugin('android') || plugins.hasPlugin('android-library')) {

            def autoIncrementVariant = { variant ->
                variant.mergedFlavor.versionName = calculateVersionName()
            }

            if (plugins.hasPlugin('android')){
                //Fails without putting android. first
                android.applicationVariants.all { variant -> autoIncrementVariant(variant) }
            }

            if (plugins.hasPlugin('android-library')) {
                //Probably needs android-library before libraryVariants. Needs testing
                libraryVariants.all { variant -> autoIncrementVariant(variant) }
            }
        }

    }

}
preBuild.dependsOn setVariantVersion
setVariantVersion.mustRunAfter updatePackage

ext {
    versionFile = new File('version.properties')
    calculateVersionName = {
        def version = readVersion()
        def semver = "Unknown"
        if (version != null){
            semver = version.getProperty('semver')
        }
        return semver
    }
}

Properties readVersion() {
    //It gets called once for every variant but all get the same version
    def version = new Properties()
    try {
        file(versionFile).withInputStream { version.load(it) }
    } catch (Exception error) {
        version = null
    } 
    return version
}

Теперь давайте рассмотрим, что на самом деле делает скрипт:

  1. updatePackage: эта задача выполняется в самом начале вашей сборки (фактически до preBuild) и выполняет gitversion для получения текущей версии, а затем создает файл version.properties, который впоследствии будет прочитан gradle для получения версии.
  2. setVariantVersion: это вызывается afterEvaluate для каждого варианта. Это означает, что если у вас есть несколько сборок, таких как отладка, выпуск, qa, постановка и т. Д., Все получат одну и ту же версию. Для моего варианта использования это хорошо, но вы можете настроить это.
  3. Порядок задач: меня беспокоило то, что версия запускалась до того, как файл был сгенерирован. Это исправлено с помощью тега mustRunAfter.

Сценарий PowerShell объяснил

Это скрипт, который запускается первым. Давайте рассмотрим, что делает:

$semver=(gitversion /showvariable Semver);
Set-Content -path props.properties -value semver=$semver; 
npm version --no-git-tag-version --allow-same-version $semver
  1. Строка 1: Gitversion имеет несколько типов версий. Если вы запустите его без каких-либо параметров, вы получите файл json с большим количеством вариантов. Здесь мы говорим, что мы хотим только SemVer. (Смотрите также FullSemVer)
  2. Строка 2: PowerShell способ создать файл и сохранить его содержимое. Это также можно сделать с помощью>, но у меня были проблемы с кодировкой, и файл свойств не читался.
  3. Строка 3: эта строка обновляет вашу версию package.json. По умолчанию он сохраняет коммит в git с новой версией. --no-git-tag-version гарантирует, что вы не переопределите его.

И это все. Теперь каждый раз, когда вы делаете сборку, версия должна генерироваться автоматически, ваш package.json обновляется, и ваша сборка должна иметь это конкретное имя версии.

Центр приложений

Поскольку я использую Центр приложений для создания сборок, я расскажу вам, как вы можете использовать это на компьютере сборки. Вам нужно только использовать собственный скрипт.

app-center-pre-build.sh

#!/usr/bin/env sh
#Installing GitVersion
OS=$(uname -s)
if [[ $OS == *"W64"* ]]; then
    echo "Installing GitVersion with Choco"
    choco install GitVersion.Portable -y
else 
    echo "Installing GitVersion with Homebrew"
    brew install --ignore-dependencies gitversion
fi

Это необходимо, потому что GitVersion в настоящее время не является частью машин сборки. Кроме того, вам нужно игнорировать моно-зависимость при установке, иначе вы получите ошибку, когда brew попытается связать файлы.

Версия @MacRusher мне подошла. Для дальнейших читателей мне пришлось добавить.toInteger(), чтобы он заработал. Поскольку я использую yarn version --patch для автоматического обновления версии в package.json, мне также пришлось взять только два первых символа.

Вот новая версия:

// On top of your file import a JSON parser
import groovy.json.JsonSlurper

def getVersionFromPackageJson() {
    //  Read and parse package.json file from project root
    def inputFile = new File("$rootDir/../package.json")
    def packageJson = new JsonSlurper().parseText(inputFile.text)

    // Return the version, you can get any value this way
    return packageJson["version"].substring(0,2).toInteger()
}

android {
    defaultConfig {
        applicationId "your.app.id"
        versionName getVersionFromPackageJson()
    }
}
Другие вопросы по тегам