Skip to content

Commit 3a99911

Browse files
committed
refresh the project; add workflows
1 parent fe28b97 commit 3a99911

20 files changed

Lines changed: 600 additions & 60 deletions
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Bug report
2+
description: Something in RedSand isn't behaving as expected
3+
labels: ["bug"]
4+
body:
5+
- type: textarea
6+
id: what
7+
attributes:
8+
label: What happened?
9+
description: Describe the unexpected behavior.
10+
validations:
11+
required: true
12+
13+
- type: textarea
14+
id: repro
15+
attributes:
16+
label: Steps to reproduce
17+
placeholder: |
18+
1. Run `...`
19+
2. Launch `RedSand.wsb`
20+
3. ...
21+
validations:
22+
required: true
23+
24+
- type: input
25+
id: windows-version
26+
attributes:
27+
label: Windows version
28+
placeholder: "e.g. Windows 11 Pro 23H2 (build 22631)"
29+
validations:
30+
required: true
31+
32+
- type: dropdown
33+
id: component
34+
attributes:
35+
label: Which component is involved?
36+
options:
37+
- RedSand.wsb
38+
- setup.ps1
39+
- installChocoAndScoop.ps1
40+
- installREToolkit.ps1
41+
- godMode.ps1
42+
- customScript.ps1
43+
- downloadSysinternalsSuite.ps1
44+
- downloadZimmermanTools.ps1
45+
- enableSandboxFeature.ps1
46+
- Docs / README
47+
- Other
48+
validations:
49+
required: true
50+
51+
- type: textarea
52+
id: logs
53+
attributes:
54+
label: Logs / screenshots
55+
description: Paste any error output or attach screenshots. Trim secrets.
56+
render: shell
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Feature request
2+
description: Suggest a new script, .wsb tweak, or improvement
3+
labels: ["enhancement"]
4+
body:
5+
- type: textarea
6+
id: problem
7+
attributes:
8+
label: What problem does this solve?
9+
description: What's the underlying friction or missing capability?
10+
validations:
11+
required: true
12+
13+
- type: textarea
14+
id: proposal
15+
attributes:
16+
label: Proposed change
17+
validations:
18+
required: true
19+
20+
- type: textarea
21+
id: alternatives
22+
attributes:
23+
label: Alternatives considered
24+
description: Workarounds you've tried, or other approaches you weighed.
25+
26+
- type: textarea
27+
id: context
28+
attributes:
29+
label: Additional context

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
## Summary
2+
3+
<!-- What changes, and why? -->
4+
5+
## Type
6+
7+
- [ ] New script
8+
- [ ] `.wsb` change
9+
- [ ] Existing script update / fix
10+
- [ ] Docs
11+
- [ ] CI / repo tooling
12+
13+
## Verification
14+
15+
- [ ] CI is green (PSScriptAnalyzer + syntax + XML)
16+
- [ ] Tested inside an actual Windows Sandbox (CI can't do this — please confirm manually for code changes)
17+
- [ ] If a new script was added, it's listed in the README scripts table
18+
- [ ] If upstream URLs changed, `url-liveness.yml` was updated to match
19+
20+
## Notes
21+
22+
<!-- Anything else reviewers should know -->

.github/dependabot.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "github-actions"
4+
directory: "/"
5+
schedule:
6+
interval: "weekly"

.github/workflows/ci.yml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [master]
6+
pull_request:
7+
8+
jobs:
9+
lint-and-validate:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
14+
- name: Install PSScriptAnalyzer
15+
shell: pwsh
16+
run: |
17+
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
18+
Install-Module -Name PSScriptAnalyzer -Force -Scope CurrentUser
19+
20+
- name: Lint PowerShell scripts
21+
shell: pwsh
22+
run: |
23+
$files = Get-ChildItem -Path . -Recurse -Filter *.ps1
24+
$results = $files | ForEach-Object {
25+
Invoke-ScriptAnalyzer -Path $_.FullName -Settings ./PSScriptAnalyzerSettings.psd1
26+
}
27+
if ($results) {
28+
$results | Format-Table -AutoSize | Out-String | Write-Host
29+
$errors = @($results | Where-Object Severity -eq 'Error')
30+
if ($errors.Count -gt 0) {
31+
Write-Host "::error::PSScriptAnalyzer found $($errors.Count) error(s)"
32+
exit 1
33+
}
34+
Write-Host "PSScriptAnalyzer: $($results.Count) non-error finding(s)"
35+
} else {
36+
Write-Host "PSScriptAnalyzer: no issues"
37+
}
38+
39+
- name: Parse PowerShell syntax
40+
shell: pwsh
41+
run: |
42+
$hadError = $false
43+
Get-ChildItem -Path . -Recurse -Filter *.ps1 | ForEach-Object {
44+
$parseErrors = $null
45+
[System.Management.Automation.Language.Parser]::ParseFile(
46+
$_.FullName, [ref]$null, [ref]$parseErrors
47+
) | Out-Null
48+
if ($parseErrors -and $parseErrors.Count -gt 0) {
49+
Write-Host "::error file=$($_.FullName)::Parse errors:"
50+
$parseErrors | ForEach-Object { Write-Host " $_" }
51+
$hadError = $true
52+
} else {
53+
Write-Host "OK: $($_.FullName)"
54+
}
55+
}
56+
if ($hadError) { exit 1 }
57+
58+
- name: Validate .wsb XML
59+
shell: pwsh
60+
run: |
61+
$hadError = $false
62+
Get-ChildItem -Path . -Recurse -Filter *.wsb | ForEach-Object {
63+
try {
64+
[xml](Get-Content $_.FullName -Raw) | Out-Null
65+
Write-Host "OK: $($_.FullName)"
66+
} catch {
67+
Write-Host "::error file=$($_.FullName)::XML invalid: $_"
68+
$hadError = $true
69+
}
70+
}
71+
if ($hadError) { exit 1 }

.github/workflows/url-liveness.yml

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
name: URL liveness
2+
3+
# Catches upstream changes before users do (e.g. an installer URL going 404, or
4+
# a release asset name pattern shifting like REtoolkit did when it switched from
5+
# _setup.exe to .7z).
6+
7+
on:
8+
schedule:
9+
- cron: '0 6 * * 1' # Mondays 06:00 UTC
10+
workflow_dispatch:
11+
12+
jobs:
13+
check-urls:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v4
17+
18+
- name: Probe upstream URLs
19+
shell: pwsh
20+
run: |
21+
$urls = @(
22+
'https://get.scoop.sh',
23+
'https://chocolatey.org/install.ps1',
24+
'https://www.7-zip.org/a/7zr.exe',
25+
'https://download.sysinternals.com/files/SysinternalsSuite.zip',
26+
'https://f001.backblazeb2.com/file/EricZimmermanTools/Get-ZimmermanTools.zip'
27+
)
28+
29+
function Test-Url {
30+
param([string]$Url)
31+
try {
32+
$r = Invoke-WebRequest -Uri $Url -Method Head -MaximumRedirection 5 -TimeoutSec 30 -ErrorAction Stop
33+
return @{ ok = $true; status = $r.StatusCode }
34+
} catch {
35+
# Some hosts don't allow HEAD — retry with a 1-byte Range GET
36+
try {
37+
$r = Invoke-WebRequest -Uri $Url -Headers @{ Range = 'bytes=0-0' } -MaximumRedirection 5 -TimeoutSec 30 -ErrorAction Stop
38+
return @{ ok = $true; status = $r.StatusCode }
39+
} catch {
40+
return @{ ok = $false; error = $_.Exception.Message }
41+
}
42+
}
43+
}
44+
45+
$failures = @()
46+
foreach ($u in $urls) {
47+
$result = Test-Url -Url $u
48+
if ($result.ok) {
49+
Write-Host "OK ($($result.status)): $u"
50+
} else {
51+
Write-Host "::error::FAIL: $u -> $($result.error)"
52+
$failures += $u
53+
}
54+
}
55+
56+
# Also verify the REtoolkit release still has a *.7z asset — the matcher
57+
# in installREToolkit.ps1 depends on it.
58+
try {
59+
$release = Invoke-RestMethod -Uri 'https://api.github.com/repos/mentebinaria/retoolkit/releases/latest' -TimeoutSec 30
60+
$asset = $release.assets | Where-Object { $_.name -like '*.7z' } | Select-Object -First 1
61+
if ($asset) {
62+
Write-Host "OK: retoolkit latest = $($release.tag_name), asset = $($asset.name)"
63+
} else {
64+
Write-Host "::error::retoolkit release $($release.tag_name) has no *.7z asset — installREToolkit.ps1 will break"
65+
$failures += 'retoolkit asset pattern'
66+
}
67+
} catch {
68+
Write-Host "::error::retoolkit API probe failed: $($_.Exception.Message)"
69+
$failures += 'retoolkit API'
70+
}
71+
72+
if ($failures.Count -gt 0) {
73+
Write-Host "::error::$($failures.Count) upstream(s) failed liveness check"
74+
exit 1
75+
}

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@ Utils/Toolkits/*
22
!Utils/Toolkits/.gitkeep
33

44
Files/*
5-
!Files/.gitkeep
5+
!Files/.gitkeep
6+
7+
# Work-in-progress profiles + their outputs — not yet released
8+
.drafts/

CONTRIBUTING.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Contributing to RedSand
2+
3+
Thanks for your interest! New scripts, `.wsb` profiles, and doc improvements are all welcome.
4+
5+
## Before you start
6+
7+
- For non-trivial changes, open an issue first to discuss the approach.
8+
- Keep changes scoped: one PR per logical change.
9+
10+
## Development setup
11+
12+
There's nothing to install — everything is `.ps1` and `.wsb`. To test your changes properly you need a host that already has Windows Sandbox enabled (see `enableSandboxFeature.ps1`).
13+
14+
## Style
15+
16+
- Prefer full cmdlet names over aliases (`Invoke-RestMethod`, not `irm`).
17+
- New scripts should start with `#Requires -Version 5.1` and `$ErrorActionPreference = 'Stop'`.
18+
- Use `$PSScriptRoot` for paths in scripts that depend on their own location — avoid relative paths that break depending on the caller's PWD.
19+
- If a script downloads a release asset, resolve "latest" dynamically via the project's release API rather than pinning a version.
20+
- Avoid `Write-Host` unless you genuinely need formatted user-facing output — otherwise prefer pipeline output.
21+
22+
## Adding a new script
23+
24+
1. Put it in the appropriate directory:
25+
- `Utils/Scripts/AdditionalScripts/OnHost/` — runs on the host
26+
- `Utils/Scripts/AdditionalScripts/InSandbox/` — runs inside the sandbox
27+
2. Add a row to the **Scripts reference** table in `README.md`.
28+
3. If it pulls from a new upstream URL, add that URL to `.github/workflows/url-liveness.yml`.
29+
30+
## CI
31+
32+
PRs run PSScriptAnalyzer, parse every `.ps1`, and validate the `.wsb` XML on `ubuntu-latest`. Make sure CI is green before requesting review.
33+
34+
Sandbox-level behavior can't be tested in CI (GitHub-hosted Windows runners don't support nested virtualization). For any code change, confirm manually that it works inside a real sandbox and note that in the PR description.
35+
36+
## Security
37+
38+
Don't open public issues for security vulnerabilities — see [SECURITY.md](SECURITY.md).

PSScriptAnalyzerSettings.psd1

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@{
2+
ExcludeRules = @(
3+
# Bootstrap scripts download install code from upstream (Scoop, Chocolatey) and run it —
4+
# Invoke-Expression on the downloaded string is the documented install pattern.
5+
'PSAvoidUsingInvokeExpression',
6+
7+
# Write-Host is used intentionally for human-readable status messages, not pipeline output.
8+
'PSAvoidUsingWriteHost'
9+
)
10+
}

0 commit comments

Comments
 (0)