diff --git a/.github/workflows/development-publish.yml b/.github/workflows/development-publish.yml new file mode 100644 index 0000000..a770e9d --- /dev/null +++ b/.github/workflows/development-publish.yml @@ -0,0 +1,26 @@ +name: Publish development branch on Merge + +on: + pull_request: + types: + - closed + branches: + - development + # On close of PR targeting development + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + +jobs: + release_on_merge: + if: github.event.pull_request.merged == true + name: Tag and Publish UPM package + uses: ./.github/workflows/upversionandtagrelease.yml + with: + build-host: ubuntu-latest + build-type: pre-release + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/getpackageversionfrompackage.yml b/.github/workflows/getpackageversionfrompackage.yml new file mode 100644 index 0000000..b1ba223 --- /dev/null +++ b/.github/workflows/getpackageversionfrompackage.yml @@ -0,0 +1,70 @@ +name: Get the Package version from a UPM Package.json file + +on: + workflow_call: + inputs: + build-host: + required: true + type: string + version-file-path: + description: 'Optional, specify a path to search for the upm package.json file. Use this if validation fails to find a valid package.json file.\n **Note, Version file MUST contain the attribute "Unity" with the full Unity version expected, e.g. "2020.2.3f1"' + type: string + required: false + outputs: + packageversion: + description: "Returns the version of the UPM package" + value: ${{ jobs.get_package_version.outputs.upmpackageversion }} + +jobs: + get_package_version: + name: Get required Package version from UPM Package + runs-on: ${{ inputs.build-host }} + outputs: + upmpackageversion: ${{ steps.getVersion.outputs.packageversion }} + steps: + - name: Script Version + run: | + echo "::group::Script Versioning" + $scriptVersion = "1.0.0" + echo "Build Script Version: $scriptVersion" + echo "::endgroup::" + shell: pwsh + - uses: actions/checkout@v7 + with: + submodules: recursive + clean: true + - id: getVersion + name: 'Get Package Version Number' + run: | + echo "::group::Validating input" + + $versionFile = "${{ inputs.version-file-path }}" + if([string]::IsNullOrEmpty($versionFile)) + { + echo 'version input was empty, using default' + $versionFile = 'package.json' + } + echo 'Checking for project json at $versionFile' + + if ( -not (Test-Path -Path $versionFile) ) { + Write-Error "Failed to find a valid package.json file" + exit 1 + } + + echo "::endgroup::" + + echo "::group::Package Version UPM check" + + $package_json = Get-Content -Path $versionFile | ConvertFrom-Json + $packageVersion = $package_json.version + + if([string]::IsNullOrEmpty($packageVersion)) { + Write-Error "Project.json version number does not exist or is empty" + exit 1 + } + + echo "packageversion=$packageVersion" >> $env:GITHUB_OUTPUT + + echo "Detected version is $packageVersion" + echo "::endgroup::" + shell: pwsh \ No newline at end of file diff --git a/.github/workflows/main-publish.yml b/.github/workflows/main-publish.yml new file mode 100644 index 0000000..f667dc6 --- /dev/null +++ b/.github/workflows/main-publish.yml @@ -0,0 +1,91 @@ +name: Publish main branch and increment version + +on: + pull_request: + types: + - closed + branches: + - release + +jobs: + # Get Version to tag and release the branch, no up-version - [no-ver] included in PR title + validate-environment: + if: github.event.pull_request.merged == true && contains(github.event.pull_request.title, 'no-ver') + name: Get Version from UPM package + uses: ./.github/workflows/getpackageversionfrompackage.yml + with: + build-host: ubuntu-latest + + # Perform tagging + release-Package-only: + needs: validate-environment + name: Release package only, no upversion + uses: ./.github/workflows/tagrelease.yml + with: + build-host: ubuntu-latest + version: ${{ needs.validate-environment.outputs.packageversion }} + secrets: inherit + + # Up version the release and publish major release + upversion-major-Package: + if: github.event.pull_request.merged == true && contains(github.event.pull_request.title, 'no-ver') == false && contains(github.event.pull_request.title, 'major-release') + name: Major Version package and release + uses: ./.github/workflows/upversionandtagrelease.yml + with: + build-host: ubuntu-latest + build-type: major + secrets: inherit + + # Up version the release and publish minor release + upversion-minor-Package: + if: github.event.pull_request.merged == true && contains(github.event.pull_request.title, 'no-ver') == false && contains(github.event.pull_request.title, 'minor-release') + name: Minor Version package and release + uses: ./.github/workflows/upversionandtagrelease.yml + with: + build-host: ubuntu-latest + build-type: minor + secrets: inherit + + # Up version the release and publish patch release (default) + upversion-patch-Package: + if: github.event.pull_request.merged == true && contains(github.event.pull_request.title, 'no-ver') == false && contains(github.event.pull_request.title, 'minor-release') == false && contains(github.event.pull_request.title, 'major-release') == false + name: Patch Version package and release + uses: ./.github/workflows/upversionandtagrelease.yml + with: + build-host: ubuntu-latest + build-type: patch-release + secrets: inherit + + release-Complete: + if: ${{ always() }} + needs: [upversion-major-Package, upversion-minor-Package, upversion-patch-Package, release-Package-only] + name: Release complete + runs-on: ubuntu-latest + steps: + - name: Script Version + run: echo "Release done, updating Development" + + # Refresh the development branch with the main publish + refresh-development: + if: ${{ always() }} + needs: [release-Complete] + name: Refresh development branch + uses: ./.github/workflows/refreshbranch.yml + with: + build-host: ubuntu-latest + target-branch: development + source-branch: main + secrets: inherit + + # Up version the development branch ready for future development + upversion-development: + if: ${{ always() }} + needs: [refresh-development] + name: UpVersion the development branch for the next release + uses: ./.github/workflows/upversionandtagrelease.yml + with: + build-host: ubuntu-latest + build-type: patch + target-branch: development + createTag: false + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/refreshbranch.yml b/.github/workflows/refreshbranch.yml new file mode 100644 index 0000000..129d610 --- /dev/null +++ b/.github/workflows/refreshbranch.yml @@ -0,0 +1,43 @@ +name: Refresh branch + +on: + workflow_call: + inputs: + build-host: + required: true + type: string + target-branch: + required: true + type: string + source-branch: + required: true + type: string + +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + +jobs: + packageRelease: + name: Refresh ${{ inputs.target-branch }} branch from ${{ inputs.source-branch }} branch + runs-on: ${{ inputs.build-host }} + steps: + - name: Script Version + run: | + echo "::group::Script Versioning" + $scriptVersion = "1.0.1" + echo "Build Script Version: $scriptVersion" + echo "::endgroup::" + shell: pwsh + - uses: actions/checkout@v7 + with: + ref: ${{ inputs.target-branch }} + clean: true + token: ${{ secrets.GIT_PAT }} + - name: Refresh from Source Branch + run: | + git pull origin ${{ inputs.source-branch }} + git commit -m "Branch ${{ inputs.target-branch }} updated with changes from ${{ inputs.source-branch }} [skip ci]" + git push origin ${{ inputs.target-branch }} + echo "Branch ${{ inputs.target-branch }} updated with changes from ${{ inputs.source-branch }}" + shell: pwsh \ No newline at end of file diff --git a/.github/workflows/tagrelease.yml b/.github/workflows/tagrelease.yml new file mode 100644 index 0000000..7a8d682 --- /dev/null +++ b/.github/workflows/tagrelease.yml @@ -0,0 +1,77 @@ +name: Tag Release + +on: + workflow_call: + inputs: + build-host: + required: true + type: string + version: + required: true + type: string + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + +jobs: + packageRelease: + name: Package UPM Project and tag + runs-on: ${{ inputs.build-host }} + steps: + - name: Script Version + run: | + echo "::group::Script Versioning" + $scriptVersion = "1.0.2" + echo "Build Script Version: $scriptVersion" + echo "::endgroup::" + shell: pwsh + - uses: actions/checkout@v7 + with: + fetch-depth: 0 + submodules: recursive + clean: true + token: ${{ secrets.GIT_PAT }} + - uses: actions/setup-node@v6 + - name: Set Github vars + run: | + if([string]::IsNullOrEmpty('${{ secrets.GIT_USER_NAME }}')){ + if([string]::IsNullOrEmpty('${{ secrets.GIT_USER_NAME }}')){ + $gitUser = "action" + $gitEmail = "action@github.com" + } + else { + $gitUser = "${GITHUB_ACTOR}" + $gitEmail = "$gitUser@users.noreply.github.com" + } + } + else { + $gitUser = "${{ secrets.GIT_USER_NAME }}" + $gitEmail = "$gitUser@users.noreply.github.com" + } + git config --global user.email "$gitUser@users.noreply.github.com" + git config --global user.name "$gitUser" + shell: pwsh + - name: Check if Tag Exists + run: | + $tagVersion = "${{ inputs.version }}" + $tags = git tag + echo "Tags found are [$tags], searching for [$tagVersion]" + foreach ($tag in $tags) + { + if($tag.Trim() -eq "$tagVersion") + { + Write-Error "$tagVersion tag already exists" + exit 1 + } + } + shell: pwsh + - name: Create tag and push + run: | + $tagVersion = "${{ inputs.version }}" + git tag -fa "v$tagVersion" "${GITHUB_SHA}" -m "v$tagVersion Release [skip ci]" + git push origin "v$tagVersion" --force + shell: pwsh \ No newline at end of file diff --git a/.github/workflows/upversionandtagrelease.yml b/.github/workflows/upversionandtagrelease.yml new file mode 100644 index 0000000..ca7ccde --- /dev/null +++ b/.github/workflows/upversionandtagrelease.yml @@ -0,0 +1,181 @@ +name: UpVersion Package UPM project and create new tag + +on: + workflow_call: + inputs: + build-host: + required: true + type: string + build-type: + required: false + default: 'pre-release' + type: string +# options: +# - major +# - minor +# - patch +# - patch-release +# - pre-release +# - build + target-branch: + required: false + type: string + default: ${{ github.ref }} + createTag: + required: false + type: boolean + default: true + + outputs: + packageversion: + description: "Returns the version of Unity the UPM package requires" + value: ${{ jobs.packageRelease.outputs.packageversion }} + secrets: + GIT_PAT: + required: true + +jobs: + packageRelease: + name: Package UPM Project and tag + runs-on: ${{ inputs.build-host }} + outputs: + packageversion: ${{ steps.getpackageversion.outputs.packageversion }} + steps: + - name: Script Version + run: | + echo "::group::Script Versioning" + $scriptVersion = "1.0.2" + echo "Build Script Version: $scriptVersion" + echo "::endgroup::" + shell: pwsh + - uses: actions/checkout@v7 + with: + ref: ${{ inputs.target-branch }} + fetch-depth: 0 + submodules: recursive + clean: true + token: ${{ secrets.GIT_PAT }} + - uses: actions/setup-node@v6 + - name: Set Github vars + run: | + if([string]::IsNullOrEmpty('${{ secrets.GIT_USER_NAME }}')){ + if([string]::IsNullOrEmpty('${{ secrets.GIT_USER_NAME }}')){ + $gitUser = "action" + $gitEmail = "action@github.com" + } + else { + $gitUser = "${GITHUB_ACTOR}" + $gitEmail = "$gitUser@users.noreply.github.com" + } + } + else { + $gitUser = "${{ secrets.GIT_USER_NAME }}" + $gitEmail = "$gitUser@users.noreply.github.com" + } + git config --global user.email "$gitUser@users.noreply.github.com" + git config --global user.name "$gitUser" + shell: pwsh + - id: getpackageversion + name: Bump UPM Package version + run: | + function UpdateProjectVersionJSON { + param ( + [Parameter(Mandatory)] + $type, + $packageFile = 'package.json' + ) + <# + Type of build can be one of the following + - 'build' # Build release - 1.0.0-pre.0+1 + - 'pre-release' # Pre-Release - 1.0.0-pre.1 + - 'patch-release' # Patch release - 1.0.1 (reset preview version to current patch, no increase) + - 'patch' # Patch release - 1.0.1 + - 'minor' # Minor release - 1.1.0 + - 'major' # Major release - 2.0.0 + #> + + if ( -not (Test-Path -Path $packageFile) ) { + Write-Error "Failed to find a valid project manifest at `"$packageFile`"" + return $null + } + + $packageInfo = (Get-Content $packageFile -Raw) | ConvertFrom-Json + Write-Host "Detected Project Version:" $packageInfo.version + function IfNull($a, $b, $c) { if ($null -eq $a) { return $b } else { return $c } } + + $packageSemVer = [System.Management.Automation.SemanticVersion]$packageInfo.version + $majorVersion = if($null -eq $packageSemVer.Major) {0} else {$packageSemVer.Major} + $minorVersion = if($null -eq $packageSemVer.Minor) {0} else {$packageSemVer.Minor} + $patchVersion = if($null -eq $packageSemVer.Patch) {0} else {$packageSemVer.Patch} + $prereleaseVersion = if($null -eq $packageSemVer.PreReleaseLabel) {0} else {$packageSemVer.PreReleaseLabel.Replace('pre.','')} + $buildVersion = if($null -eq $packageSemVer.BuildLabel) {0} else {$packageSemVer.BuildLabel} + + # work out new version + switch ($type) { + 'build' { + [int]$buildVersion += 1 + $newPackageSemVer = [System.Management.Automation.SemanticVersion]::New($majorVersion, $minorVersion, $patchVersion, "pre." + $prereleaseVersion, $buildVersion) + } + 'pre-release' { + [int]$prereleaseVersion += 1 + $newPackageSemVer = [System.Management.Automation.SemanticVersion]::New($majorVersion, $minorVersion, $patchVersion, "pre." + $prereleaseVersion) + } + 'patch-release' { + $newPackageSemVer = [System.Management.Automation.SemanticVersion]::New($majorVersion, $minorVersion, $patchVersion) + } + 'patch' { + [int]$patchVersion += 1 + $newPackageSemVer = [System.Management.Automation.SemanticVersion]::New($majorVersion, $minorVersion, $patchVersion) + } + 'minor' { + [int]$minorVersion += 1 + $newPackageSemVer = [System.Management.Automation.SemanticVersion]::New($majorVersion, $minorVersion, 0) + } + 'major' { + [int]$majorVersion += 1 + $newPackageSemVer = [System.Management.Automation.SemanticVersion]::New($majorVersion, 0, 0) + } + } + + Write-Host "Upgrading project version [$packageSemVer] to [$newPackageSemVer]" + + # Write out updated package info + + $packageInfo.version = $newPackageSemVer.ToString() + $packageInfo | ConvertTo-Json | Set-Content $packageFile + + return $packageInfo.version + } + + $packageFile = 'package.json' + $result = UpdateProjectVersionJSON("${{ inputs.build-type }}","$packageFile") + if([string]::IsNullOrEmpty($result)) { + echo "Version patch failed" + exit 1 + } + git add "$packageFile" + git commit -m "Auto increment pre-release version to $result [skip ci]" + git push origin + echo "packageversion=$result" >> $env:GITHUB_OUTPUT + shell: pwsh + - name: Check if Tag Exists + run: | + $tagVersion = '${{steps.getpackageversion.outputs.packageversion }}' + $tags = git tag + echo "Tags found are [$tags], searching for [$tagVersion]" + foreach ($tag in $tags) + { + if($tag.Trim() -eq "$tagVersion") + { + Write-Error "$tagVersion tag already exists" + exit 1 + } + } + shell: pwsh + - name: Publish package tag + if: ${{inputs.createTag == true}} + run: | + $outputVersion = '${{steps.getpackageversion.outputs.packageversion }}' + git tag -fa "v$outputVersion" "${GITHUB_SHA}" -m "v$outputVersion Release" + git push origin "v$outputVersion" --force --tags + shell: pwsh \ No newline at end of file