Add input to set version code

Use action input `androidVersionCode` when provided. Generate the androidVersionCode from the version otherwise.
This commit is contained in:
Benoit Dion
2020-06-24 18:02:05 -04:00
committed by Webber Takken
parent 401ddcaae0
commit bdc3a88d22
17 changed files with 130 additions and 7 deletions
+1
View File
@@ -74,6 +74,7 @@ jobs:
projectPath: ${{ matrix.projectPath }} projectPath: ${{ matrix.projectPath }}
unityVersion: ${{ matrix.unityVersion }} unityVersion: ${{ matrix.unityVersion }}
targetPlatform: ${{ matrix.targetPlatform }} targetPlatform: ${{ matrix.targetPlatform }}
androidVersionCode: ${{ github.run_number }}
customParameters: -profile SomeProfile -someBoolean -someValue exampleValue customParameters: -profile SomeProfile -someBoolean -someValue exampleValue
- uses: actions/upload-artifact@v1 - uses: actions/upload-artifact@v1
with: with:
+6
View File
@@ -295,6 +295,12 @@ No version will be set by Builder. **(not recommended)**
> Not recommended unless you generate a new version in a pre-commit hook. Manually > Not recommended unless you generate a new version in a pre-commit hook. Manually
> setting versions is error-prone. > setting versions is error-prone.
#### androidVersionCode
Configure the android `versionCode`.
When not specified, the version code is generated from the version using the `major * 1000000 + minor * 1000 + patch` scheme;
#### allowDirtyBuild #### allowDirtyBuild
Allows the branch of the build to be dirty, and still generate the build. Allows the branch of the build to be dirty, and still generate the build.
+8
View File
@@ -26,6 +26,14 @@ inputs:
required: false required: false
default: '' default: ''
description: 'Path to a Namespace.Class.StaticMethod to run to perform the build.' description: 'Path to a Namespace.Class.StaticMethod to run to perform the build.'
versioning:
required: false
default: 'Semantic'
description: 'The versioning scheme to use when building the project'
androidVersionCode:
required: false
default: ''
description: 'The android versionCode'
outputs: {} outputs: {}
branding: branding:
icon: 'box' icon: 'box'
@@ -28,6 +28,7 @@ namespace UnityBuilderAction
// Set version for this build // Set version for this build
VersionApplicator.SetVersion(options["version"]); VersionApplicator.SetVersion(options["version"]);
VersionApplicator.SetAndroidVersionCode(options["androidVersionCode"]);
// Perform build // Perform build
BuildReport buildReport = BuildPipeline.BuildPlayer(buildOptions); BuildReport buildReport = BuildPipeline.BuildPlayer(buildOptions);
@@ -1,5 +1,4 @@
using System; using System;
using JetBrains.Annotations;
using UnityEditor; using UnityEditor;
namespace UnityBuilderAction.Versioning namespace UnityBuilderAction.Versioning
@@ -15,6 +14,10 @@ namespace UnityBuilderAction.Versioning
Apply(version); Apply(version);
} }
public static void SetAndroidVersionCode(string androidVersionCode) {
PlayerSettings.Android.bundleVersionCode = Int32.Parse(androidVersionCode);
}
static void Apply(string version) static void Apply(string version)
{ {
PlayerSettings.bundleVersion = version; PlayerSettings.bundleVersion = version;
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -109,8 +109,8 @@ xvfb-run --auto-servernum --server-args='-screen 0 640x480x24' \
-customBuildTarget "$BUILD_TARGET" \ -customBuildTarget "$BUILD_TARGET" \
-customBuildPath "$CUSTOM_BUILD_PATH" \ -customBuildPath "$CUSTOM_BUILD_PATH" \
-executeMethod "$BUILD_METHOD" \ -executeMethod "$BUILD_METHOD" \
-versioning "$VERSIONING" \
-version "$VERSION" \ -version "$VERSION" \
-androidVersionCode "$ANDROID_VERSION_CODE" \
$CUSTOM_PARAMETERS $CUSTOM_PARAMETERS
# Catch exit code # Catch exit code
+3 -1
View File
@@ -10,12 +10,14 @@
"prebuild": "yarn", "prebuild": "yarn",
"build": "ncc build src --out action --minify", "build": "ncc build src --out action --minify",
"lint": "prettier --check \"src/**/*.js\" && eslint src", "lint": "prettier --check \"src/**/*.js\" && eslint src",
"format": "prettier --write \"src/**/*.js\"",
"test": "jest" "test": "jest"
}, },
"dependencies": { "dependencies": {
"@actions/core": "^1.2.4", "@actions/core": "^1.2.4",
"@actions/exec": "1.0.4", "@actions/exec": "1.0.4",
"@actions/github": "^2.1.1" "@actions/github": "^2.1.1",
"semver": "^7.3.2"
}, },
"devDependencies": { "devDependencies": {
"@babel/cli": "7.8.4", "@babel/cli": "7.8.4",
+33
View File
@@ -0,0 +1,33 @@
import * as core from '@actions/core';
import * as semver from 'semver';
export default class AndroidVersioning {
static determineVersionCode(version, inputVersionCode) {
if (!inputVersionCode) {
return AndroidVersioning.versionToVersionCode(version);
}
return inputVersionCode;
}
static versionToVersionCode(version) {
const parsedVersion = semver.parse(version);
if (!parsedVersion) {
core.warning(`Could not parse "${version}" to semver, defaulting android version code to 1`);
return 1;
}
// The greatest value Google Plays allows is 2100000000.
// Allow for 3 patch digits, 3 minor digits and 3 major digits.
const versionCode =
parsedVersion.major * 1000000 + parsedVersion.minor * 1000 + parsedVersion.patch;
if (versionCode >= 1000000000) {
throw new Error(
`Generated versionCode ${versionCode} is dangerously close to the maximum allowed number 2100000000. Consider a different versioning scheme to be able to continue updating your application.`,
);
}
core.info(`Using android versionCode ${versionCode}`);
return versionCode;
}
}
+27
View File
@@ -0,0 +1,27 @@
import AndroidVersioning from './android-versioning';
describe('Android Versioning', () => {
describe('versionToVersionCode', () => {
it('defaults to 1 when version is not a valid semver', () => {
expect(AndroidVersioning.versionToVersionCode('abcd')).toBe(1);
});
it('returns a number', () => {
expect(AndroidVersioning.versionToVersionCode('123.456.789')).toBe(123456789);
});
it('throw when generated version code is too large', () => {
expect(() => AndroidVersioning.versionToVersionCode('1234.0.0')).toThrow();
});
});
describe('determineVersionCode', () => {
it('defaults to parsed version', () => {
expect(AndroidVersioning.determineVersionCode('1.2.3', '')).toBe(1002003);
});
it('use specified code', () => {
expect(AndroidVersioning.determineVersionCode('1.2.3', 2)).toBe(2);
});
});
});
+7
View File
@@ -1,3 +1,4 @@
import AndroidVersioning from './android-versioning';
import Input from './input'; import Input from './input';
import Platform from './platform'; import Platform from './platform';
import Versioning from './versioning'; import Versioning from './versioning';
@@ -10,6 +11,11 @@ class BuildParameters {
Input.specifiedVersion, Input.specifiedVersion,
); );
const androidVersionCode = AndroidVersioning.determineVersionCode(
buildVersion,
Input.androidVersionCode,
);
return { return {
version: Input.unityVersion, version: Input.unityVersion,
platform: Input.targetPlatform, platform: Input.targetPlatform,
@@ -19,6 +25,7 @@ class BuildParameters {
buildFile, buildFile,
buildMethod: Input.buildMethod, buildMethod: Input.buildMethod,
buildVersion, buildVersion,
androidVersionCode,
customParameters: Input.customParameters, customParameters: Input.customParameters,
}; };
} }
+16
View File
@@ -30,6 +30,22 @@ describe('BuildParameters', () => {
); );
}); });
it('returns the android version code with provided input', async () => {
const mockValue = '42';
jest.spyOn(Input, 'androidVersionCode', 'get').mockReturnValue(mockValue);
await expect(BuildParameters.create()).resolves.toEqual(
expect.objectContaining({ androidVersionCode: mockValue }),
);
});
it('returns the android version code from version by default', async () => {
const mockValue = '';
jest.spyOn(Input, 'androidVersionCode', 'get').mockReturnValue(mockValue);
await expect(BuildParameters.create()).resolves.toEqual(
expect.objectContaining({ androidVersionCode: 1003037 }),
);
});
it('returns the platform', async () => { it('returns the platform', async () => {
const mockValue = 'somePlatform'; const mockValue = 'somePlatform';
jest.spyOn(Input, 'targetPlatform', 'get').mockReturnValue(mockValue); jest.spyOn(Input, 'targetPlatform', 'get').mockReturnValue(mockValue);
+2
View File
@@ -29,6 +29,7 @@ class Docker {
buildMethod, buildMethod,
buildVersion, buildVersion,
customParameters, customParameters,
androidVersionCode,
} = parameters; } = parameters;
const command = `docker run \ const command = `docker run \
@@ -47,6 +48,7 @@ class Docker {
--env BUILD_FILE="${buildFile}" \ --env BUILD_FILE="${buildFile}" \
--env BUILD_METHOD="${buildMethod}" \ --env BUILD_METHOD="${buildMethod}" \
--env VERSION="${buildVersion}" \ --env VERSION="${buildVersion}" \
--env ANDROID_VERSION_CODE="${androidVersionCode}" \
--env CUSTOM_PARAMETERS="${customParameters}" \ --env CUSTOM_PARAMETERS="${customParameters}" \
--env HOME=/github/home \ --env HOME=/github/home \
--env GITHUB_REF \ --env GITHUB_REF \
+1 -1
View File
@@ -25,7 +25,7 @@ describe('Docker', () => {
const parameters = { const parameters = {
workspace: Action.rootFolder, workspace: Action.rootFolder,
projectPath: `${Action.rootFolder}/test-project`, projectPath: `${Action.rootFolder}/test-project`,
buildName: 'someBulidName', buildName: 'someBuildName',
buildsPath: 'build', buildsPath: 'build',
method: '', method: '',
}; };
+4
View File
@@ -41,6 +41,10 @@ class Input {
return core.getInput('version') || ''; return core.getInput('version') || '';
} }
static get androidVersionCode() {
return core.getInput('androidVersionCode');
}
static get allowDirtyBuild() { static get allowDirtyBuild() {
const input = core.getInput('allowDirtyBuild') || 'false'; const input = core.getInput('allowDirtyBuild') || 'false';
+13
View File
@@ -118,6 +118,19 @@ describe('Input', () => {
}); });
}); });
describe('androidVersionCode', () => {
it('defaults to null', () => {
expect(Input.androidVersionCode).toBeFalsy();
});
it('takes input from the users workflow', () => {
const mockValue = '42';
const spy = jest.spyOn(core, 'getInput').mockReturnValue(mockValue);
expect(Input.androidVersionCode).toStrictEqual(mockValue);
expect(spy).toHaveBeenCalledTimes(1);
});
});
describe('allowDirtyBuild', () => { describe('allowDirtyBuild', () => {
it('returns the default value', () => { it('returns the default value', () => {
expect(Input.allowDirtyBuild).toStrictEqual('false'); expect(Input.allowDirtyBuild).toStrictEqual('false');
+1 -1
View File
@@ -5045,7 +5045,7 @@ semver@^6.0.0, semver@^6.1.2, semver@^6.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
semver@^7.1.3: semver@^7.1.3, semver@^7.3.2:
version "7.3.2" version "7.3.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==