Skip to content
Open
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
699c9b3
feat(ui): replace static value labels with editable NumericUpDown con…
undead2146 Dec 28, 2025
755e532
feat: implement interactive numeric inputs for game settings (#223)
undead2146 Dec 28, 2025
71d5cdc
feat: fix CD disk detection; add manual folder picker (#222)
undead2146 Dec 31, 2025
9a2cb9e
refactor: centralize game settings mapping and fix persistence bugs (…
undead2146 Dec 31, 2025
b03ae8c
fix: refactor changelog generation logic in GitHub release (#226)
undead2146 Dec 31, 2025
4105527
feat: enhance game profile settings UI, local content, and dependency…
undead2146 Dec 31, 2025
6941a39
feat: implement GeneralsOnline profile reconciliation service and upd…
undead2146 Jan 1, 2026
fca61fb
fix: resolve development branch subscription logic (#224)
undead2146 Jan 1, 2026
fc1d179
refactor: improve process termination logic to prevent UI blocking (#…
undead2146 Jan 1, 2026
32a319a
feat: Implement data-driven provider definition configurations with e…
undead2146 Jan 1, 2026
048d06f
feat: image as backdrop and add header collapse functionality in Game…
undead2146 Jan 1, 2026
a7f2e4c
feat: add "Delete All User Data" logic to the `Delete all application…
undead2146 Jan 1, 2026
c694877
feat: add game type filter and enhance UI elements for better content…
undead2146 Jan 1, 2026
e1f6324
feat: add data directories access in settings tab (#236)
undead2146 Jan 2, 2026
5b7a8dc
feat: Implement Add Local Content feature with new ViewModel and UI (…
undead2146 Jan 3, 2026
615dc70
feat: Enhance Game Installation Service with manual installation stor…
undead2146 Jan 3, 2026
b20861a
fix: resolve generalsonline reconciler and update service (#240)
undead2146 Jan 4, 2026
59d3fa0
feat: redesign the GameProfileCards UI (#244)
undead2146 Jan 5, 2026
250e19b
feat(notifications): Add persistent notification feed with action sup…
undead2146 Jan 6, 2026
f3e8e93
fix(update): overhaul update system platform detection and PR subscri…
undead2146 Jan 7, 2026
d7d92fd
feat: Implement SteamLauncher for game directory preparation and prox…
undead2146 Jan 7, 2026
33dbae1
feat: Refactor and implement Map/Replay Managers and Tools Sidebar (#…
undead2146 Jan 8, 2026
17e2501
feat(content): implement foundation for AODMaps and CNCLabs pipelines…
undead2146 Jan 14, 2026
51ce8ee
feat: implement Tool Profile support for standalone executables and m…
undead2146 Jan 16, 2026
b48204e
fix: GO Reconciler fails to parse versions.
undead2146 Jan 16, 2026
1f1552a
fix: resolve the github and manifest factories regarding TSH content …
undead2146 Jan 19, 2026
72b0589
refactor: Add Executable and ModdingTool to the GameLauncher to track…
undead2146 Jan 21, 2026
b07845d
fix(deps): resolve security vulnerabilities in vite, preact, and esbu…
undead2146 Jan 22, 2026
e84b778
feat(gamelod): fix texture quality reset to low by mapping Very High …
undead2146 Jan 23, 2026
d6847b5
feat: Add Genhub.Tools project for CsvGenerationUtility (#221)
mnoserat Jan 23, 2026
d2359aa
feat: Set up the repository file structure for storing CSV registries…
mnoserat Jan 23, 2026
7e5e1ed
feat: redesign the gameprofile settings window (#258)
undead2146 Jan 24, 2026
11dd3ee
feat: info tab features, faq parser and sidebar refinements, (#248)
undead2146 Jan 25, 2026
5d4f1a7
feat: Add new styles for landing page website components and improve …
undead2146 Jan 25, 2026
df4d717
docs: resolve deadlinks in vitepress documentation site (#260)
undead2146 Jan 25, 2026
81e1843
refactor: Remove the active workspace for steamlauncher and use alrea…
undead2146 Jan 26, 2026
0354aad
refactor: filter non-workspace files from workspace strategies (#263)
undead2146 Jan 26, 2026
64adab9
Fix(github): resolve content downloaded from github not being launcha…
undead2146 Jan 26, 2026
9fb435a
feat: Implement copy profile functionality (#267)
undead2146 Jan 27, 2026
8a82b9f
feat(website): add a tracker for total installs and updates on github…
undead2146 Jan 30, 2026
71792f7
feat(notifications): add mute functionality, improve badge UI, and fi…
aRibals Feb 21, 2026
b937355
Fix: Resolve Hotkeys for legionnaire/leikeze not working and issue wi…
undead2146 Mar 1, 2026
8a09814
feat: replaced all quicklaunch occurances with quickstart (#279)
R3voA3 Mar 14, 2026
5ba2a51
feat: implement content reconciliation system with CAS lifecycle mana…
undead2146 Mar 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
47 changes: 47 additions & 0 deletions .github/scripts/inject-token.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
param(
[string]$Token
)

if ([string]::IsNullOrEmpty($Token)) {
# For PRs from forks, secrets are not available. We use a dummy token to allow the build to pass.
if ($env:GITHUB_EVENT_NAME -eq 'pull_request') {
Write-Host "Warning: No UPLOADTHING_TOKEN provided. Using dummy token for PR build."
$Token = "DUMMY_TOKEN_FOR_CI_ONLY"
} else {
Write-Error "No UPLOADTHING_TOKEN provided. Fails for Release builds."
exit 1
}
}

$constantsPath = "GenHub/GenHub.Core/Constants/ApiConstants.cs"
if (-not (Test-Path $constantsPath)) {
Write-Error "Could not find $constantsPath"
exit 1
}

$tokenBytes = [System.Text.Encoding]::UTF8.GetBytes($Token)
$key = New-Object byte[] 32
[System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($key)

$obfuscated = New-Object byte[] $tokenBytes.Length
for ($i = 0; $i -lt $tokenBytes.Length; $i++) {
$obfuscated[$i] = $tokenBytes[$i] -bxor $key[$i % $key.Length]
}

$dataStr = ($obfuscated | ForEach-Object { "0x{0:x2}" -f $_ }) -join ", "
$keyStr = ($key | ForEach-Object { "0x{0:x2}" -f $_ }) -join ", "

$content = Get-Content $constantsPath -Raw

# Use regex replace to be robust against whitespace
# Pattern: byte[] data = []; // [PLACEHOLDER_DATA]
$content = [System.Text.RegularExpressions.Regex]::Replace($content, 'byte\[\]\s+data\s*=\s*\[\];\s*//\s*\[PLACEHOLDER_DATA\]', "byte[] data = [$dataStr];")
$content = [System.Text.RegularExpressions.Regex]::Replace($content, 'byte\[\]\s+key\s*=\s*\[\];\s*//\s*\[PLACEHOLDER_KEY\]', "byte[] key = [$keyStr];")

if ($content -notmatch "0x") {
Write-Error "Token injection failed! Placeholders were not found or replaced."
exit 1
Comment on lines +36 to +43

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Strengthen placeholder validation to avoid false positives.

The current -notmatch "0x" check can succeed even if placeholders are not replaced (e.g., other hex literals exist), causing silent token injection failure. Prefer explicitly checking for leftover placeholders.

🔧 Suggested fix
- if ($content -notmatch "0x") {
-     Write-Error "Token injection failed! Placeholders were not found or replaced."
-     exit 1
- }
+ if ($content -match '\[PLACEHOLDER_DATA\]' -or $content -match '\[PLACEHOLDER_KEY\]') {
+     Write-Error "Token injection failed! Placeholders were not found or replaced."
+     exit 1
+ }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Use regex replace to be robust against whitespace
# Pattern: byte[] data = []; // [PLACEHOLDER_DATA]
$content = [System.Text.RegularExpressions.Regex]::Replace($content, 'byte\[\]\s+data\s*=\s*\[\];\s*//\s*\[PLACEHOLDER_DATA\]', "byte[] data = [$dataStr];")
$content = [System.Text.RegularExpressions.Regex]::Replace($content, 'byte\[\]\s+key\s*=\s*\[\];\s*//\s*\[PLACEHOLDER_KEY\]', "byte[] key = [$keyStr];")
if ($content -notmatch "0x") {
Write-Error "Token injection failed! Placeholders were not found or replaced."
exit 1
# Use regex replace to be robust against whitespace
# Pattern: byte[] data = []; // [PLACEHOLDER_DATA]
$content = [System.Text.RegularExpressions.Regex]::Replace($content, 'byte\[\]\s+data\s*=\s*\[\];\s*//\s*\[PLACEHOLDER_DATA\]', "byte[] data = [$dataStr];")
$content = [System.Text.RegularExpressions.Regex]::Replace($content, 'byte\[\]\s+key\s*=\s*\[\];\s*//\s*\[PLACEHOLDER_KEY\]', "byte[] key = [$keyStr];")
if ($content -match '\[PLACEHOLDER_DATA\]' -or $content -match '\[PLACEHOLDER_KEY\]') {
Write-Error "Token injection failed! Placeholders were not found or replaced."
exit 1
}
🤖 Prompt for AI Agents
In @.github/scripts/inject-token.ps1 around lines 36 - 43, The current
validation uses -notmatch "0x" which can produce false positives; instead
explicitly verify that the placeholders were removed and replacements inserted
by checking $content does not contain the literal placeholders
"[PLACEHOLDER_DATA]" or "[PLACEHOLDER_KEY]" (e.g., use -match/-notmatch against
'\[PLACEHOLDER_DATA\]' and '\[PLACEHOLDER_KEY\]') and also ensure the injected
arrays contain hex literals by confirming both the new byte[] data and byte[]
key blocks include "0x"; if any placeholder remains or the arrays lack "0x" then
Write-Error and exit 1.

}

Set-Content $constantsPath $content
Write-Host "Successfully injected and obfuscated UPLOADTHING_TOKEN into ApiConstants.cs"
11 changes: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ jobs:
echo "VERSION=$version" >> $env:GITHUB_OUTPUT
echo "CHANNEL=$channel" >> $env:GITHUB_OUTPUT

- name: Inject Secrets
shell: pwsh
run: |
./.github/scripts/inject-token.ps1 -Token "${{ secrets.UPLOADTHING_TOKEN }}"

Comment on lines +126 to +130

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Guard secret injection to trusted contexts only.

Running the token-injection step on PR CI (especially public repos) risks embedding UPLOADTHING_TOKEN into artifacts that can be downloaded, and will also fail on fork PRs where secrets are unavailable. Gate this step to trusted events/branches and skip if the secret is missing.

🔒 Suggested guard (apply to both Windows & Linux steps)
-      - name: Inject Secrets
-        shell: pwsh
-        run: |
-          ./.github/scripts/inject-token.ps1 -Token "${{ secrets.UPLOADTHING_TOKEN }}"
+      - name: Inject Secrets
+        if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && secrets.UPLOADTHING_TOKEN != '' }}
+        shell: pwsh
+        run: |
+          ./.github/scripts/inject-token.ps1 -Token "${{ secrets.UPLOADTHING_TOKEN }}"

Also applies to: 288-292

🤖 Prompt for AI Agents
In @.github/workflows/ci.yml around lines 126 - 130, The Inject Secrets step
currently runs unguarded and can fail or leak secrets on PRs/forks; update the
step named "Inject Secrets" (and the equivalent Linux step) to only run when a
secret is present and the workflow is a trusted event (e.g. not a pull_request),
by adding a GitHub Actions conditional such as if: ${{ github.event_name !=
'pull_request' && secrets.UPLOADTHING_TOKEN != '' }} so the ./
.github/scripts/inject-token.ps1 invocation is skipped when UPLOADTHING_TOKEN is
missing or the event is an untrusted PR/fork.

- name: Build Projects
shell: pwsh
run: |
Expand All @@ -142,6 +147,7 @@ jobs:
Write-Host "Building Windows project"
dotnet build "${{ env.WINDOWS_PROJECT }}" -c ${{ env.BUILD_CONFIGURATION }} @buildProps


- name: Publish Windows App
shell: pwsh
run: |
Expand Down Expand Up @@ -279,6 +285,11 @@ jobs:
echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT

- name: Inject Secrets
shell: pwsh
run: |
./.github/scripts/inject-token.ps1 -Token "${{ secrets.UPLOADTHING_TOKEN }}"

- name: Build Projects
run: |
BUILD_PROPS="-p:Version=${{ steps.buildinfo.outputs.VERSION }} -p:GitShortHash=${{ steps.buildinfo.outputs.SHORT_HASH }} -p:PullRequestNumber=${{ steps.buildinfo.outputs.PR_NUMBER }} -p:BuildChannel=${{ steps.buildinfo.outputs.CHANNEL }}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: BuildChannel output is never set in this job

steps.buildinfo.outputs.CHANNEL is referenced here, but the build-info step only echoes SHORT_HASH, PR_NUMBER, and VERSION. This leaves BuildChannel empty in CI builds, which can cause incorrect channel tagging or defaults. Consider exporting CHANNEL in the build-info step.

Expand Down
53 changes: 53 additions & 0 deletions .github/workflows/github-pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Deploy Landing Page to GitHub Pages

on:
workflow_run:
workflows: ["GenHub Release"]
types: [completed]
workflow_dispatch:

permissions:
contents: write
pages: write
id-token: write

jobs:
deploy:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Manual workflow dispatch will never run

For workflow_dispatch events, github.event.workflow_run is undefined, so this if condition evaluates to false and skips the job entirely. If you intend manual runs to work, the condition should allow workflow_dispatch (e.g., check github.event_name).

Comment on lines +14 to +17

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Manual dispatch will be skipped due to condition check.

The condition github.event.workflow_run.conclusion == 'success' evaluates to false (or undefined) when triggered via workflow_dispatch, causing the job to be skipped entirely for manual runs.

🐛 Proposed fix
 jobs:
   deploy:
     runs-on: ubuntu-latest
-    if: ${{ github.event.workflow_run.conclusion == 'success' }}
+    if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
🤖 Prompt for AI Agents
In @.github/workflows/github-pages.yml around lines 14 - 17, The deploy job's
conditional `if: ${{ github.event.workflow_run.conclusion == 'success' }}` skips
manual runs; update the deploy job (job name "deploy") to allow either a
successful workflow_run OR a manual dispatch by replacing the condition with
something like `if: ${{ github.event_name == 'workflow_dispatch' ||
github.event.workflow_run.conclusion == 'success' }}` so manual
`workflow_dispatch` triggers are not skipped.


steps:
- uses: actions/checkout@v4

- uses: actions/configure-pages@v5

- id: release_info
env:
GH_TOKEN: ${{ github.token }}
run: |
LATEST_TAG=$(gh release list --limit 1 --json tagName -q '.[0].tagName')

BUILD_NUM=$(echo "$LATEST_TAG" | cut -d'.' -f3)
DISPLAY_NAME="Alpha ${BUILD_NUM}"

echo "latest_tag=$LATEST_TAG" >> $GITHUB_OUTPUT
echo "display_name=$DISPLAY_NAME" >> $GITHUB_OUTPUT
Comment on lines +24 to +34

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add error handling for missing releases.

If no releases exist, gh release list returns an empty result, causing LATEST_TAG to be empty. This would result in an invalid download URL and display name.

🛡️ Suggested defensive check
       - id: release_info
         env:
           GH_TOKEN: ${{ github.token }}
         run: |
           LATEST_TAG=$(gh release list --limit 1 --json tagName -q '.[0].tagName')
+          
+          if [ -z "$LATEST_TAG" ]; then
+            echo "::error::No releases found"
+            exit 1
+          fi
           
           BUILD_NUM=$(echo "$LATEST_TAG" | cut -d'.' -f3)
           DISPLAY_NAME="Alpha ${BUILD_NUM}"
🤖 Prompt for AI Agents
In @.github/workflows/github-pages.yml around lines 24 - 34, The release_info
step currently assumes LATEST_TAG is set; add a defensive check after computing
LATEST_TAG in the release_info run block to handle when gh release list returns
empty: if LATEST_TAG is empty, either fail fast with a clear error message
(e.g., via echo and exit 1) or set safe defaults for BUILD_NUM and DISPLAY_NAME
and write those to GITHUB_OUTPUT so downstream steps don't construct invalid
URLs; update references to LATEST_TAG, BUILD_NUM, and DISPLAY_NAME in the
release_info step to use this validated/initialized value.


- run: |
mkdir -p ./public
cp Landing-page/index.html ./public/index.html

if [ -d "Landing-page/assets" ]; then
cp -r Landing-page/assets ./public/assets
fi

DOWNLOAD_URL="https://github.com/community-outpost/GenHub/releases/download/${{ steps.release_info.outputs.latest_tag }}/GenHub-win-Setup.exe"

sed -i "s|VERSION_PLACEHOLDER|${{ steps.release_info.outputs.display_name }}|g" ./public/index.html
sed -i "s|URL_PLACEHOLDER|${DOWNLOAD_URL}|g" ./public/index.html

- uses: actions/upload-pages-artifact@v3
with:
path: ./public

- uses: actions/deploy-pages@v4
Loading