From a763e56842f1580b37c8ca3a60ec8ec72c74eb50 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 29 May 2026 04:28:22 +0000
Subject: [PATCH 1/7] chore: harden GitHub workflows
---
.github/workflows/ci.yml | 20 ++++----
.github/workflows/codeql.yml | 63 +++++++++++++++++++++++++
.github/workflows/dependency-review.yml | 28 +++++++++++
.github/workflows/release.yml | 41 +++++++++-------
4 files changed, 128 insertions(+), 24 deletions(-)
create mode 100644 .github/workflows/codeql.yml
create mode 100644 .github/workflows/dependency-review.yml
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 774b6a67..46f454ce 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -31,10 +31,12 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v6
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+ with:
+ persist-credentials: false
- name: Setup .NET SDK
- uses: actions/setup-dotnet@v5
+ uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5
with:
global-json-file: global.json
cache: true
@@ -89,7 +91,7 @@ jobs:
- name: Upload test results
if: always()
- uses: actions/upload-artifact@v7
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: test-results
path: artifacts/test-results
@@ -97,7 +99,7 @@ jobs:
- name: Upload MSBuild binlogs
if: always()
- uses: actions/upload-artifact@v7
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: msbuild-binlogs
path: artifacts/binlogs
@@ -123,10 +125,12 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v6
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+ with:
+ persist-credentials: false
- name: Setup .NET SDK
- uses: actions/setup-dotnet@v5
+ uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5
with:
global-json-file: global.json
cache: true
@@ -176,7 +180,7 @@ jobs:
}
- name: Upload packaged CLI
- uses: actions/upload-artifact@v7
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: luotsi-cli-${{ matrix.rid }}
path: artifacts/packages/luotsi-cli-${{ matrix.rid }}.${{ matrix.archive_ext }}
@@ -184,7 +188,7 @@ jobs:
- name: Upload publish binlog
if: always()
- uses: actions/upload-artifact@v7
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: publish-binlog-${{ matrix.rid }}
path: |
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 00000000..656acec4
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,63 @@
+name: CodeQL
+
+on:
+ push:
+ branches:
+ - main
+ - master
+ pull_request:
+ schedule:
+ - cron: "27 4 * * 1"
+
+permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+concurrency:
+ group: codeql-${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+env:
+ DOTNET_NOLOGO: true
+ DOTNET_CLI_TELEMETRY_OPTOUT: true
+ DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
+
+jobs:
+ analyze:
+ name: Analyze C#
+ runs-on: ubuntu-latest
+ timeout-minutes: 30
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+ with:
+ persist-credentials: false
+
+ - name: Setup .NET SDK
+ uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5
+ with:
+ global-json-file: global.json
+ cache: true
+ cache-dependency-path: |
+ **/*.csproj
+ **/packages.lock.json
+ global.json
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4
+ with:
+ languages: csharp
+ build-mode: manual
+
+ - name: Restore
+ shell: bash
+ run: dotnet restore Luotsi.sln --locked-mode
+
+ - name: Build
+ shell: bash
+ run: dotnet build Luotsi.sln --configuration Release --no-restore
+
+ - name: Analyze
+ uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4
diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml
new file mode 100644
index 00000000..d49cca6d
--- /dev/null
+++ b/.github/workflows/dependency-review.yml
@@ -0,0 +1,28 @@
+name: Dependency Review
+
+on:
+ pull_request:
+
+permissions:
+ contents: read
+
+concurrency:
+ group: dependency-review-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ dependency-review:
+ name: Review dependency changes
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+ with:
+ persist-credentials: false
+
+ - name: Dependency review
+ uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
+ with:
+ fail-on-severity: high
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 7e9227f1..1dd66a14 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -11,11 +11,6 @@ on:
required: true
type: string
-permissions:
- contents: write
- id-token: write
- attestations: write
-
concurrency:
group: release-${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
cancel-in-progress: false
@@ -33,6 +28,8 @@ jobs:
name: Validate release tag
runs-on: ubuntu-latest
timeout-minutes: 5
+ permissions:
+ contents: read
outputs:
tag: ${{ steps.version.outputs.tag }}
version: ${{ steps.version.outputs.version }}
@@ -40,9 +37,10 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v6
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
+ persist-credentials: false
- name: Resolve version
id: version
@@ -87,15 +85,18 @@ jobs:
runs-on: windows-latest
needs: validate-tag
timeout-minutes: 20
+ permissions:
+ contents: read
steps:
- name: Checkout
- uses: actions/checkout@v6
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ needs.validate-tag.outputs.tag }}
+ persist-credentials: false
- name: Setup .NET SDK
- uses: actions/setup-dotnet@v5
+ uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5
with:
global-json-file: global.json
cache: true
@@ -133,7 +134,7 @@ jobs:
- name: Upload validation diagnostics
if: always()
- uses: actions/upload-artifact@v7
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: release-validation-diagnostics
path: |
@@ -148,6 +149,8 @@ jobs:
- validate-tag
- validate
timeout-minutes: 20
+ permissions:
+ contents: read
strategy:
fail-fast: false
matrix:
@@ -167,12 +170,13 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v6
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ needs.validate-tag.outputs.tag }}
+ persist-credentials: false
- name: Setup .NET SDK
- uses: actions/setup-dotnet@v5
+ uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5
with:
global-json-file: global.json
cache: true
@@ -238,7 +242,7 @@ jobs:
"$($hash.Hash.ToLowerInvariant()) $(Split-Path $archive -Leaf)" | Set-Content "$archive.sha256" -Encoding ascii
- name: Upload package
- uses: actions/upload-artifact@v7
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: release-package-${{ matrix.rid }}
path: |
@@ -247,7 +251,7 @@ jobs:
- name: Upload publish binlog
if: always()
- uses: actions/upload-artifact@v7
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: release-publish-binlog-${{ matrix.rid }}
path: |
@@ -263,15 +267,20 @@ jobs:
- validate
- package
timeout-minutes: 10
+ permissions:
+ contents: write
+ id-token: write
+ attestations: write
steps:
- name: Checkout tag
- uses: actions/checkout@v6
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ needs.validate-tag.outputs.tag }}
+ persist-credentials: false
- name: Download release packages
- uses: actions/download-artifact@v8
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
pattern: release-package-*
path: release-assets
@@ -295,7 +304,7 @@ jobs:
cat SHA256SUMS
- name: Attest release assets
- uses: actions/attest-build-provenance@v4
+ uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4
with:
subject-path: |
release-assets/*.zip
From 6eacfd3241ab15da94de5959a5279df21cafdc00 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 29 May 2026 04:31:17 +0000
Subject: [PATCH 2/7] chore: expand codeql workflow coverage
---
.github/workflows/codeql.yml | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 656acec4..08238588 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -25,9 +25,17 @@ env:
jobs:
analyze:
- name: Analyze C#
+ name: Analyze ${{ matrix.language }}
runs-on: ubuntu-latest
timeout-minutes: 30
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - language: actions
+ build-mode: none
+ - language: csharp
+ build-mode: manual
steps:
- name: Checkout
@@ -36,6 +44,7 @@ jobs:
persist-credentials: false
- name: Setup .NET SDK
+ if: matrix.language == 'csharp'
uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5
with:
global-json-file: global.json
@@ -48,14 +57,16 @@ jobs:
- name: Initialize CodeQL
uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4
with:
- languages: csharp
- build-mode: manual
+ languages: ${{ matrix.language }}
+ build-mode: ${{ matrix.build-mode }}
- name: Restore
+ if: matrix.language == 'csharp'
shell: bash
run: dotnet restore Luotsi.sln --locked-mode
- name: Build
+ if: matrix.language == 'csharp'
shell: bash
run: dotnet build Luotsi.sln --configuration Release --no-restore
From 31bd9c9561afcd84e659fcd8ac0c0285dde42e7e Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 29 May 2026 04:41:07 +0000
Subject: [PATCH 3/7] chore: pin NuGet source mapping and Gradle wrapper
checksum
---
.../gradle/wrapper/gradle-wrapper.properties | 1 +
NuGet.config | 12 ++++++++++++
2 files changed, 13 insertions(+)
create mode 100644 NuGet.config
diff --git a/Luotsi.ViewServer.Android/gradle/wrapper/gradle-wrapper.properties b/Luotsi.ViewServer.Android/gradle/wrapper/gradle-wrapper.properties
index c61a118f..80d82296 100644
--- a/Luotsi.ViewServer.Android/gradle/wrapper/gradle-wrapper.properties
+++ b/Luotsi.ViewServer.Android/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
+distributionSha256Sum=2ab2958f2a1e51120c326cad6f385153bb11ee93b3c216c5fccebfdfbb7ec6cb
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/NuGet.config b/NuGet.config
new file mode 100644
index 00000000..4e800bf6
--- /dev/null
+++ b/NuGet.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
From 86805cf2c9af1ac963221b6cc8cfa9a11f02cbc4 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 29 May 2026 04:57:18 +0000
Subject: [PATCH 4/7] chore: resolve merge conflicts with main
---
.github/workflows/ci.yml | 6 +-----
.github/workflows/release.yml | 6 +-----
.../gradle/wrapper/gradle-wrapper.properties | 4 ----
3 files changed, 2 insertions(+), 14 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e98dca7a..b1871636 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -281,12 +281,8 @@ jobs:
- name: Upload publish binlog
if: always()
-<<<<<<< HEAD
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
-=======
continue-on-error: true
- uses: actions/upload-artifact@v7
->>>>>>> origin/main
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: publish-binlog-${{ matrix.rid }}
path: |
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index d3caeaff..5f00cb2b 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -422,12 +422,8 @@ jobs:
- name: Upload publish binlog
if: always()
-<<<<<<< HEAD
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
-=======
continue-on-error: true
- uses: actions/upload-artifact@v7
->>>>>>> origin/main
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: release-publish-binlog-${{ matrix.rid }}
path: |
diff --git a/Luotsi.ViewServer.Android/gradle/wrapper/gradle-wrapper.properties b/Luotsi.ViewServer.Android/gradle/wrapper/gradle-wrapper.properties
index aa0f0260..ac0d302a 100644
--- a/Luotsi.ViewServer.Android/gradle/wrapper/gradle-wrapper.properties
+++ b/Luotsi.ViewServer.Android/gradle/wrapper/gradle-wrapper.properties
@@ -1,12 +1,8 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
-<<<<<<< HEAD
distributionSha256Sum=2ab2958f2a1e51120c326cad6f385153bb11ee93b3c216c5fccebfdfbb7ec6cb
-networkTimeout=10000
-=======
networkTimeout=60000
->>>>>>> origin/main
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
From 1b3ceac3f301d96cc6fd716a1a3a332c4f920a4d Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 29 May 2026 05:21:46 +0000
Subject: [PATCH 5/7] Include NuGet.config in setup-dotnet cache dependency
paths
---
.github/workflows/ci.yml | 2 ++
.github/workflows/codeql.yml | 1 +
.github/workflows/release.yml | 2 ++
3 files changed, 5 insertions(+)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b1871636..80fd7ada 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -44,6 +44,7 @@ jobs:
**/*.csproj
**/packages.lock.json
global.json
+ NuGet.config
- name: SDK diagnostics
shell: pwsh
@@ -207,6 +208,7 @@ jobs:
**/*.csproj
**/packages.lock.json
global.json
+ NuGet.config
- name: Setup Java
uses: actions/setup-java@v5
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 08238588..97e9f2c9 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -53,6 +53,7 @@ jobs:
**/*.csproj
**/packages.lock.json
global.json
+ NuGet.config
- name: Initialize CodeQL
uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 5f00cb2b..6089249c 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -109,6 +109,7 @@ jobs:
**/*.csproj
**/packages.lock.json
global.json
+ NuGet.config
- name: Restore
shell: pwsh
@@ -226,6 +227,7 @@ jobs:
**/*.csproj
**/packages.lock.json
global.json
+ NuGet.config
- name: Setup Java
uses: actions/setup-java@v5
From 75ea94bce441bda03732e4d374c9701dc68fb89f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 29 May 2026 05:35:07 +0000
Subject: [PATCH 6/7] chore: disable codeql workflow file
---
.github/workflows/{codeql.yml => codeql.yml.disabled} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename .github/workflows/{codeql.yml => codeql.yml.disabled} (100%)
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml.disabled
similarity index 100%
rename from .github/workflows/codeql.yml
rename to .github/workflows/codeql.yml.disabled
From 8ae0ba93889e47cf3d70d00df95511a8aa88ff5f Mon Sep 17 00:00:00 2001
From: Slideep
Date: Fri, 29 May 2026 14:55:57 +0300
Subject: [PATCH 7/7] Harden workflow action pins and Android helper build
---
.github/workflows/ci.yml | 93 +++++++++++++----
.github/workflows/codeql.yml.disabled | 75 --------------
.github/workflows/pages.yml | 12 ++-
.github/workflows/release.yml | 143 +++++++++++++++++---------
4 files changed, 178 insertions(+), 145 deletions(-)
delete mode 100644 .github/workflows/codeql.yml.disabled
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 80fd7ada..f656b04a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -129,7 +129,7 @@ jobs:
- name: Upload coverage report
if: always()
- uses: actions/upload-artifact@v7
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: coverage-report
path: artifacts/coverage-report
@@ -150,10 +150,12 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v6
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+ with:
+ persist-credentials: false
- name: Setup Node.js
- uses: actions/setup-node@v6
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version: 22
cache: npm
@@ -171,10 +173,66 @@ jobs:
working-directory: website
run: npm run build
+ android-helper:
+ name: Build Android view helper
+ runs-on: windows-latest
+ timeout-minutes: 20
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+ with:
+ persist-credentials: false
+
+ - name: Setup Java
+ uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
+ with:
+ distribution: temurin
+ java-version: "17"
+ cache: gradle
+
+ - name: Build Android helper APK
+ shell: pwsh
+ run: |
+ $wrapper = ".\Luotsi.ViewServer.Android\gradlew.bat"
+ $arguments = @("--no-daemon", "-p", "Luotsi.ViewServer.Android", ":app:assembleRelease")
+ $maxAttempts = 3
+ $exitCode = 0
+
+ for ($attempt = 1; $attempt -le $maxAttempts; $attempt++) {
+ & $wrapper @arguments
+ $exitCode = $LASTEXITCODE
+ if ($exitCode -eq 0) {
+ break
+ }
+
+ if ($attempt -eq $maxAttempts) {
+ exit $exitCode
+ }
+
+ $delaySeconds = 20 * $attempt
+ Write-Warning "Android helper build failed with exit code $exitCode. Retrying in $delaySeconds seconds ($attempt/$maxAttempts)."
+ Start-Sleep -Seconds $delaySeconds
+ }
+
+ $apk = "Luotsi.ViewServer.Android/app/build/outputs/apk/release/app-release.apk"
+ if (!(Test-Path -LiteralPath $apk)) {
+ throw "Android view helper release APK was not produced at $apk."
+ }
+
+ - name: Upload Android helper APK
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
+ with:
+ name: android-helper-apk
+ path: Luotsi.ViewServer.Android/app/build/outputs/apk/release/app-release.apk
+ if-no-files-found: error
+
publish:
name: Publish ${{ matrix.rid }}
runs-on: windows-latest
- needs: validate
+ needs:
+ - validate
+ - android-helper
timeout-minutes: 20
strategy:
fail-fast: false
@@ -210,24 +268,22 @@ jobs:
global.json
NuGet.config
- - name: Setup Java
- uses: actions/setup-java@v5
- with:
- distribution: temurin
- java-version: "17"
- cache: gradle
-
- name: Verify locked restore
shell: pwsh
run: dotnet restore $env:SOLUTION --locked-mode /bl:artifacts/binlogs/publish-restore-${{ matrix.rid }}.binlog
- - name: Build Android view helper
+ - name: Download Android view helper
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
+ with:
+ name: android-helper-apk
+ path: Luotsi.ViewServer.Android/app/build/outputs/apk/release
+
+ - name: Verify Android view helper
shell: pwsh
run: |
- $wrapper = ".\Luotsi.ViewServer.Android\gradlew.bat"
- & $wrapper -p Luotsi.ViewServer.Android :app:assembleRelease
- if ($LASTEXITCODE -ne 0) {
- exit $LASTEXITCODE
+ $helper = "Luotsi.ViewServer.Android/app/build/outputs/apk/release/app-release.apk"
+ if (!(Test-Path -LiteralPath $helper)) {
+ throw "Downloaded Android view helper APK is missing: $helper"
}
- name: Stage FFmpeg native libraries
@@ -298,14 +354,15 @@ jobs:
needs:
- validate
- website
+ - android-helper
- publish
if: always()
steps:
- name: Check required jobs
shell: bash
run: |
- if [[ "${{ needs.validate.result }}" != "success" || "${{ needs.website.result }}" != "success" || "${{ needs.publish.result }}" != "success" ]]; then
- echo "CI failed: validate=${{ needs.validate.result }}, website=${{ needs.website.result }}, publish=${{ needs.publish.result }}"
+ if [[ "${{ needs.validate.result }}" != "success" || "${{ needs.website.result }}" != "success" || "${{ needs.android-helper.result }}" != "success" || "${{ needs.publish.result }}" != "success" ]]; then
+ echo "CI failed: validate=${{ needs.validate.result }}, website=${{ needs.website.result }}, android-helper=${{ needs.android-helper.result }}, publish=${{ needs.publish.result }}"
exit 1
fi
echo "CI passed."
diff --git a/.github/workflows/codeql.yml.disabled b/.github/workflows/codeql.yml.disabled
deleted file mode 100644
index 97e9f2c9..00000000
--- a/.github/workflows/codeql.yml.disabled
+++ /dev/null
@@ -1,75 +0,0 @@
-name: CodeQL
-
-on:
- push:
- branches:
- - main
- - master
- pull_request:
- schedule:
- - cron: "27 4 * * 1"
-
-permissions:
- actions: read
- contents: read
- security-events: write
-
-concurrency:
- group: codeql-${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-env:
- DOTNET_NOLOGO: true
- DOTNET_CLI_TELEMETRY_OPTOUT: true
- DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
-
-jobs:
- analyze:
- name: Analyze ${{ matrix.language }}
- runs-on: ubuntu-latest
- timeout-minutes: 30
- strategy:
- fail-fast: false
- matrix:
- include:
- - language: actions
- build-mode: none
- - language: csharp
- build-mode: manual
-
- steps:
- - name: Checkout
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- with:
- persist-credentials: false
-
- - name: Setup .NET SDK
- if: matrix.language == 'csharp'
- uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5
- with:
- global-json-file: global.json
- cache: true
- cache-dependency-path: |
- **/*.csproj
- **/packages.lock.json
- global.json
- NuGet.config
-
- - name: Initialize CodeQL
- uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4
- with:
- languages: ${{ matrix.language }}
- build-mode: ${{ matrix.build-mode }}
-
- - name: Restore
- if: matrix.language == 'csharp'
- shell: bash
- run: dotnet restore Luotsi.sln --locked-mode
-
- - name: Build
- if: matrix.language == 'csharp'
- shell: bash
- run: dotnet build Luotsi.sln --configuration Release --no-restore
-
- - name: Analyze
- uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4
diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
index 5269a0ca..901748d4 100644
--- a/.github/workflows/pages.yml
+++ b/.github/workflows/pages.yml
@@ -23,17 +23,19 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v6
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+ with:
+ persist-credentials: false
- name: Setup Node.js
- uses: actions/setup-node@v6
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version: 22
cache: npm
cache-dependency-path: website/package-lock.json
- name: Configure GitHub Pages
- uses: actions/configure-pages@v6
+ uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6
- name: Install website dependencies
working-directory: website
@@ -44,7 +46,7 @@ jobs:
run: npm run build
- name: Upload Pages artifact
- uses: actions/upload-pages-artifact@v5
+ uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5
with:
path: website/dist
@@ -59,4 +61,4 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
- uses: actions/deploy-pages@v5
\ No newline at end of file
+ uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 6089249c..49a0745f 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -179,37 +179,19 @@ jobs:
- name: Upload coverage report
if: always()
- uses: actions/upload-artifact@v7
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: release-coverage-report
path: artifacts/coverage-report
if-no-files-found: ignore
- package:
- name: Package ${{ matrix.rid }}
- runs-on: ${{ matrix.runner }}
- needs:
- - validate-tag
- - validate
+ android-helper:
+ name: Build Android view helper
+ runs-on: windows-latest
+ needs: validate-tag
timeout-minutes: 20
permissions:
contents: read
- strategy:
- fail-fast: false
- matrix:
- include:
- - rid: win-x64
- archive_ext: zip
- runner: windows-latest
- - rid: linux-x64
- archive_ext: tar.gz
- runner: ubuntu-latest
- - rid: osx-x64
- archive_ext: tar.gz
- runner: ubuntu-latest
- - rid: osx-arm64
- archive_ext: tar.gz
- runner: ubuntu-latest
steps:
- name: Checkout
@@ -218,29 +200,14 @@ jobs:
ref: ${{ needs.validate-tag.outputs.tag }}
persist-credentials: false
- - name: Setup .NET SDK
- uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5
- with:
- global-json-file: global.json
- cache: true
- cache-dependency-path: |
- **/*.csproj
- **/packages.lock.json
- global.json
- NuGet.config
-
- name: Setup Java
- uses: actions/setup-java@v5
+ uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: temurin
java-version: "17"
cache: gradle
- - name: Verify locked restore
- shell: pwsh
- run: dotnet restore $env:SOLUTION --locked-mode /bl:artifacts/binlogs/release-publish-restore-${{ matrix.rid }}.binlog
-
- - name: Build Android view helper
+ - name: Build signed Android helper APK
shell: pwsh
env:
LUOTSI_ANDROID_KEYSTORE_BASE64: ${{ secrets.LUOTSI_ANDROID_KEYSTORE_BASE64 }}
@@ -267,13 +234,25 @@ jobs:
Write-Host "Using Luotsi Android release signing key from GitHub secrets."
Write-Host "Stamping Android helper version $env:LUOTSI_ANDROID_VERSION_NAME ($env:LUOTSI_ANDROID_VERSION_CODE)."
- if ($IsWindows) {
- & ".\Luotsi.ViewServer.Android\gradlew.bat" -p Luotsi.ViewServer.Android :app:assembleRelease
- } else {
- & bash "./Luotsi.ViewServer.Android/gradlew" -p Luotsi.ViewServer.Android :app:assembleRelease
- }
- if ($LASTEXITCODE -ne 0) {
- exit $LASTEXITCODE
+ $wrapper = ".\Luotsi.ViewServer.Android\gradlew.bat"
+ $arguments = @("--no-daemon", "-p", "Luotsi.ViewServer.Android", ":app:assembleRelease")
+ $maxAttempts = 3
+ $exitCode = 0
+
+ for ($attempt = 1; $attempt -le $maxAttempts; $attempt++) {
+ & $wrapper @arguments
+ $exitCode = $LASTEXITCODE
+ if ($exitCode -eq 0) {
+ break
+ }
+
+ if ($attempt -eq $maxAttempts) {
+ exit $exitCode
+ }
+
+ $delaySeconds = 20 * $attempt
+ Write-Warning "Android helper build failed with exit code $exitCode. Retrying in $delaySeconds seconds ($attempt/$maxAttempts)."
+ Start-Sleep -Seconds $delaySeconds
}
$releaseApkDir = Join-Path $PWD "Luotsi.ViewServer.Android/app/build/outputs/apk/release"
@@ -294,6 +273,76 @@ jobs:
Write-Host "Android helper output: $($_.FullName)"
}
+ - name: Upload Android helper APK
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
+ with:
+ name: android-helper-apk
+ path: Luotsi.ViewServer.Android/app/build/outputs/apk/release/app-release.apk
+ if-no-files-found: error
+
+ package:
+ name: Package ${{ matrix.rid }}
+ runs-on: ${{ matrix.runner }}
+ needs:
+ - validate-tag
+ - validate
+ - android-helper
+ timeout-minutes: 20
+ permissions:
+ contents: read
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - rid: win-x64
+ archive_ext: zip
+ runner: windows-latest
+ - rid: linux-x64
+ archive_ext: tar.gz
+ runner: ubuntu-latest
+ - rid: osx-x64
+ archive_ext: tar.gz
+ runner: ubuntu-latest
+ - rid: osx-arm64
+ archive_ext: tar.gz
+ runner: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+ with:
+ ref: ${{ needs.validate-tag.outputs.tag }}
+ persist-credentials: false
+
+ - name: Setup .NET SDK
+ uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5
+ with:
+ global-json-file: global.json
+ cache: true
+ cache-dependency-path: |
+ **/*.csproj
+ **/packages.lock.json
+ global.json
+ NuGet.config
+
+ - name: Verify locked restore
+ shell: pwsh
+ run: dotnet restore $env:SOLUTION --locked-mode /bl:artifacts/binlogs/release-publish-restore-${{ matrix.rid }}.binlog
+
+ - name: Download Android view helper
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
+ with:
+ name: android-helper-apk
+ path: Luotsi.ViewServer.Android/app/build/outputs/apk/release
+
+ - name: Verify Android view helper
+ shell: pwsh
+ run: |
+ $helper = "Luotsi.ViewServer.Android/app/build/outputs/apk/release/app-release.apk"
+ if (!(Test-Path -LiteralPath $helper)) {
+ throw "Downloaded Android view helper APK is missing: $helper"
+ }
+
- name: Publish
shell: pwsh
run: >