mirror of
https://github.com/game-ci/unity-builder.git
synced 2026-01-29 20:39:07 +08:00
Compare commits
28 Commits
v0.13
...
check-inte
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03391a19f1 | ||
|
|
fdcb37075f | ||
|
|
229b0d02f8 | ||
|
|
c68bdf8177 | ||
|
|
938926799f | ||
|
|
5efb4868ad | ||
|
|
7749b8862d | ||
|
|
98a56c4169 | ||
|
|
720ee0c896 | ||
|
|
d42c251af3 | ||
|
|
bfe6be7ce2 | ||
|
|
f15f40d265 | ||
|
|
866f364f64 | ||
|
|
a245f08e75 | ||
|
|
21c211bbdd | ||
|
|
3718e05961 | ||
|
|
0159028bb1 | ||
|
|
054c6bfab3 | ||
|
|
8c9ff3249e | ||
|
|
7386c669ad | ||
|
|
ce865270c4 | ||
|
|
7e17091251 | ||
|
|
02ff5bbef2 | ||
|
|
8c177b1bad | ||
|
|
699621ed21 | ||
|
|
44bde7feb9 | ||
|
|
5328bda08e | ||
|
|
34e4b86924 |
29
.github/workflows/activation.yml
vendored
Normal file
29
.github/workflows/activation.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
#name: Acquire activation file
|
||||
#
|
||||
#on: [push]
|
||||
#
|
||||
#jobs:
|
||||
# activation:
|
||||
# name: Request manual activation file (${{ matrix.unityVersion }}) 🔑
|
||||
# runs-on: ubuntu-latest
|
||||
# strategy:
|
||||
# fail-fast: false
|
||||
# matrix:
|
||||
# unityVersion:
|
||||
# - 2019.2.11f1
|
||||
# - 2019.3.15f1
|
||||
#
|
||||
# steps:
|
||||
# # Request manual activation file
|
||||
# - name: Request manual activation file
|
||||
# id: getManualLicenseFile
|
||||
# uses: webbertakken/unity-request-manual-activation-file@v1.1
|
||||
# with:
|
||||
# unityVersion: ${{ matrix.unityVersion }}
|
||||
#
|
||||
# # Upload artifact (Unity_v20XX.X.XXXX.alf)
|
||||
# - name: Expose as artifact
|
||||
# uses: actions/upload-artifact@v1
|
||||
# with:
|
||||
# name: ${{ steps.getManualLicenseFile.outputs.filePath }}
|
||||
# path: ${{ steps.getManualLicenseFile.outputs.filePath }}
|
||||
21
.github/workflows/main.yml
vendored
21
.github/workflows/main.yml
vendored
@@ -2,10 +2,9 @@ name: Actions 😎
|
||||
|
||||
on:
|
||||
pull_request: {}
|
||||
push: { branches: [master] }
|
||||
push: { branches: [master, check-internal-push] }
|
||||
|
||||
env:
|
||||
UNITY_LICENSE: "<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>\n <License id=\"Terms\">\n <MachineBindings>\n <Binding Key=\"1\" Value=\"d39b8e2f4d364b2e98b06afa0c6e08c5\"/>\n <Binding Key=\"2\" Value=\"d39b8e2f4d364b2e98b06afa0c6e08c5\"/>\n </MachineBindings>\n <MachineID Value=\"Xxo1ZKbdPu/IATrc0mPBYANJFF0=\"/>\n <SerialHash Value=\"1efd68fa935192b6090ac03c77d289a9f588c55a\"/>\n <Features>\n <Feature Value=\"33\"/>\n <Feature Value=\"1\"/>\n <Feature Value=\"12\"/>\n <Feature Value=\"2\"/>\n <Feature Value=\"24\"/>\n <Feature Value=\"3\"/>\n <Feature Value=\"36\"/>\n <Feature Value=\"17\"/>\n <Feature Value=\"19\"/>\n <Feature Value=\"62\"/>\n </Features>\n <DeveloperData Value=\"AQAAAEY0LUg2WFMtUE00NS1SM0M4LUUyWlotWkdWOA==\"/>\n <SerialMasked Value=\"F4-H6XS-PM45-R3C8-E2ZZ-XXXX\"/>\n <StartDate Value=\"2018-05-02T00:00:00\"/>\n <UpdateDate Value=\"2019-11-25T18:23:38\"/>\n <InitialActivationDate Value=\"2018-05-02T14:21:28\"/>\n <LicenseVersion Value=\"6.x\"/>\n <ClientProvidedVersion Value=\"2019.2.11f1\"/>\n <AlwaysOnline Value=\"false\"/>\n <Entitlements>\n <Entitlement Ns=\"unity_editor\" Tag=\"UnityPersonal\" Type=\"EDITOR\" ValidTo=\"9999-12-31T00:00:00\"/>\n </Entitlements>\n </License>\n<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#Terms\"><Transforms><Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>JHdOBFmBNq2H8BrGFzir/StLoYo=</DigestValue></Reference></SignedInfo><SignatureValue>aENLHd37a51RtP2/g7YU0Pexf5mx0/ENXYGtrPzqwZ8NQt2AsSdxGnl0CUB45/GuNXfJVDt2HWot\ncNYZB2OylVBn1WHQbKZlPmm8gEAMz0MYbr4Isb5i5buryBrZlmbEOjnRI+pEg1CBwlgMo6xdtjjE\n/d7cC293QIUO91kdzRXftYou1dNaUyuPL9ZH65vdB2pDXGRNxgUVD+GnnqZA7b5L2HXqNQclcWAK\n5Yd1BeF3VzR1iLw9G/SmH5oOhnpXSmqbL4qk7LVP2/mgXpFk5kP4X8VC3z47obNhBIGq40dwWyEe\nUYk5/nRAOkZawDT+tcu96e06gPC9Cxk5PdbRbA==</SignatureValue></Signature></root>"
|
||||
CODECOV_TOKEN: '2f2eb890-30e2-4724-83eb-7633832cf0de'
|
||||
|
||||
jobs:
|
||||
@@ -34,7 +33,15 @@ jobs:
|
||||
- test-project
|
||||
unityVersion:
|
||||
- 2019.2.11f1
|
||||
# - 2019.3.0f1 # requires different license file/method
|
||||
- 2019.3.15f1
|
||||
include:
|
||||
# Please be polite; don't copy my personal licenses.
|
||||
# These are here because they are needed to allowing pull requests from forks to unity-builder.
|
||||
# You should be using ${{ secrets.UNITY_LICENSE_2019_3_15 }} here.
|
||||
- unityVersion: 2019.2.11f1
|
||||
license: "<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>\n <License id=\"Terms\">\n <MachineBindings>\n <Binding Key=\"1\" Value=\"d39b8e2f4d364b2e98b06afa0c6e08c5\"/>\n <Binding Key=\"2\" Value=\"d39b8e2f4d364b2e98b06afa0c6e08c5\"/>\n </MachineBindings>\n <MachineID Value=\"Xxo1ZKbdPu/IATrc0mPBYANJFF0=\"/>\n <SerialHash Value=\"1efd68fa935192b6090ac03c77d289a9f588c55a\"/>\n <Features>\n <Feature Value=\"33\"/>\n <Feature Value=\"1\"/>\n <Feature Value=\"12\"/>\n <Feature Value=\"2\"/>\n <Feature Value=\"24\"/>\n <Feature Value=\"3\"/>\n <Feature Value=\"36\"/>\n <Feature Value=\"17\"/>\n <Feature Value=\"19\"/>\n <Feature Value=\"62\"/>\n </Features>\n <DeveloperData Value=\"AQAAAEY0LUg2WFMtUE00NS1SM0M4LUUyWlotWkdWOA==\"/>\n <SerialMasked Value=\"F4-H6XS-PM45-R3C8-E2ZZ-XXXX\"/>\n <StartDate Value=\"2018-05-02T00:00:00\"/>\n <UpdateDate Value=\"2019-11-25T18:23:38\"/>\n <InitialActivationDate Value=\"2018-05-02T14:21:28\"/>\n <LicenseVersion Value=\"6.x\"/>\n <ClientProvidedVersion Value=\"2019.2.11f1\"/>\n <AlwaysOnline Value=\"false\"/>\n <Entitlements>\n <Entitlement Ns=\"unity_editor\" Tag=\"UnityPersonal\" Type=\"EDITOR\" ValidTo=\"9999-12-31T00:00:00\"/>\n </Entitlements>\n </License>\n<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#Terms\"><Transforms><Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>JHdOBFmBNq2H8BrGFzir/StLoYo=</DigestValue></Reference></SignedInfo><SignatureValue>aENLHd37a51RtP2/g7YU0Pexf5mx0/ENXYGtrPzqwZ8NQt2AsSdxGnl0CUB45/GuNXfJVDt2HWot\ncNYZB2OylVBn1WHQbKZlPmm8gEAMz0MYbr4Isb5i5buryBrZlmbEOjnRI+pEg1CBwlgMo6xdtjjE\n/d7cC293QIUO91kdzRXftYou1dNaUyuPL9ZH65vdB2pDXGRNxgUVD+GnnqZA7b5L2HXqNQclcWAK\n5Yd1BeF3VzR1iLw9G/SmH5oOhnpXSmqbL4qk7LVP2/mgXpFk5kP4X8VC3z47obNhBIGq40dwWyEe\nUYk5/nRAOkZawDT+tcu96e06gPC9Cxk5PdbRbA==</SignatureValue></Signature></root>"
|
||||
- unityVersion: 2019.3.15f1
|
||||
license: "<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>\n <License id=\"Terms\">\n <MachineBindings>\n <Binding Key=\"1\" Value=\"33bf639e81e54693a8f9bf57c8900e5a\"/>\n <Binding Key=\"2\" Value=\"33bf639e81e54693a8f9bf57c8900e5a\"/>\n </MachineBindings>\n <MachineID Value=\"xWka2iXdDJejhZdi/zU2RUeXUi4=\"/>\n <SerialHash Value=\"1efd68fa935192b6090ac03c77d289a9f588c55a\"/>\n <Features>\n <Feature Value=\"33\"/>\n <Feature Value=\"1\"/>\n <Feature Value=\"12\"/>\n <Feature Value=\"2\"/>\n <Feature Value=\"24\"/>\n <Feature Value=\"3\"/>\n <Feature Value=\"36\"/>\n <Feature Value=\"17\"/>\n <Feature Value=\"19\"/>\n <Feature Value=\"62\"/>\n </Features>\n <DeveloperData Value=\"AQAAAEY0LUg2WFMtUE00NS1SM0M4LUUyWlotWkdWOA==\"/>\n <SerialMasked Value=\"F4-H6XS-PM45-R3C8-E2ZZ-XXXX\"/>\n <StartDate Value=\"2018-05-02T00:00:00\"/>\n <UpdateDate Value=\"2020-06-14T13:49:47\"/>\n <InitialActivationDate Value=\"2018-05-02T14:21:28\"/>\n <LicenseVersion Value=\"6.x\"/>\n <ClientProvidedVersion Value=\"2019.3.15f1\"/>\n <AlwaysOnline Value=\"false\"/>\n <Entitlements>\n <Entitlement Ns=\"unity_editor\" Tag=\"UnityPersonal\" Type=\"EDITOR\" ValidTo=\"9999-12-31T00:00:00\"/>\n </Entitlements>\n </License>\n<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#Terms\"><Transforms><Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>bpzWx3PZ0lqWDo1m9aLQuZ4cweo=</DigestValue></Reference></SignedInfo><SignatureValue>QcDm4/qAXZuUMQbUVk63vO6u66Bp8PnqqWQcZZOcym/rGUZLj1sr66EquF3X3w1L7aqiwMGtbY2b\nkPttcalFeaBkc5NsJMrexWjuBCxQvhbmVFQnTjvC6vNS+k1wrkz7If1oPkz/XaDtCfUs8oxc9iPe\nPzzUJIVYLZoDtpPq2XbgVn9/TiVb3Zu6ldKgvtNRYUjrB3KywtvL9OcIFll3htRcBZPG43kxryJc\nDD2TL5Nw1JuX6MejBBuYTZsZNpGX9Pjop9+uFUZ4GI9h8a5g6wJUfXzsGw7j4gkvDkC9MvyWiksi\n2hNXw1QNeB6JfQsd4sAuhYh/CqTm2gCz9i9ZpA==</SignatureValue></Signature></root>"
|
||||
targetPlatform:
|
||||
- StandaloneOSX # Build a macOS standalone (Intel 64-bit).
|
||||
- StandaloneWindows # Build a Windows standalone.
|
||||
@@ -42,7 +49,7 @@ jobs:
|
||||
- StandaloneLinux64 # Build a Linux 64-bit standalone.
|
||||
- iOS # Build an iOS player.
|
||||
# - Android # Build an Android .apk standalone app.
|
||||
- WebGL # WebGL.
|
||||
# - WebGL # WebGL.
|
||||
# - WSAPlayer # Build an Windows Store Apps player.
|
||||
# - PS4 # Build a PS4 Standalone.
|
||||
# - XboxOne # Build a Xbox One Standalone.
|
||||
@@ -60,7 +67,9 @@ jobs:
|
||||
restore-keys: |
|
||||
Library-${{ matrix.projectPath }}-
|
||||
Library-
|
||||
- uses: ./
|
||||
- uses: webbertakken/unity-builder@8ae8dbb
|
||||
env:
|
||||
UNITY_LICENSE: ${{ matrix.license }}
|
||||
with:
|
||||
projectPath: ${{ matrix.projectPath }}
|
||||
unityVersion: ${{ matrix.unityVersion }}
|
||||
@@ -68,5 +77,5 @@ jobs:
|
||||
customParameters: -profile SomeProfile -someBoolean -someValue exampleValue
|
||||
- uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: Build
|
||||
name: Build (${{ matrix.unityVersion }})
|
||||
path: build
|
||||
|
||||
85
README.md
85
README.md
@@ -1,7 +1,6 @@
|
||||
# Unity - Builder
|
||||
|
||||
[](https://github.com/webbertakken/unity-builder/actions?query=branch%3Amaster+event%3Apush+workflow%3A%22Actions+%F0%9F%98%8E%22)
|
||||
[](https://snyk.io/test/github/webbertakken/unity-builder)
|
||||
[](https://lgtm.com/projects/g/webbertakken/unity-builder/context:javascript)
|
||||
[](https://codecov.io/gh/webbertakken/unity-builder)
|
||||
|
||||
@@ -51,7 +50,7 @@ your license file and add it as a secret.
|
||||
Then, define the build step as follows:
|
||||
|
||||
```yaml
|
||||
- uses: webbertakken/unity-builder@v0.11
|
||||
- uses: webbertakken/unity-builder@<version>
|
||||
env:
|
||||
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
|
||||
with:
|
||||
@@ -73,7 +72,7 @@ Instead, three variables will need to be set.
|
||||
Define the build step as follows:
|
||||
|
||||
```yaml
|
||||
- uses: webbertakken/unity-builder@v0.11
|
||||
- uses: webbertakken/unity-builder@<version>
|
||||
env:
|
||||
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
|
||||
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
|
||||
@@ -177,7 +176,7 @@ jobs:
|
||||
restore-keys: |
|
||||
Library-${{ matrix.projectPath }}-
|
||||
Library-
|
||||
- uses: webbertakken/unity-builder@v0.11
|
||||
- uses: webbertakken/unity-builder@<version>
|
||||
with:
|
||||
projectPath: ${{ matrix.projectPath }}
|
||||
unityVersion: ${{ matrix.unityVersion }}
|
||||
@@ -255,33 +254,7 @@ _**default:** Built-in script that will run a build out of the box._
|
||||
|
||||
#### versioning
|
||||
|
||||
The versioning strategy to use.
|
||||
|
||||
Strategies only work when no custom buildMethod is specified.
|
||||
|
||||
_**required:** `false`_
|
||||
_**default:** `Auto`_
|
||||
|
||||
#### _These are the available strategies:_
|
||||
|
||||
##### None
|
||||
|
||||
No version will be set by Builder.
|
||||
|
||||
```yaml
|
||||
- uses: webbertakken/unity-builder@<version>
|
||||
with:
|
||||
versioning: None
|
||||
```
|
||||
|
||||
Note that the version set in the project will be used instead.
|
||||
|
||||
##### Semantic (default)
|
||||
|
||||
Builder automatically generates a version based on [semantic versioning](https://semver.org/) out of the box.
|
||||
|
||||
The version works as follows: `<major>.<minor>.<patch>` for example `0.1.2`.
|
||||
The latest tag dictates `<major>.<minor>` and the number of commits since that tag is used in `<patch>`.
|
||||
Configure a specific versioning strategy
|
||||
|
||||
```yaml
|
||||
- uses: webbertakken/unity-builder@<version>
|
||||
@@ -289,40 +262,52 @@ The latest tag dictates `<major>.<minor>` and the number of commits since that t
|
||||
versioning: Semantic
|
||||
```
|
||||
|
||||
This strategy works well for the following reasons:
|
||||
Find the available strategies below:
|
||||
|
||||
- All builds have their unique version
|
||||
- No version related commits are created
|
||||
- No knowledge of git or versioning is required
|
||||
- Developer keeps control over `major` and `minor` versions using tags.
|
||||
- Zero configuration; It works out of the box
|
||||
##### Semantic
|
||||
|
||||
##### Tag
|
||||
Versioning out of the box! **(recommended)**
|
||||
|
||||
Uses the tag that points at `HEAD` as the version.
|
||||
> Compatible with **all platforms**.
|
||||
> Does **not** modify your repository.
|
||||
> Requires **zero configuration**.
|
||||
|
||||
```yaml
|
||||
- uses: webbertakken/unity-builder@<version>
|
||||
with:
|
||||
versioning: Tag
|
||||
```
|
||||
How it works:
|
||||
|
||||
This strategy works well when using a pipeline that specifically runs for tags.
|
||||
> Generates a version based on [semantic versioning](https://semver.org/).
|
||||
> Follows `<major>.<minor>.<patch>` for example `0.17.2`.
|
||||
> The latest tag dictates `<major>.<minor>` (defaults to 0.0 for no tag).
|
||||
> The number of commits (since the last tag, if any) is used for `<patch>`.
|
||||
|
||||
The tag must be a version tag.
|
||||
No configuration required.
|
||||
|
||||
##### Custom
|
||||
|
||||
Allows specifying a custom version in the `version` field.
|
||||
Allows specifying a custom version in the `version` field. **(advanced users)**
|
||||
|
||||
> This strategy is useful when your project or pipeline has some kind of orchestration
|
||||
> that determines the versions.
|
||||
|
||||
##### None
|
||||
|
||||
No version will be set by Builder. **(not recommended)**
|
||||
|
||||
> Not recommended unless you generate a new version in a pre-commit hook. Manually
|
||||
> setting versions is error-prone.
|
||||
|
||||
#### allowDirtyBuild
|
||||
|
||||
Allows the branch of the build to be dirty, and still generate the build.
|
||||
|
||||
```yaml
|
||||
- uses: webbertakken/unity-builder@<version>
|
||||
with:
|
||||
versioning: Custom
|
||||
version: <some_version>
|
||||
allowDirtyBuild: true
|
||||
```
|
||||
|
||||
If there is a use case missing from Builder, feel free to create a feature request.
|
||||
Note that it is generally bad practice to modify your branch
|
||||
in a CI Pipeline. However there are exceptions where this might
|
||||
be needed. (use with care).
|
||||
|
||||
#### customParameters
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -123,6 +123,13 @@ else
|
||||
echo "Build failed, with exit code $BUILD_EXIT_CODE";
|
||||
fi
|
||||
|
||||
# Add permissions to make app runnable
|
||||
if [[ "$BUILD_TARGET" == "StandaloneOSX" ]]; then
|
||||
ADD_PERMISSIONS_PATH=$BUILD_PATH_FULL/StandaloneOSX.app/Contents/MacOS/*
|
||||
echo "Making the following path executable: $ADD_PERMISSIONS_PATH"
|
||||
chmod +x $ADD_PERMISSIONS_PATH
|
||||
fi
|
||||
|
||||
#
|
||||
# Results
|
||||
#
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Action, BuildParameters, Cache, Docker, Input, ImageTag } from './model';
|
||||
import { Action, BuildParameters, Cache, Docker, ImageTag } from './model';
|
||||
|
||||
const core = require('@actions/core');
|
||||
|
||||
@@ -7,7 +7,8 @@ async function action() {
|
||||
Cache.verify();
|
||||
|
||||
const { dockerfile, workspace, actionFolder } = Action;
|
||||
const buildParameters = BuildParameters.create(await Input.getFromUser());
|
||||
|
||||
const buildParameters = await BuildParameters.create();
|
||||
const baseImage = new ImageTag(buildParameters);
|
||||
|
||||
// Build docker image
|
||||
|
||||
@@ -26,4 +26,24 @@ expect.extend({
|
||||
pass,
|
||||
};
|
||||
},
|
||||
|
||||
toBeParsableToANumber(received) {
|
||||
let pass = false;
|
||||
let errorMessage = '';
|
||||
|
||||
try {
|
||||
Number.parseInt(received, 10);
|
||||
pass = true;
|
||||
} catch (error) {
|
||||
errorMessage = error;
|
||||
}
|
||||
|
||||
const message = () => `Expected ${this.utils.printExpected(received)} to be parsable as a number
|
||||
, but received error: ${this.utils.printReceived(errorMessage)}.`;
|
||||
|
||||
return {
|
||||
message,
|
||||
pass,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
38
src/model/__mocks__/versioning.js
Normal file
38
src/model/__mocks__/versioning.js
Normal file
@@ -0,0 +1,38 @@
|
||||
/* eslint-disable unicorn/prevent-abbreviations */
|
||||
|
||||
// Import these named export into your test file:
|
||||
export const mockProjectPath = jest.fn().mockResolvedValue('mockProjectPath');
|
||||
export const mockIsDirtyAllowed = jest.fn().mockResolvedValue(false);
|
||||
export const mockBranch = jest.fn().mockResolvedValue('mockBranch');
|
||||
export const mockHeadRef = jest.fn().mockResolvedValue('mockHeadRef');
|
||||
export const mockRef = jest.fn().mockResolvedValue('mockRef');
|
||||
export const mockDetermineVersion = jest.fn().mockResolvedValue('1.2.3');
|
||||
export const mockGenerateSemanticVersion = jest.fn().mockResolvedValue('2.3.4');
|
||||
export const mockGenerateTagVersion = jest.fn().mockResolvedValue('1.0');
|
||||
export const mockParseSemanticVersion = jest.fn().mockResolvedValue({});
|
||||
export const mockFetch = jest.fn().mockImplementation(() => {});
|
||||
export const mockGetVersionDescription = jest.fn().mockResolvedValue('1.2-3-g12345678-dirty');
|
||||
export const mockIsDirty = jest.fn().mockResolvedValue(false);
|
||||
export const mockGetTag = jest.fn().mockResolvedValue('v1.0');
|
||||
export const mockHasAnyVersionTags = jest.fn().mockResolvedValue(true);
|
||||
export const mockGetTotalNumberOfCommits = jest.fn().mockResolvedValue(3);
|
||||
export const mockGit = jest.fn().mockImplementation(() => {});
|
||||
|
||||
export default {
|
||||
projectPath: mockProjectPath,
|
||||
isDirtyAllowed: mockIsDirtyAllowed,
|
||||
branch: mockBranch,
|
||||
headRef: mockHeadRef,
|
||||
ref: mockRef,
|
||||
determineVersion: mockDetermineVersion,
|
||||
generateSemanticVersion: mockGenerateSemanticVersion,
|
||||
generateTagVersion: mockGenerateTagVersion,
|
||||
parseSemanticVersion: mockParseSemanticVersion,
|
||||
fetch: mockFetch,
|
||||
getVersionDescription: mockGetVersionDescription,
|
||||
isDirty: mockIsDirty,
|
||||
getTag: mockGetTag,
|
||||
hasAnyVersionTags: mockHasAnyVersionTags,
|
||||
getTotalNumberOfCommits: mockGetTotalNumberOfCommits,
|
||||
git: mockGit,
|
||||
};
|
||||
@@ -1,28 +1,25 @@
|
||||
import Input from './input';
|
||||
import Platform from './platform';
|
||||
import Versioning from './versioning';
|
||||
|
||||
class BuildParameters {
|
||||
static create(parameters) {
|
||||
const {
|
||||
version,
|
||||
targetPlatform,
|
||||
projectPath,
|
||||
buildName,
|
||||
buildsPath,
|
||||
buildMethod,
|
||||
buildVersion,
|
||||
customParameters,
|
||||
} = parameters;
|
||||
static async create() {
|
||||
const buildFile = this.parseBuildFile(Input.buildName, Input.targetPlatform);
|
||||
const buildVersion = await Versioning.determineVersion(
|
||||
Input.versioningStrategy,
|
||||
Input.specifiedVersion,
|
||||
);
|
||||
|
||||
return {
|
||||
version,
|
||||
platform: targetPlatform,
|
||||
projectPath,
|
||||
buildName,
|
||||
buildPath: `${buildsPath}/${targetPlatform}`,
|
||||
buildFile: this.parseBuildFile(buildName, targetPlatform),
|
||||
buildMethod,
|
||||
version: Input.unityVersion,
|
||||
platform: Input.targetPlatform,
|
||||
projectPath: Input.projectPath,
|
||||
buildName: Input.buildName,
|
||||
buildPath: `${Input.buildsPath}/${Input.targetPlatform}`,
|
||||
buildFile,
|
||||
buildMethod: Input.buildMethod,
|
||||
buildVersion,
|
||||
customParameters,
|
||||
customParameters: Input.customParameters,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,82 +1,110 @@
|
||||
import Versioning from './versioning';
|
||||
import BuildParameters from './build-parameters';
|
||||
import Input from './input';
|
||||
import Platform from './platform';
|
||||
|
||||
const determineVersion = jest
|
||||
.spyOn(Versioning, 'determineVersion')
|
||||
.mockImplementation(() => '1.3.37');
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('BuildParameters', () => {
|
||||
describe('create', () => {
|
||||
const someParameters = {
|
||||
version: 'someVersion',
|
||||
targetPlatform: 'somePlatform',
|
||||
projectPath: 'path/to/project',
|
||||
buildName: 'someBuildName',
|
||||
buildsPath: 'someBuildsPath',
|
||||
buildMethod: 'Namespace.Class.Method',
|
||||
customParameters: '-someParam someValue',
|
||||
};
|
||||
|
||||
it('does not throw', () => {
|
||||
expect(() => BuildParameters.create(someParameters)).not.toThrow();
|
||||
it('does not throw', async () => {
|
||||
await expect(BuildParameters.create()).resolves.not.toThrow();
|
||||
});
|
||||
|
||||
it('returns the version', () => {
|
||||
expect(BuildParameters.create(someParameters).version).toStrictEqual(someParameters.version);
|
||||
it('determines the version only once', async () => {
|
||||
await BuildParameters.create();
|
||||
expect(determineVersion).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('returns the platform', () => {
|
||||
expect(BuildParameters.create(someParameters).platform).toStrictEqual(
|
||||
someParameters.targetPlatform,
|
||||
it('returns the version', async () => {
|
||||
const mockValue = 'someVersion';
|
||||
jest.spyOn(Input, 'unityVersion', 'get').mockReturnValue(mockValue);
|
||||
await expect(BuildParameters.create()).resolves.toEqual(
|
||||
expect.objectContaining({ version: mockValue }),
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the project path', () => {
|
||||
expect(BuildParameters.create(someParameters).projectPath).toStrictEqual(
|
||||
someParameters.projectPath,
|
||||
it('returns the platform', async () => {
|
||||
const mockValue = 'somePlatform';
|
||||
jest.spyOn(Input, 'targetPlatform', 'get').mockReturnValue(mockValue);
|
||||
await expect(BuildParameters.create()).resolves.toEqual(
|
||||
expect.objectContaining({ platform: mockValue }),
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the build name', () => {
|
||||
expect(BuildParameters.create(someParameters).buildName).toStrictEqual(
|
||||
someParameters.buildName,
|
||||
it('returns the project path', async () => {
|
||||
const mockValue = 'path/to/project';
|
||||
jest.spyOn(Input, 'projectPath', 'get').mockReturnValue(mockValue);
|
||||
await expect(BuildParameters.create()).resolves.toEqual(
|
||||
expect.objectContaining({ projectPath: mockValue }),
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the build path', () => {
|
||||
expect(BuildParameters.create(someParameters).buildPath).toStrictEqual(
|
||||
`${someParameters.buildsPath}/${someParameters.targetPlatform}`,
|
||||
it('returns the build name', async () => {
|
||||
const mockValue = 'someBuildName';
|
||||
jest.spyOn(Input, 'buildName', 'get').mockReturnValue(mockValue);
|
||||
await expect(BuildParameters.create()).resolves.toEqual(
|
||||
expect.objectContaining({ buildName: mockValue }),
|
||||
);
|
||||
});
|
||||
|
||||
describe('build file', () => {
|
||||
it('returns the build file', () => {
|
||||
expect(BuildParameters.create(someParameters).buildFile).toStrictEqual(
|
||||
someParameters.buildName,
|
||||
it('returns the build path', async () => {
|
||||
const mockPath = 'somePath';
|
||||
const mockPlatform = 'somePlatform';
|
||||
const expectedBuildPath = `${mockPath}/${mockPlatform}`;
|
||||
jest.spyOn(Input, 'buildsPath', 'get').mockReturnValue(mockPath);
|
||||
jest.spyOn(Input, 'targetPlatform', 'get').mockReturnValue(mockPlatform);
|
||||
await expect(BuildParameters.create()).resolves.toEqual(
|
||||
expect.objectContaining({ buildPath: expectedBuildPath }),
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the build file', async () => {
|
||||
const mockValue = 'someBuildName';
|
||||
jest.spyOn(Input, 'buildName', 'get').mockReturnValue(mockValue);
|
||||
await expect(BuildParameters.create()).resolves.toEqual(
|
||||
expect.objectContaining({ buildFile: mockValue }),
|
||||
);
|
||||
});
|
||||
|
||||
test.each([Platform.types.StandaloneWindows, Platform.types.StandaloneWindows64])(
|
||||
'appends exe for %s',
|
||||
async (targetPlatform) => {
|
||||
jest.spyOn(Input, 'targetPlatform', 'get').mockReturnValue(targetPlatform);
|
||||
jest.spyOn(Input, 'buildName', 'get').mockReturnValue(targetPlatform);
|
||||
await expect(BuildParameters.create()).resolves.toEqual(
|
||||
expect.objectContaining({ buildFile: `${targetPlatform}.exe` }),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test.each([Platform.types.StandaloneWindows, Platform.types.StandaloneWindows64])(
|
||||
'appends exe for %s',
|
||||
(targetPlatform) => {
|
||||
expect(
|
||||
BuildParameters.create({ ...someParameters, targetPlatform }).buildFile,
|
||||
).toStrictEqual(`${someParameters.buildName}.exe`);
|
||||
},
|
||||
);
|
||||
|
||||
test.each([Platform.types.Android])('appends apk for %s', (targetPlatform) => {
|
||||
expect(
|
||||
BuildParameters.create({ ...someParameters, targetPlatform }).buildFile,
|
||||
).toStrictEqual(`${someParameters.buildName}.apk`);
|
||||
});
|
||||
});
|
||||
|
||||
it('returns the build method', () => {
|
||||
expect(BuildParameters.create(someParameters).buildMethod).toStrictEqual(
|
||||
someParameters.buildMethod,
|
||||
test.each([Platform.types.Android])('appends apk for %s', async (targetPlatform) => {
|
||||
jest.spyOn(Input, 'targetPlatform', 'get').mockReturnValue(targetPlatform);
|
||||
jest.spyOn(Input, 'buildName', 'get').mockReturnValue(targetPlatform);
|
||||
await expect(BuildParameters.create()).resolves.toEqual(
|
||||
expect.objectContaining({ buildFile: `${targetPlatform}.apk` }),
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the custom parameters', () => {
|
||||
expect(BuildParameters.create(someParameters).customParameters).toStrictEqual(
|
||||
someParameters.customParameters,
|
||||
it('returns the build method', async () => {
|
||||
const mockValue = 'Namespace.ClassName.BuildMethod';
|
||||
jest.spyOn(Input, 'buildMethod', 'get').mockReturnValue(mockValue);
|
||||
await expect(BuildParameters.create()).resolves.toEqual(
|
||||
expect.objectContaining({ buildMethod: mockValue }),
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the custom parameters', async () => {
|
||||
const mockValue = '-profile SomeProfile -someBoolean -someValue exampleValue';
|
||||
jest.spyOn(Input, 'customParameters', 'get').mockReturnValue(mockValue);
|
||||
await expect(BuildParameters.create()).resolves.toEqual(
|
||||
expect.objectContaining({ customParameters: mockValue }),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import * as core from '@actions/core';
|
||||
import fs from 'fs';
|
||||
import Action from './action';
|
||||
import Project from './project';
|
||||
@@ -14,11 +15,11 @@ class Cache {
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`
|
||||
core.warning(`
|
||||
Library folder does not exist.
|
||||
Consider setting up caching to speed up your workflow
|
||||
If this is not your first build.`);
|
||||
Consider setting up caching to speed up your workflow,
|
||||
if this is not your first build.
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,38 +1,54 @@
|
||||
import Platform from './platform';
|
||||
import Versioning from './versioning';
|
||||
|
||||
const core = require('@actions/core');
|
||||
|
||||
/**
|
||||
* Input variables specified in workflows using "with" prop.
|
||||
*
|
||||
* Note that input is always passed as a string, even booleans.
|
||||
*/
|
||||
class Input {
|
||||
static async getFromUser() {
|
||||
// Input variables specified in workflows using "with" prop.
|
||||
const version = core.getInput('unityVersion');
|
||||
const targetPlatform = core.getInput('targetPlatform') || Platform.default;
|
||||
static get unityVersion() {
|
||||
return core.getInput('unityVersion');
|
||||
}
|
||||
|
||||
static get targetPlatform() {
|
||||
return core.getInput('targetPlatform') || Platform.default;
|
||||
}
|
||||
|
||||
static get projectPath() {
|
||||
const rawProjectPath = core.getInput('projectPath') || '.';
|
||||
const buildName = core.getInput('buildName') || targetPlatform;
|
||||
const buildsPath = core.getInput('buildsPath') || 'build';
|
||||
const buildMethod = core.getInput('buildMethod'); // processed in docker file
|
||||
const versioningStrategy = core.getInput('versioning') || 'Semantic';
|
||||
const specifiedVersion = core.getInput('version') || '';
|
||||
const customParameters = core.getInput('customParameters') || '';
|
||||
return rawProjectPath.replace(/\/$/, '');
|
||||
}
|
||||
|
||||
// Sanitise input
|
||||
const projectPath = rawProjectPath.replace(/\/$/, '');
|
||||
static get buildName() {
|
||||
return core.getInput('buildName') || this.targetPlatform;
|
||||
}
|
||||
|
||||
// Parse input
|
||||
const buildVersion = await Versioning.determineVersion(versioningStrategy, specifiedVersion);
|
||||
static get buildsPath() {
|
||||
return core.getInput('buildsPath') || 'build';
|
||||
}
|
||||
|
||||
// Return validated input
|
||||
return {
|
||||
version,
|
||||
targetPlatform,
|
||||
projectPath,
|
||||
buildName,
|
||||
buildsPath,
|
||||
buildMethod,
|
||||
buildVersion,
|
||||
customParameters,
|
||||
};
|
||||
static get buildMethod() {
|
||||
return core.getInput('buildMethod'); // processed in docker file
|
||||
}
|
||||
|
||||
static get versioningStrategy() {
|
||||
return core.getInput('versioning') || 'Semantic';
|
||||
}
|
||||
|
||||
static get specifiedVersion() {
|
||||
return core.getInput('version') || '';
|
||||
}
|
||||
|
||||
static get allowDirtyBuild() {
|
||||
const input = core.getInput('allowDirtyBuild') || 'false';
|
||||
|
||||
return input === 'true' ? 'true' : 'false';
|
||||
}
|
||||
|
||||
static get customParameters() {
|
||||
return core.getInput('customParameters') || '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,27 +1,151 @@
|
||||
import Input from './input';
|
||||
import Versioning from './versioning';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
const determineVersion = jest
|
||||
.spyOn(Versioning, 'determineVersion')
|
||||
.mockImplementation(() => '1.3.37');
|
||||
import Input from './input';
|
||||
import Platform from './platform';
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('Input', () => {
|
||||
describe('getFromUser', () => {
|
||||
it('does not throw', async () => {
|
||||
await expect(Input.getFromUser()).resolves.not.toBeNull();
|
||||
describe('unityVersion', () => {
|
||||
it('returns the default value', () => {
|
||||
expect(Input.unityVersion).toStrictEqual('');
|
||||
});
|
||||
|
||||
it('returns an object', async () => {
|
||||
await expect(typeof (await Input.getFromUser())).toStrictEqual('object');
|
||||
it('takes input from the users workflow', () => {
|
||||
const mockValue = '2020.4.99f9';
|
||||
const spy = jest.spyOn(core, 'getInput').mockReturnValue(mockValue);
|
||||
expect(Input.unityVersion).toStrictEqual(mockValue);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('targetPlatform', () => {
|
||||
it('returns the default value', () => {
|
||||
expect(Input.targetPlatform).toStrictEqual(Platform.default);
|
||||
});
|
||||
|
||||
it('calls version generator once', async () => {
|
||||
await Input.getFromUser();
|
||||
expect(determineVersion).toHaveBeenCalledTimes(1);
|
||||
it('takes input from the users workflow', () => {
|
||||
const mockValue = 'Android';
|
||||
const spy = jest.spyOn(core, 'getInput').mockReturnValue(mockValue);
|
||||
expect(Input.targetPlatform).toStrictEqual(mockValue);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('projectPath', () => {
|
||||
it('returns the default value', () => {
|
||||
expect(Input.projectPath).toStrictEqual('.');
|
||||
});
|
||||
|
||||
it('takes input from the users workflow', () => {
|
||||
const mockValue = 'customProjectPath';
|
||||
const spy = jest.spyOn(core, 'getInput').mockReturnValue(mockValue);
|
||||
expect(Input.projectPath).toStrictEqual(mockValue);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildName', () => {
|
||||
it('returns the default value', () => {
|
||||
expect(Input.buildName).toStrictEqual(Input.targetPlatform);
|
||||
});
|
||||
|
||||
it('takes input from the users workflow', () => {
|
||||
const mockValue = 'Build';
|
||||
const spy = jest.spyOn(core, 'getInput').mockReturnValue(mockValue);
|
||||
expect(Input.buildName).toStrictEqual(mockValue);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('takes special characters as input', () => {
|
||||
const mockValue = '1ßúëld2';
|
||||
jest.spyOn(core, 'getInput').mockReturnValue(mockValue);
|
||||
expect(Input.buildName).toStrictEqual(mockValue);
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildsPath', () => {
|
||||
it('returns the default value', () => {
|
||||
expect(Input.buildsPath).toStrictEqual('build');
|
||||
});
|
||||
|
||||
it('takes input from the users workflow', () => {
|
||||
const mockValue = 'customBuildsPath';
|
||||
const spy = jest.spyOn(core, 'getInput').mockReturnValue(mockValue);
|
||||
expect(Input.buildsPath).toStrictEqual(mockValue);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildMethod', () => {
|
||||
it('returns the default value', () => {
|
||||
expect(Input.buildMethod).toStrictEqual('');
|
||||
});
|
||||
|
||||
it('takes input from the users workflow', () => {
|
||||
const mockValue = 'Namespace.ClassName.Method';
|
||||
const spy = jest.spyOn(core, 'getInput').mockReturnValue(mockValue);
|
||||
expect(Input.buildMethod).toStrictEqual(mockValue);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('versioningStrategy', () => {
|
||||
it('returns the default value', () => {
|
||||
expect(Input.versioningStrategy).toStrictEqual('Semantic');
|
||||
});
|
||||
|
||||
it('takes input from the users workflow', () => {
|
||||
const mockValue = 'Anything';
|
||||
const spy = jest.spyOn(core, 'getInput').mockReturnValue(mockValue);
|
||||
expect(Input.versioningStrategy).toStrictEqual(mockValue);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('specifiedVersion', () => {
|
||||
it('returns the default value', () => {
|
||||
expect(Input.specifiedVersion).toStrictEqual('');
|
||||
});
|
||||
|
||||
it('takes input from the users workflow', () => {
|
||||
const mockValue = '1.33.7';
|
||||
const spy = jest.spyOn(core, 'getInput').mockReturnValue(mockValue);
|
||||
expect(Input.specifiedVersion).toStrictEqual(mockValue);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('allowDirtyBuild', () => {
|
||||
it('returns the default value', () => {
|
||||
expect(Input.allowDirtyBuild).toStrictEqual('false');
|
||||
});
|
||||
|
||||
it('returns true when string true is passed', () => {
|
||||
const spy = jest.spyOn(core, 'getInput').mockReturnValue('true');
|
||||
expect(Input.allowDirtyBuild).toStrictEqual('true');
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('returns false when string false is passed', () => {
|
||||
const spy = jest.spyOn(core, 'getInput').mockReturnValue('false');
|
||||
expect(Input.allowDirtyBuild).toStrictEqual('false');
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('customParameters', () => {
|
||||
it('returns the default value', () => {
|
||||
expect(Input.customParameters).toStrictEqual('');
|
||||
});
|
||||
|
||||
it('takes input from the users workflow', () => {
|
||||
const mockValue = '-imAFlag';
|
||||
const spy = jest.spyOn(core, 'getInput').mockReturnValue(mockValue);
|
||||
expect(Input.customParameters).toStrictEqual(mockValue);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import * as core from '@actions/core';
|
||||
import Input from './input';
|
||||
import Unity from './unity';
|
||||
import Action from './action';
|
||||
|
||||
class Project {
|
||||
static get relativePath() {
|
||||
// Todo - properly use Input for this.
|
||||
const projectPath = core.getInput('projectPath') || '.';
|
||||
const { projectPath } = Input;
|
||||
|
||||
return `${projectPath}`;
|
||||
}
|
||||
|
||||
@@ -19,22 +19,40 @@ class System {
|
||||
},
|
||||
};
|
||||
|
||||
const exitCode = await exec(command, arguments_, { silent: true, listeners, ...options });
|
||||
const showOutput = () => {
|
||||
if (debug !== '') {
|
||||
core.debug(debug);
|
||||
}
|
||||
|
||||
if (debug !== '') {
|
||||
core.debug(debug);
|
||||
}
|
||||
if (result !== '') {
|
||||
core.info(result);
|
||||
}
|
||||
|
||||
if (result !== '') {
|
||||
core.info(result);
|
||||
}
|
||||
if (error !== '') {
|
||||
core.warning(error);
|
||||
}
|
||||
};
|
||||
|
||||
if (exitCode !== 0) {
|
||||
throw new Error(error);
|
||||
}
|
||||
const throwContextualError = (message) => {
|
||||
let commandAsString = command;
|
||||
if (Array.isArray(arguments_)) {
|
||||
commandAsString += ` ${arguments_.join(' ')}`;
|
||||
} else if (typeof arguments_ === 'string') {
|
||||
commandAsString += ` ${arguments_}`;
|
||||
}
|
||||
|
||||
if (error !== '') {
|
||||
core.warning(error);
|
||||
throw new Error(`Failed to run "${commandAsString}".\n ${message}`);
|
||||
};
|
||||
|
||||
try {
|
||||
const exitCode = await exec(command, arguments_, { silent: true, listeners, ...options });
|
||||
showOutput();
|
||||
if (exitCode !== 0) {
|
||||
throwContextualError(`Command returned non-zero exit code.\nError: ${error}`);
|
||||
}
|
||||
} catch (inCommandError) {
|
||||
showOutput();
|
||||
throwContextualError(`In-command error caught: ${inCommandError}`);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -44,5 +44,13 @@ describe('System', () => {
|
||||
expect(info).toHaveBeenCalledTimes(2);
|
||||
expect(info).toHaveBeenLastCalledWith('3\n');
|
||||
});
|
||||
|
||||
it('allows pipes using buffer', async () => {
|
||||
await expect(
|
||||
System.run('sh', undefined, {
|
||||
input: Buffer.from('git tag --list --merged HEAD | grep v[0-9]* | wc -l'),
|
||||
}),
|
||||
).resolves.toBeParsableToANumber();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
import * as core from '@actions/core';
|
||||
import NotImplementedException from './error/not-implemented-exception';
|
||||
import ValidationError from './error/validation-error';
|
||||
import Input from './input';
|
||||
import System from './system';
|
||||
|
||||
export default class Versioning {
|
||||
static get projectPath() {
|
||||
return Input.projectPath;
|
||||
}
|
||||
|
||||
static get isDirtyAllowed() {
|
||||
return Input.allowDirtyBuild === 'true';
|
||||
}
|
||||
|
||||
static get strategies() {
|
||||
return { None: 'None', Semantic: 'Semantic', Tag: 'Tag', Custom: 'Custom' };
|
||||
}
|
||||
@@ -79,7 +88,7 @@ export default class Versioning {
|
||||
static async generateSemanticVersion() {
|
||||
await this.fetch();
|
||||
|
||||
if (await this.isDirty()) {
|
||||
if ((await this.isDirty()) && !this.isDirtyAllowed) {
|
||||
throw new Error('Branch is dirty. Refusing to base semantic version on uncommitted changes');
|
||||
}
|
||||
|
||||
@@ -137,10 +146,10 @@ export default class Versioning {
|
||||
*/
|
||||
static async fetch() {
|
||||
try {
|
||||
await System.run('git', ['fetch', '--unshallow']);
|
||||
await this.git(['fetch', '--unshallow']);
|
||||
} catch (error) {
|
||||
core.warning(error);
|
||||
await System.run('git', ['fetch']);
|
||||
core.warning(`Fetch --unshallow caught: ${error}`);
|
||||
await this.git(['fetch']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,21 +162,15 @@ export default class Versioning {
|
||||
* identifies the current commit.
|
||||
*/
|
||||
static async getVersionDescription() {
|
||||
return System.run('git', [
|
||||
'describe',
|
||||
'--long',
|
||||
'--tags',
|
||||
'--always',
|
||||
'--debug',
|
||||
`origin/${this.branch}`,
|
||||
]);
|
||||
const commitIsh = (await this.getTag()) ? 'HEAD' : `origin/${this.branch}`;
|
||||
return this.git(['describe', '--long', '--tags', '--always', '--debug', commitIsh]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether there are uncommitted changes that are not ignored.
|
||||
*/
|
||||
static async isDirty() {
|
||||
const output = await System.run('git', ['status', '--porcelain']);
|
||||
const output = await this.git(['status', '--porcelain']);
|
||||
|
||||
return output !== '';
|
||||
}
|
||||
@@ -176,33 +179,42 @@ export default class Versioning {
|
||||
* Get the tag if there is one pointing at HEAD
|
||||
*/
|
||||
static async getTag() {
|
||||
return System.run('git', ['tag', '--points-at', 'HEAD']);
|
||||
return this.git(['tag', '--points-at', 'HEAD']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the repository has any version tags yet.
|
||||
*/
|
||||
static async hasAnyVersionTags() {
|
||||
const numberOfVersionCommits = await System.run('git', [
|
||||
'tag',
|
||||
'--list',
|
||||
'--merged',
|
||||
'HEAD',
|
||||
'|',
|
||||
'grep v[0-9]*',
|
||||
'|',
|
||||
'wc -l',
|
||||
]);
|
||||
const numberOfCommitsAsString = await System.run('sh', undefined, {
|
||||
input: Buffer.from('git tag --list --merged HEAD | grep v[0-9]* | wc -l'),
|
||||
silent: false,
|
||||
});
|
||||
|
||||
return numberOfVersionCommits !== '0';
|
||||
const numberOfCommits = Number.parseInt(numberOfCommitsAsString, 10);
|
||||
|
||||
return numberOfCommits !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total number of commits on head.
|
||||
*
|
||||
* Note: HEAD should not be used, as it may be detached, resulting in an additional count.
|
||||
*/
|
||||
static async getTotalNumberOfCommits() {
|
||||
const numberOfCommitsAsString = await System.run('git', ['rev-list', '--count', 'HEAD']);
|
||||
const numberOfCommitsAsString = await this.git([
|
||||
'rev-list',
|
||||
'--count',
|
||||
`origin/${this.branch}`,
|
||||
]);
|
||||
|
||||
return Number.parseInt(numberOfCommitsAsString, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run git in the specified project path
|
||||
*/
|
||||
static async git(arguments_, options = {}) {
|
||||
return System.run('git', arguments_, { cwd: this.projectPath, ...options });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +90,16 @@ describe('Versioning', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('isDirtyAllowed', () => {
|
||||
it('does not throw', () => {
|
||||
expect(() => Versioning.isDirtyAllowed).not.toThrow();
|
||||
});
|
||||
|
||||
it('returns false by default', () => {
|
||||
expect(Versioning.isDirtyAllowed).toStrictEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('descriptionRegex', () => {
|
||||
it('is a valid regex', () => {
|
||||
expect(Versioning.descriptionRegex).toBeInstanceOf(RegExp);
|
||||
|
||||
Reference in New Issue
Block a user