Skip to content

Add temporary compiler-driven migration script #22

Add temporary compiler-driven migration script

Add temporary compiler-driven migration script #22

name: .NET 10 migration build
on:
push:
branches:
- agent/net10-mudblazor-migration
pull_request:
branches:
- magiccodingman/net10
workflow_dispatch:
permissions:
contents: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repair branch
uses: actions/checkout@v4
with:
ref: agent/net10-mudblazor-migration
- name: Apply compiler-driven migration fixes
shell: bash
run: |
python3 <<'PY'
from pathlib import Path
def replace(path: str, old: str, new: str) -> None:
file = Path(path)
text = file.read_text(encoding="utf-8-sig")
if old in text:
file.write_text(text.replace(old, new), encoding="utf-8")
dashboard = "TruthGate-Web/TruthGate-Web/Components/Shared/DashboardMetrics.razor"
replace(dashboard, " MatchBoundsToSize = true,\n", "")
replace(dashboard, ".AsChartDataSet()", "")
api_keys = "TruthGate-Web/TruthGate-Web/Components/Pages/Settings/ApiKeys.razor"
replace(api_keys,
'Dialogs.ShowAsync("Add API Key", p,',
'Dialogs.ShowAsync<AddApiKeyDialog>("Add API Key", p,')
replace(api_keys,
"if (result.Canceled || result.Data is not AddApiKeyDialog.AddApiKeyResult r) return;",
"if (result is null || result.Canceled || result.Data is not AddApiKeyDialog.AddApiKeyResult r) return;")
replace(api_keys,
"if (result.Canceled || result.Data is not bool yes || !yes) return;",
"if (result is null || result.Canceled || result.Data is not bool yes || !yes) return;")
ip_bans = "TruthGate-Web/TruthGate-Web/Components/Pages/Settings/IpBansPage.razor"
replace(ip_bans,
"LoadBansGridAsync(GridState<BanDto> state)",
"LoadBansGridAsync(GridState<BanDto> state, CancellationToken cancellationToken)")
replace(ip_bans,
"LoadWhitelistIpGridAsync(GridState<Whitelist> state)",
"LoadWhitelistIpGridAsync(GridState<Whitelist> state, CancellationToken cancellationToken)")
replace(ip_bans,
"LoadWhitelistPrefixGridAsync(GridState<Whitelist> state)",
"LoadWhitelistPrefixGridAsync(GridState<Whitelist> state, CancellationToken cancellationToken)")
replace(ip_bans, "Dialogs.ShowMessageBox(", "Dialogs.ShowMessageBoxAsync(")
replace(ip_bans, 'Sortable="false"', 'SortMode="SortMode.None"')
replace(ip_bans,
'await Dialogs.ShowAsync<SearchIpDialog>("Search IP", parameters, new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small }).Result;',
'var dialog = await Dialogs.ShowAsync<SearchIpDialog>("Search IP", parameters, new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small });\n await dialog.Result;')
replace(ip_bans,
'await Dialogs.ShowAsync<AddBanDialog>("Add Ban", new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small }).Result;',
'var dialog = await Dialogs.ShowAsync<AddBanDialog>("Add Ban", new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small });\n await dialog.Result;')
replace(ip_bans,
"DbFactory.CreateDbContextAsync();",
"DbFactory.CreateDbContextAsync(cancellationToken);")
replace(ip_bans, "q.CountAsync();", "q.CountAsync(cancellationToken);")
replace(ip_bans, ".ToListAsync();", ".ToListAsync(cancellationToken);")
simple_prompt = "TruthGate-Web/TruthGate-Web/Components/Shared/SimplePromptDialog.razor"
replace(simple_prompt, '<MudForm @ref="_form" Validation="Validate">', '<MudForm @ref="_form">')
replace(simple_prompt,
'Required="@Required"\n Lines=',
'Required="@Required"\n Validation="@(new Func<string?, string?>(ValidateValue))"\n Lines=')
replace(simple_prompt,
''' private IEnumerable<string> Validate()
{

Check failure on line 82 in .github/workflows/net10-migration-build.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/net10-migration-build.yml

Invalid workflow file

You have an error in your yaml syntax on line 82
_error = null;
if (Required && string.IsNullOrWhiteSpace(_value))
{
_error = "Please enter a value.";
yield return _error;
}
}
''',
''' private string? ValidateValue(string? value)
{
_error = null;
if (Required && string.IsNullOrWhiteSpace(value))
return _error = "Please enter a value.";
return null;
}
''')
replace(simple_prompt, "await _form.Validate();", "await _form.ValidateAsync();")
add_pinned = "TruthGate-Web/TruthGate-Web/Components/Shared/AddPinnedItemDialog.razor"
replace(add_pinned,
'<MudForm @ref="_form" Model="_model" Validation="Validate">',
'<MudForm @ref="_form" Model="_model">')
add_ipns = "TruthGate-Web/TruthGate-Web/Components/Shared/AddOrEditIpnsDialog.razor"
replace(add_ipns,
'<MudForm @ref="_form" Model="_model" Validation="Validate">',
'<MudForm @ref="_form" Model="_model">')
replace(add_ipns,
'Required="true"\n Disabled="_isEdit" />',
'Required="true"\n Validation="@(new Func<string?, string?>(ValidateName))"\n Disabled="_isEdit" />',
)
# The second required/disabled field is the IPNS key; correct its validator after the global replacement.
replace(add_ipns,
'Label="IPNS Key (k51… or /ipns/k51…)"\n @bind-Value="_model.Key"\n Immediate="true"\n Required="true"\n Validation="@(new Func<string?, string?>(ValidateName))"',
'Label="IPNS Key (k51… or /ipns/k51…)"\n @bind-Value="_model.Key"\n Immediate="true"\n Required="true"\n Validation="@(new Func<string?, string?>(ValidateKey))"')
replace(add_ipns,
''' private IEnumerable<string> Validate()
{
_error = null;
if (string.IsNullOrWhiteSpace(_model.Name))
yield return "Name is required.";
if (string.IsNullOrWhiteSpace(_model.Key))
yield return "IPNS key is required.";
var leaf = IpfsGateway.ToSafeLeaf(_model.Name);
if (leaf is null)
yield return "Invalid name.";
if (!_model.Key.StartsWith("k51") && !_model.Key.StartsWith("/ipns/"))
yield return "IPNS Key should look like k51… or /ipns/k51…";
}
''',
''' private string? ValidateName(string? value)
{
if (string.IsNullOrWhiteSpace(value))
return "Name is required.";
return IpfsGateway.ToSafeLeaf(value) is null ? "Invalid name." : null;
}
private static string? ValidateKey(string? value)
{
if (string.IsNullOrWhiteSpace(value))
return "IPNS key is required.";
return value.StartsWith("k51", StringComparison.OrdinalIgnoreCase) ||
value.StartsWith("/ipns/k51", StringComparison.OrdinalIgnoreCase)
? null
: "IPNS Key should look like k51… or /ipns/k51…";
}
''')
replace(add_ipns, "private async void Submit()", "private async Task Submit()")
replace(add_ipns, "await _form.Validate();", "await _form.ValidateAsync();")
replace(add_ipns,
'<MudGrid Spacing="2" AlignItems="AlignItems.Center">',
'<MudGrid Spacing="2" Style="align-items:center;">')
search_ip = "TruthGate-Web/TruthGate-Web/Components/Pages/Settings/Shared/SearchIpDialog.razor"
replace(search_ip, '<MudForm @ref="_form" Validation="Validate">', '<MudForm @ref="_form">')
replace(search_ip,
'Required="true"\n @onkeydown=',
'Required="true"\n Validation="@(new Func<string?, string?>(ValidateIp))"\n @onkeydown=')
replace(search_ip,
''' private IEnumerable<string> Validate()
{
_error = null;
if (string.IsNullOrWhiteSpace(_ip))
{
_error = "Please enter an IP address.";
yield return _error;
yield break;
}
if (!IPAddress.TryParse(_ip, out _))
{
_error = "Invalid IP format (v4 or v6 required).";
yield return _error;
}
}
''',
''' private string? ValidateIp(string? value)
{
_error = null;
if (string.IsNullOrWhiteSpace(value))
return _error = "Please enter an IP address.";
if (!IPAddress.TryParse(value, out _))
return _error = "Invalid IP format (v4 or v6 required).";
return null;
}
''')
replace(search_ip, "await _form.Validate();", "await _form.ValidateAsync();")
replace(search_ip, 'Sortable="false"', 'SortMode="SortMode.None"')
domains = "TruthGate-Web/TruthGate-Web/Components/Pages/Settings/Domains.razor"
replace(domains, 'Class="truncate-text" Title="@context.RedirectUrl"', 'Class="truncate-text" title="@context.RedirectUrl"')
replace(domains,
'Color="Color.Primary" Variant="Variant.Outlined" StartIcon="@Icons.Material.Filled.Link"',
'Color="Color.Primary" Variant="Variant.Outlined" Icon="@Icons.Material.Filled.Link"')
replace(domains,
'Color="Color.Primary" Variant="Variant.Outlined" StartIcon="@Icons.Material.Filled.Fingerprint"',
'Color="Color.Primary" Variant="Variant.Outlined" Icon="@Icons.Material.Filled.Fingerprint"')
PY
if ! git diff --quiet; then
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add TruthGate-Web/TruthGate-Web/Components/Shared/DashboardMetrics.razor \
TruthGate-Web/TruthGate-Web/Components/Pages/Settings/ApiKeys.razor \
TruthGate-Web/TruthGate-Web/Components/Pages/Settings/IpBansPage.razor \
TruthGate-Web/TruthGate-Web/Components/Shared/SimplePromptDialog.razor \
TruthGate-Web/TruthGate-Web/Components/Shared/AddPinnedItemDialog.razor \
TruthGate-Web/TruthGate-Web/Components/Shared/AddOrEditIpnsDialog.razor \
TruthGate-Web/TruthGate-Web/Components/Pages/Settings/Shared/SearchIpDialog.razor \
TruthGate-Web/TruthGate-Web/Components/Pages/Settings/Domains.razor
git commit -m "Finish MudBlazor 9 form and component migrations"
git push origin HEAD:agent/net10-mudblazor-migration
fi
- name: Setup .NET 10
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x
- name: Restore
run: dotnet restore TruthGate-IPFS.sln
- name: Build
id: build
shell: bash
run: |
set +e
dotnet build TruthGate-IPFS.sln --configuration Release --no-restore > net10-build.log 2>&1
status=$?
echo "status=$status" >> "$GITHUB_OUTPUT"
tail -n 200 net10-build.log
exit 0
- name: Upload build diagnostics
if: always()
uses: actions/upload-artifact@v4
with:
name: net10-build-log
path: net10-build.log
if-no-files-found: error
- name: Report build failure
if: steps.build.outputs.status != '0'
run: exit 1