feat: add shared runtime abstractions packages
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
name: Publish NuGet packages
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
env:
|
||||
NUGET_AUTH_TOKEN: ${{ secrets.SHRINKSDK_PACKAGE_TOKEN }}
|
||||
steps:
|
||||
- name: Checkout tagged source
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: '8.0.x'
|
||||
|
||||
- name: Validate tag and pack projects
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
tag="${GITEA_REF#refs/tags/}"
|
||||
version="$(node -p "require('./package.json').version")"
|
||||
test "$tag" = "v$version"
|
||||
mkdir -p packages
|
||||
mapfile -d '' projects < <(find DotNet~ Godot~ -type f -name '*.csproj' -print0 2>/dev/null || true)
|
||||
test "${#projects[@]}" -gt 0
|
||||
for project in "${projects[@]}"; do
|
||||
dotnet restore "$project" --configfile NuGet.Config
|
||||
dotnet pack "$project" --configuration Release --no-restore --output "$PWD/packages" --include-symbols --include-source
|
||||
done
|
||||
find packages -maxdepth 1 -name '*.nupkg' -type f | grep -q .
|
||||
|
||||
- name: Publish packages
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
: "${NUGET_AUTH_TOKEN:?SHRINKSDK_PACKAGE_TOKEN is required}"
|
||||
dotnet nuget push 'packages/*.nupkg' --api-key "$NUGET_AUTH_TOKEN" --source https://git.crash.work/api/packages/ShrinkSDK/nuget/index.json --skip-duplicate
|
||||
if compgen -G 'packages/*.snupkg' > /dev/null; then
|
||||
dotnet nuget push 'packages/*.snupkg' --api-key "$NUGET_AUTH_TOKEN" --source https://git.crash.work/api/packages/ShrinkSDK/nuget/index.json --skip-duplicate
|
||||
fi
|
||||
@@ -0,0 +1,67 @@
|
||||
name: Publish UPM package
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.SHRINKSDK_PACKAGE_TOKEN }}
|
||||
steps:
|
||||
- name: Fetch exact tagged release archive
|
||||
env:
|
||||
GITEA_REF: ${{ gitea.ref }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
tag="${GITEA_REF#refs/tags/}"
|
||||
case "$tag" in
|
||||
v[0-9]*) ;;
|
||||
*) echo "Expected a version tag ref, got: $GITEA_REF" >&2; exit 1 ;;
|
||||
esac
|
||||
export SHRINKSDK_ARCHIVE_URL="https://git.crash.work/ShrinkSDK/ShrinkRuntime.Abstractions/archive/${tag}.tar.gz"
|
||||
node --input-type=module <<'NODE'
|
||||
import { writeFile } from 'node:fs/promises';
|
||||
|
||||
const response = await fetch(process.env.SHRINKSDK_ARCHIVE_URL);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Release archive download failed: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
|
||||
await writeFile('release.tar.gz', new Uint8Array(await response.arrayBuffer()));
|
||||
NODE
|
||||
mkdir release
|
||||
tar -xzf release.tar.gz --strip-components=1 -C release
|
||||
rm -f release.tar.gz
|
||||
printf '%s' "$tag" > release/.shrink-sdk-release-tag
|
||||
|
||||
- name: Validate immutable release version
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
cd release
|
||||
tag="$(cat .shrink-sdk-release-tag)"
|
||||
version="$(node -p "require('./package.json').version")"
|
||||
test "$tag" = "v$version"
|
||||
npm pack --dry-run
|
||||
|
||||
- name: Publish to ShrinkSDK registry
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
: "${NODE_AUTH_TOKEN:?SHRINKSDK_PACKAGE_TOKEN is required}"
|
||||
cd release
|
||||
npmrc="$HOME/.npmrc"
|
||||
cleanup() { rm -f "$npmrc"; }
|
||||
trap cleanup EXIT
|
||||
printf '%s\n' \
|
||||
'registry=https://git.crash.work/api/packages/ShrinkSDK/npm/' \
|
||||
'//git.crash.work/api/packages/ShrinkSDK/npm/:_authToken=${NODE_AUTH_TOKEN}' > "$npmrc"
|
||||
npm publish --registry=https://git.crash.work/api/packages/ShrinkSDK/npm/
|
||||
@@ -0,0 +1,3 @@
|
||||
**/bin/
|
||||
**/obj/
|
||||
artifacts/
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
.git/
|
||||
.gitea/
|
||||
Development~/
|
||||
Tools~/
|
||||
DotNet~/
|
||||
Godot~/
|
||||
NuGet.Config
|
||||
*.csproj
|
||||
*.sln
|
||||
*.user
|
||||
*.DotSettings.user
|
||||
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
||||
<AssemblyName>ShrinkRuntime.Abstractions</AssemblyName>
|
||||
<RootNamespace>ShrinkSDK.Runtime</RootNamespace>
|
||||
<PackageId>ShrinkSDK.Runtime.Abstractions</PackageId>
|
||||
<Version>0.1.0</Version>
|
||||
<Description>Engine-neutral ShrinkSDK runtime contracts.</Description>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Runtime\ShrinkRuntimeServices.cs" Link="Runtime\ShrinkRuntimeServices.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="ShrinkSDK" value="https://git.crash.work/api/packages/ShrinkSDK/nuget/index.json" />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
@@ -0,0 +1,7 @@
|
||||
# ShrinkSDK Runtime Abstractions
|
||||
|
||||
Unity 和普通 .NET/Godot 宿主共用的平台服务合同,包含日志、主线程派发、时钟、持久化路径、截图和应用生命周期。
|
||||
|
||||
- Unity:安装 `com.cneicy.shrink-runtime-abstractions`。
|
||||
- .NET/Godot:安装 `ShrinkSDK.Runtime.Abstractions`。
|
||||
- NuGet 打包工程位于 `DotNet~/ShrinkSDK.Runtime.Abstractions.csproj`。
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fdcff332146fc1d439fc0c82285637da
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "ShrinkRuntime.Abstractions",
|
||||
"rootNamespace": "ShrinkSDK.Runtime",
|
||||
"autoReferenced": true
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9285a23e48a9fd04ea5d3a7507010d2b
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,127 @@
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ShrinkSDK.Runtime
|
||||
{
|
||||
public enum ShrinkLogLevel { Trace, Debug, Information, Warning, Error }
|
||||
|
||||
public interface IShrinkLogger
|
||||
{
|
||||
void Log(ShrinkLogLevel level, string message, Exception? exception = null);
|
||||
}
|
||||
|
||||
public interface IShrinkMainThreadDispatcher
|
||||
{
|
||||
bool IsMainThread { get; }
|
||||
bool TryPost(Action action);
|
||||
}
|
||||
|
||||
public interface IShrinkClock
|
||||
{
|
||||
DateTimeOffset UtcNow { get; }
|
||||
double UnscaledTimeSeconds { get; }
|
||||
}
|
||||
|
||||
public interface IShrinkPathProvider
|
||||
{
|
||||
string PersistentDataPath { get; }
|
||||
string TemporaryDataPath { get; }
|
||||
}
|
||||
|
||||
public interface IShrinkScreenshotProvider
|
||||
{
|
||||
ValueTask<byte[]> CapturePngAsync(CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public interface IShrinkApplicationLifecycle
|
||||
{
|
||||
event Action? Paused;
|
||||
event Action? Resumed;
|
||||
event Action? Exiting;
|
||||
}
|
||||
|
||||
public static class ShrinkLoggerExtensions
|
||||
{
|
||||
public static void Error(this IShrinkLogger logger, string message, Exception? exception = null) =>
|
||||
logger.Log(ShrinkLogLevel.Error, message, exception);
|
||||
}
|
||||
|
||||
public static class ShrinkRuntimeServices
|
||||
{
|
||||
private static IShrinkLogger _logger = new ConsoleLogger();
|
||||
private static IShrinkMainThreadDispatcher _dispatcher = new InlineDispatcher();
|
||||
private static IShrinkClock _clock = new SystemClock();
|
||||
private static IShrinkPathProvider _paths = new SystemPaths();
|
||||
|
||||
public static IShrinkLogger Logger => _logger;
|
||||
public static IShrinkMainThreadDispatcher Dispatcher => _dispatcher;
|
||||
public static IShrinkClock Clock => _clock;
|
||||
public static IShrinkPathProvider Paths => _paths;
|
||||
public static IShrinkScreenshotProvider? Screenshots { get; private set; }
|
||||
public static IShrinkApplicationLifecycle? Lifecycle { get; private set; }
|
||||
|
||||
public static void Configure(IShrinkLogger logger, IShrinkMainThreadDispatcher dispatcher,
|
||||
IShrinkClock clock, IShrinkPathProvider paths,
|
||||
IShrinkScreenshotProvider? screenshots = null, IShrinkApplicationLifecycle? lifecycle = null)
|
||||
{
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
|
||||
_clock = clock ?? throw new ArgumentNullException(nameof(clock));
|
||||
_paths = paths ?? throw new ArgumentNullException(nameof(paths));
|
||||
Screenshots = screenshots;
|
||||
Lifecycle = lifecycle;
|
||||
}
|
||||
|
||||
private sealed class ConsoleLogger : IShrinkLogger
|
||||
{
|
||||
public void Log(ShrinkLogLevel level, string message, Exception? exception = null)
|
||||
{
|
||||
Console.WriteLine($"[{level}] {message}");
|
||||
if (exception != null) Console.WriteLine(exception);
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class InlineDispatcher : IShrinkMainThreadDispatcher
|
||||
{
|
||||
public bool IsMainThread => true;
|
||||
public bool TryPost(Action action)
|
||||
{
|
||||
if (action == null) return false;
|
||||
action();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class SystemClock : IShrinkClock
|
||||
{
|
||||
private readonly Stopwatch _stopwatch = Stopwatch.StartNew();
|
||||
public DateTimeOffset UtcNow => DateTimeOffset.UtcNow;
|
||||
public double UnscaledTimeSeconds => _stopwatch.Elapsed.TotalSeconds;
|
||||
}
|
||||
|
||||
private sealed class SystemPaths : IShrinkPathProvider
|
||||
{
|
||||
public string PersistentDataPath => Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "ShrinkSDK");
|
||||
public string TemporaryDataPath => Path.GetTempPath();
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
|
||||
public sealed class ShrinkCodeGenWovenAttribute : Attribute
|
||||
{
|
||||
public ShrinkCodeGenWovenAttribute(string weaverVersion, string inputMvid)
|
||||
{
|
||||
WeaverVersion = weaverVersion;
|
||||
InputMvid = inputMvid;
|
||||
}
|
||||
|
||||
public string WeaverVersion { get; }
|
||||
public string InputMvid { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9f9b07df5ab1dc345be31f33e94077d2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "com.cneicy.shrink-runtime-abstractions",
|
||||
"version": "0.1.0",
|
||||
"displayName": "ShrinkSDK Runtime Abstractions",
|
||||
"description": "Engine-neutral runtime services and CodeGen marker contracts.",
|
||||
"unity": "2022.3"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2f07481a8e08f454fa1d85c5afe4c92d
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user