Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unity-uwp-builder@v1.0.2 #5

Merged
merged 10 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 38 additions & 19 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,58 +13,77 @@ concurrency:
cancel-in-progress: true
jobs:
unity-build:
name: '(${{ matrix.unity-versions }}) ${{ matrix.build-target }}'
name: '(${{ matrix.unity-version }}) ${{ matrix.build-target }} - ${{ matrix.uwp-package-type }}'
env:
TEMPLATE_PATH: ''
UNITY_PROJECT_PATH: '' # set by unity-setup action
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [windows-latest]
build-target: [WSAPlayer]
unity-versions: [2021.x, 2022.x, 6000.x]
unity-version: [2021.x, 2022.x, 6000.x]
uwp-package-type: [sideload, upload]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v4
with:
repository: RageAgainstThePixel/com.utilities.encoder.wav
path: 'com.utilities.encoder.wav'
ref: test
- run: 'npm install -g openupm-cli'
# Installs the Unity Editor based on your project version text file
# sets -> env.UNITY_EDITOR_PATH
# sets -> env.UNITY_PROJECT_PATH
- uses: RageAgainstThePixel/unity-setup@v1
with:
unity-version: ${{ matrix.unity-versions }}
version-file: 'None'
build-targets: ${{ matrix.build-target }}
version-file: '${{ github.workspace }}/com.utilities.encoder.wav/Utilities.Encoder.Wav/ProjectSettings/ProjectVersion.txt'
unity-version: ${{ matrix.unity-version }}
- name: Find Unity Template Path
run: |
$rootPath = $env:UNITY_EDITOR_PATH -replace "Editor.*", ""
Write-Host "ROOT_PATH=$rootPath"
$templatePath = Get-ChildItem -Recurse -Filter "com.unity.template.3d*.tgz" -Path $rootPath | Select-Object -First 1 | Select-Object -ExpandProperty FullName
Write-Host "TEMPLATE_PATH=$templatePath"
echo "TEMPLATE_PATH=$templatePath" >> $env:GITHUB_ENV
$projectPath = "${{ github.workspace }}/TestProject"
echo "UNITY_PROJECT_PATH=$projectPath" >> $env:GITHUB_ENV
shell: pwsh
# Activates the installation with the provided credentials
- uses: RageAgainstThePixel/activate-unity-license@v1
with:
license: 'Personal'
username: ${{ secrets.UNITY_USERNAME }}
password: ${{ secrets.UNITY_PASSWORD }}
- uses: RageAgainstThePixel/unity-action@v1
name: '${{ matrix.build-target }}-Validate'
name: Create Test Project
with:
log-name: '${{ matrix.build-target }}-Validate'
args: '-quit -nographics -batchmode -executeMethod Utilities.Editor.BuildPipeline.UnityPlayerBuildTools.ValidateProject -importTMProEssentialsAsset'
log-name: 'create-test-project'
args: '-quit -nographics -batchmode -createProject "${{ github.workspace }}/TestProject" -cloneFromTemplate "${{ env.TEMPLATE_PATH }}"'
- run: 'openupm add com.utilities.buildpipeline'
name: Add Build Pipeline Package
working-directory: ${{ github.workspace }}/TestProject
- uses: RageAgainstThePixel/unity-action@v1
name: '${{ matrix.build-target }}-Test'
name: '${{ matrix.build-target }}-Validate'
with:
log-name: '${{ matrix.build-target }}-Test'
build-target: ${{ matrix.build-target }}
args: '-nographics -batchmode -runTests -testPlatform EditMode -testResults "${{ github.workspace }}/Logs/${{ matrix.build-target }}-results.xml"'
log-name: '${{ matrix.build-target }}-Validate'
args: '-quit -nographics -batchmode -executeMethod Utilities.Editor.BuildPipeline.UnityPlayerBuildTools.ValidateProject -importTMProEssentialsAsset'
- uses: RageAgainstThePixel/unity-action@v1
name: '${{ matrix.build-target }}-Build'
with:
build-target: ${{ matrix.build-target }}
log-name: '${{ matrix.build-target }}-Build'
args: '-quit -nographics -batchmode -executeMethod Utilities.Editor.BuildPipeline.UnityPlayerBuildTools.StartCommandLineBuild -arch ARM64'
args: '-quit -nographics -batchmode -executeMethod Utilities.Editor.BuildPipeline.UnityPlayerBuildTools.StartCommandLineBuild -sceneList Assets/Scenes/SampleScene.unity -arch ARM64'

- uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.x'
- uses: microsoft/setup-msbuild@v2

# builds visual studio project for UWP and packages it as an appx
# builds visual studio project for UWP and packages it for store upload
- uses: ./ # RageAgainstThePixel/unity-uwp-builder
id: uwp-build
with:
project-path: ${{ env.UNITY_PROJECT_PATH }}/Builds/WSAPlayer
package-type: 'upload'
package-type: ${{ matrix.uwp-package-type }}

- name: print outputs
shell: bash
Expand All @@ -76,7 +95,7 @@ jobs:
- uses: actions/upload-artifact@v4
with:
retention-days: 1
name: ${{ matrix.unity-versions }}-${{ matrix.build-target }}.${{ github.run_number }}
name: ${{ github.run_number }}.${{ github.run_attempt }} ${{ matrix.unity-version }}-${{ matrix.build-target }}-${{ matrix.uwp-package-type }}
path: |
${{ github.workspace }}/**/*.log
${{ steps.uwp-build.outputs.output-directory }}
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@ A GitHub Action to build Unity exported UWP projects.

```yaml
steps:
# required for unity-uwp-builder action
- uses: microsoft/setup-msbuild@v2

# builds visual studio project for UWP and packages it for store upload
- uses: RageAgainstThePixel/unity-uwp-builder@v1
id: uwp-build
with:
project-path: '/path/to/your/build/output/directory'
architecture: 'ARM64'
package-type: 'upload'

- name: print outputs
Expand All @@ -33,6 +38,7 @@ steps:
| `configuration` | The configuration to use when building the visual studio project. | Defaults to `Master`. |
| `architecture` | The architecture to use when building the visual studio project. Can be: `x86`, `x64`, `ARM`, or `ARM64`. | Defaults to `ARM64`. |
| `package-type` | The type of package to generate. Can be: `sideload` or `upload`. | Defaults to `sideload`. |
| `certificate-path` | The path to the certificate to use when packaging the UWP project. | Required when `package-type` is `sideload`. Defaults to the Unity generated test certificate. |

### outputs

Expand Down
3 changes: 3 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ inputs:
description: 'The type of package to generate. Can be: `sideload` or `upload`. Defaults to `sideload`.'
required: false
default: 'sideload'
certificate-path:
description: 'The path to the certificate to use when packaging the UWP project. Required when `package-type` is `sideload`. If no certificate is provided, then a test certificate is created.'
required: false
outputs:
executable:
description: The path to the generated executable.
Expand Down
38 changes: 37 additions & 1 deletion dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30546,6 +30546,7 @@ const core = __nccwpck_require__(2186);
const exec = __nccwpck_require__(1514);
const glob = __nccwpck_require__(8090);
const path = __nccwpck_require__(1017);
const fs = __nccwpck_require__(7147);
const main = async () => {
try {
if (process.platform !== `win32`) {
Expand All @@ -30559,6 +30560,11 @@ const main = async () => {
}
const buildPath = files[0];
core.info(`Building ${buildPath}`);
const appPackagesPath = path.join(projectPath, `AppPackages`);
if (fs.existsSync(appPackagesPath)) {
core.info(`Cleaning AppPackages directory: ${appPackagesPath}`);
await fs.promises.rm(appPackagesPath, { recursive: true, force: true });
}
let projectName = path.basename(buildPath, `.sln`);
core.info(`projectName: "${projectName}"`);
const configuration = core.getInput(`configuration`, { required: true });
Expand All @@ -30578,7 +30584,9 @@ const main = async () => {
buildArgs.push(`/p:UapAppxPackageBuildMode=StoreUpload`, `/p:GenerateAppInstallerFile=false`, `/p:AppxPackageSigningEnabled=false`, `/p:BuildAppxUploadPackageForUap=true`);
break;
case `sideload`:
buildArgs.push(`/p:UapAppxPackageBuildMode=SideloadOnly`);
const certificatePath = await getCertificatePath(projectPath);
const thumbprint = await getCertificateThumbprint(certificatePath);
buildArgs.push(`/p:UapAppxPackageBuildMode=SideloadOnly`, `/p:AppxPackageSigningEnabled=true`, `/p:PackageCertificateThumbprint=${thumbprint}`, `/p:PackageCertificateKeyFile="${certificatePath}"`);
break;
default:
throw new Error(`Invalid package type: "${packageType}"`);
Expand Down Expand Up @@ -30631,6 +30639,34 @@ const main = async () => {
}
};
main();
async function getCertificatePath(projectPath) {
let certificatePath = core.getInput(`certificate-path`) || `${projectPath}/**/*.pfx`;
const certificateGlobber = await glob.create(certificatePath);
const certificateFiles = await certificateGlobber.glob();
switch (certificateFiles.length) {
case 0:
throw new Error(`No certificate file found. Please set the 'certificate-path' input.`);
default:
if (certificateFiles.length > 1) {
core.warning(`More than one certificate file found, using the first one found:\n${certificateFiles.join(`\n`)}`);
}
certificatePath = certificateFiles[0];
}
await fs.promises.access(certificatePath, fs.constants.R_OK);
return certificatePath;
}
async function getCertificateThumbprint(certificatePath) {
const thumbprintCmd = `powershell -command "(Get-PfxCertificate -FilePath '${certificatePath}').Thumbprint"`;
let thumbprint = ``;
await exec.exec(thumbprintCmd, [], {
listeners: {
stdout: (data) => {
thumbprint += data.toString();
}
}
});
return thumbprint.trim();
}

})();

Expand Down
2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "unity-uwp-builder",
"version": "1.0.1",
"version": "1.0.2",
"description": "A GitHub Action to build Unity exported UWP projects.",
"author": "RageAgainstThePixel",
"license": "MIT",
Expand Down
42 changes: 41 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ const main = async () => {
if (files.length === 0) { throw new Error(`No solution file found.`); }
const buildPath = files[0];
core.info(`Building ${buildPath}`);
const appPackagesPath = path.join(projectPath, `AppPackages`);
if (fs.existsSync(appPackagesPath)) {
core.info(`Cleaning AppPackages directory: ${appPackagesPath}`);
await fs.promises.rm(appPackagesPath, { recursive: true, force: true });
}
let projectName = path.basename(buildPath, `.sln`);
core.info(`projectName: "${projectName}"`);
const configuration = core.getInput(`configuration`, { required: true });
Expand All @@ -37,8 +42,13 @@ const main = async () => {
);
break;
case `sideload`:
const certificatePath = await getCertificatePath(projectPath);
const thumbprint = await getCertificateThumbprint(certificatePath);
buildArgs.push(
`/p:UapAppxPackageBuildMode=SideloadOnly`
`/p:UapAppxPackageBuildMode=SideloadOnly`,
`/p:AppxPackageSigningEnabled=true`,
`/p:PackageCertificateThumbprint=${thumbprint}`,
`/p:PackageCertificateKeyFile="${certificatePath}"`
);
break;
default:
Expand Down Expand Up @@ -92,3 +102,33 @@ const main = async () => {
}

main();

async function getCertificatePath(projectPath: string): Promise<string> {
let certificatePath = core.getInput(`certificate-path`) || `${projectPath}/**/*.pfx`;
const certificateGlobber = await glob.create(certificatePath);
const certificateFiles = await certificateGlobber.glob();
switch (certificateFiles.length) {
case 0:
throw new Error(`No certificate file found. Please set the 'certificate-path' input.`);
default:
if (certificateFiles.length > 1) {
core.warning(`More than one certificate file found, using the first one found:\n${certificateFiles.join(`\n`)}`);
}
certificatePath = certificateFiles[0];
}
await fs.promises.access(certificatePath, fs.constants.R_OK);
return certificatePath;
}

async function getCertificateThumbprint(certificatePath: string): Promise<string> {
const thumbprintCmd = `powershell -command "(Get-PfxCertificate -FilePath '${certificatePath}').Thumbprint"`;
let thumbprint = ``;
await exec.exec(thumbprintCmd, [], {
listeners: {
stdout: (data: Buffer) => {
thumbprint += data.toString();
}
}
});
return thumbprint.trim();
}
Loading