From 0789bb9665f80df10fea1d9fc517e85ba91b7636 Mon Sep 17 00:00:00 2001 From: PrexCoder <72302739+PrexCoder@users.noreply.github.com> Date: Wed, 19 Nov 2025 17:41:08 +0200 Subject: [PATCH 1/2] fixes --- .../EdgegapServerShutdownSubsystem.cpp | 45 ++++++++++--------- .../Public/EdgegapServerShutdownSubsystem.h | 14 ++++-- StartServer.sh | 37 +++++---------- 3 files changed, 47 insertions(+), 49 deletions(-) diff --git a/Source/EdgegapIntegrationKit/Private/EdgegapServerShutdownSubsystem.cpp b/Source/EdgegapIntegrationKit/Private/EdgegapServerShutdownSubsystem.cpp index 5650727..4002d5a 100644 --- a/Source/EdgegapIntegrationKit/Private/EdgegapServerShutdownSubsystem.cpp +++ b/Source/EdgegapIntegrationKit/Private/EdgegapServerShutdownSubsystem.cpp @@ -38,11 +38,15 @@ void UEdgegapServerShutdownSubsystem::Initialize(FSubsystemCollectionBase& Colle CachedRequestID = FPlatformMisc::GetEnvironmentVariable(TEXT("ARBITRIUM_REQUEST_ID")); } - bIsEdgegapEnvironment = !CachedRequestID.IsEmpty(); + // Get production self-stop URL and token (preferred method for production) + CachedDeleteURL = FPlatformMisc::GetEnvironmentVariable(TEXT("ARBITRIUM_DELETE_URL")); + CachedDeleteToken = FPlatformMisc::GetEnvironmentVariable(TEXT("ARBITRIUM_DELETE_TOKEN")); + + bIsEdgegapEnvironment = !CachedDeleteURL.IsEmpty() && !CachedDeleteToken.IsEmpty(); if (bIsEdgegapEnvironment) { - UE_LOG(LogTemp, Log, TEXT("EdgegapServerShutdown: Detected Edgegap environment. Request ID: %s"), *CachedRequestID); + UE_LOG(LogTemp, Log, TEXT("EdgegapServerShutdown: Detected Edgegap environment with production self-stop endpoint")); // Setup shutdown hooks SetupShutdownHooks(); @@ -52,7 +56,7 @@ void UEdgegapServerShutdownSubsystem::Initialize(FSubsystemCollectionBase& Colle } else { - UE_LOG(LogTemp, Log, TEXT("EdgegapServerShutdown: Not running on Edgegap (no request ID found)")); + UE_LOG(LogTemp, Log, TEXT("EdgegapServerShutdown: Not running on Edgegap (no ARBITRIUM_DELETE_URL found)")); } } @@ -91,15 +95,25 @@ void UEdgegapServerShutdownSubsystem::CallSelfStopAPI(bool bWaitForResponse) return; } - if (!bIsEdgegapEnvironment || CachedRequestID.IsEmpty()) + if (!bIsEdgegapEnvironment) { - UE_LOG(LogTemp, Warning, TEXT("EdgegapServerShutdown: Cannot call self-stop API - not running on Edgegap or no request ID")); + UE_LOG(LogTemp, Warning, TEXT("EdgegapServerShutdown: Cannot call self-stop API - not running on Edgegap")); OnServerShutdown.Broadcast(false, TEXT("Not running on Edgegap environment")); return; } bShutdownInitiated = true; - StopDeploymentInternal(CachedRequestID); + + // Use production self-stop method (ARBITRIUM_DELETE_URL) - required for production + if (!CachedDeleteURL.IsEmpty() && !CachedDeleteToken.IsEmpty()) + { + StopDeploymentInternal(CachedDeleteURL, CachedDeleteToken); + } + else + { + UE_LOG(LogTemp, Error, TEXT("EdgegapServerShutdown: Production self-stop method not available - missing ARBITRIUM_DELETE_URL or ARBITRIUM_DELETE_TOKEN")); + OnServerShutdown.Broadcast(false, TEXT("Production self-stop method not available - missing ARBITRIUM_DELETE_URL or ARBITRIUM_DELETE_TOKEN")); + } if (bWaitForResponse) { @@ -118,8 +132,9 @@ void UEdgegapServerShutdownSubsystem::CallSelfStopAPI(bool bWaitForResponse) } } -void UEdgegapServerShutdownSubsystem::StopDeploymentInternal(const FString& RequestID) +void UEdgegapServerShutdownSubsystem::StopDeploymentInternal(const FString& DeleteURL, const FString& DeleteToken) { + // Production self-stop endpoint (preferred method) FHttpModule* Http = &FHttpModule::Get(); if (!Http) { @@ -128,26 +143,16 @@ void UEdgegapServerShutdownSubsystem::StopDeploymentInternal(const FString& Requ return; } - FString AuthorizationKey = UEGIKBlueprintFunctionLibrary::GetAuthorizationKey(); - if (AuthorizationKey.IsEmpty()) - { - UE_LOG(LogTemp, Error, TEXT("EdgegapServerShutdown: Authorization key not found")); - OnServerShutdown.Broadcast(false, TEXT("Authorization key not configured")); - return; - } - - FString URL = FString::Printf(TEXT("https://api.edgegap.com/v1/stop/%s"), *RequestID); - ShutdownRequest = Http->CreateRequest(); - ShutdownRequest->SetURL(URL); + ShutdownRequest->SetURL(DeleteURL); ShutdownRequest->SetVerb("DELETE"); ShutdownRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json")); - ShutdownRequest->SetHeader(TEXT("Authorization"), *AuthorizationKey); + ShutdownRequest->SetHeader(TEXT("Authorization"), *DeleteToken); ShutdownRequest->SetTimeout(5); // 5 second timeout ShutdownRequest->OnProcessRequestComplete().BindUObject(this, &UEdgegapServerShutdownSubsystem::OnShutdownResponseReceived); - UE_LOG(LogTemp, Log, TEXT("EdgegapServerShutdown: Calling self-stop API for request ID: %s"), *RequestID); + UE_LOG(LogTemp, Log, TEXT("EdgegapServerShutdown: Calling production self-stop API")); if (!ShutdownRequest->ProcessRequest()) { diff --git a/Source/EdgegapIntegrationKit/Public/EdgegapServerShutdownSubsystem.h b/Source/EdgegapIntegrationKit/Public/EdgegapServerShutdownSubsystem.h index f701d92..b224a5b 100644 --- a/Source/EdgegapIntegrationKit/Public/EdgegapServerShutdownSubsystem.h +++ b/Source/EdgegapIntegrationKit/Public/EdgegapServerShutdownSubsystem.h @@ -32,7 +32,7 @@ class EDGEGAPINTEGRATIONKIT_API UEdgegapServerShutdownSubsystem : public UGameIn /** * Check if the server is running in Edgegap environment - * @return True if EDGEGAP_REQUEST_ID environment variable is set + * @return True if ARBITRIUM_DELETE_URL and ARBITRIUM_DELETE_TOKEN environment variables are set */ UFUNCTION(BlueprintPure, Category = "Edgegap Integration Kit | Server") bool IsRunningOnEdgegap() const; @@ -53,7 +53,13 @@ class EDGEGAPINTEGRATIONKIT_API UEdgegapServerShutdownSubsystem : public UGameIn /** The deployment request ID from environment */ FString CachedRequestID; - /** Whether we're running on Edgegap (have request ID) */ + /** Production self-stop URL from ARBITRIUM_DELETE_URL environment variable */ + FString CachedDeleteURL; + + /** Production self-stop token from ARBITRIUM_DELETE_TOKEN environment variable */ + FString CachedDeleteToken; + + /** Whether we're running on Edgegap (have request ID or delete URL) */ bool bIsEdgegapEnvironment; /** Flag to prevent multiple shutdown calls */ @@ -65,8 +71,8 @@ class EDGEGAPINTEGRATIONKIT_API UEdgegapServerShutdownSubsystem : public UGameIn /** Callback for shutdown API response */ void OnShutdownResponseReceived(TSharedPtr HttpRequest, TSharedPtr HttpResponse, bool bArg); - /** Internal method to stop deployment */ - void StopDeploymentInternal(const FString& RequestID); + /** Internal method to stop deployment using production self-stop endpoint */ + void StopDeploymentInternal(const FString& DeleteURL, const FString& DeleteToken); /** Setup crash handlers */ void SetupCrashHandlers(); diff --git a/StartServer.sh b/StartServer.sh index 376b4f5..b3bb796 100644 --- a/StartServer.sh +++ b/StartServer.sh @@ -8,46 +8,33 @@ env # Function to call Edgegap self-stop API call_stop_api() { local EXIT_CODE=$1 - # Try multiple possible environment variable names for request ID - local REQUEST_ID="${EG_REQUEST_ID:-${EDGEGAP_REQUEST_ID:-${EDGE_REQUEST_ID:-${ARBITRIUM_REQUEST_ID}}}}" - # API key may not be available as env var (typically stored in config) - # Try environment first, then common config locations - local API_KEY="${EG_API_KEY:-${EDGEGAP_API_KEY:-${EDGE_API_KEY}}}" + # Use production self-stop endpoint (ARBITRIUM_DELETE_URL) - required for production + local DELETE_URL="${ARBITRIUM_DELETE_URL}" + local DELETE_TOKEN="${ARBITRIUM_DELETE_TOKEN}" - # If API key not in env, try reading from config file (if available) - if [ -z "$API_KEY" ] && [ -f "${UE_PROJECT_DIR}/Saved/Config/LinuxServer/DefaultEngine.ini" ]; then - API_KEY=$(grep -m 1 "^AuthorizationKey=" "${UE_PROJECT_DIR}/Saved/Config/LinuxServer/DefaultEngine.ini" 2>/dev/null | cut -d'=' -f2 | tr -d ' ') - fi - - if [ -z "$REQUEST_ID" ]; then - echo "No Edgegap request ID found in environment variables (checked: EG_REQUEST_ID, EDGEGAP_REQUEST_ID, EDGE_REQUEST_ID, ARBITRIUM_REQUEST_ID)" - echo "Note: The C++ subsystem may still call the self-stop API if it has access to the request ID" - exit $EXIT_CODE - fi - - if [ -z "$API_KEY" ]; then - echo "No Edgegap API key found (checked env vars and config file)" - echo "Note: The C++ subsystem may still call the self-stop API if it has access to the API key from config" + if [ -z "$DELETE_URL" ] || [ -z "$DELETE_TOKEN" ]; then + echo "Error: Production self-stop method not available - missing ARBITRIUM_DELETE_URL or ARBITRIUM_DELETE_TOKEN" + echo "Note: The C++ subsystem may still call the self-stop API if it has access to the environment variables" exit $EXIT_CODE fi - echo "Calling Edgegap self-stop API for request ID: $REQUEST_ID" + # Production method - use deployment-specific URL and token + echo "Calling Edgegap production self-stop API" - # Call the self-stop API RESPONSE=$(curl -s -w "\n%{http_code}" -X DELETE \ -H "Content-Type: application/json" \ - -H "Authorization: $API_KEY" \ - "https://api.edgegap.com/v1/stop/$REQUEST_ID" \ + -H "Authorization: $DELETE_TOKEN" \ + "$DELETE_URL" \ --max-time 5) HTTP_CODE=$(echo "$RESPONSE" | tail -n1) BODY=$(echo "$RESPONSE" | sed '$d') if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then - echo "Successfully called self-stop API (HTTP $HTTP_CODE)" + echo "Successfully called production self-stop API (HTTP $HTTP_CODE)" else - echo "Self-stop API call returned HTTP $HTTP_CODE: $BODY" + echo "Production self-stop API call returned HTTP $HTTP_CODE: $BODY" fi exit $EXIT_CODE From af7afb789184ae107a16d0ad019c0cd761ca2edd Mon Sep 17 00:00:00 2001 From: PrexCoder <72302739+PrexCoder@users.noreply.github.com> Date: Thu, 20 Nov 2025 07:16:31 +0200 Subject: [PATCH 2/2] Fix for 5.7 --- .../Private/APIToken/APITokenSettings.h | 2 +- Source/Edgegap/Private/EdgegapSettings.h | 2 +- .../Private/EdgegapSettingsDetails.cpp | 51 ++++++++++++------- 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/Source/Edgegap/Private/APIToken/APITokenSettings.h b/Source/Edgegap/Private/APIToken/APITokenSettings.h index faaff9a..608a531 100644 --- a/Source/Edgegap/Private/APIToken/APITokenSettings.h +++ b/Source/Edgegap/Private/APIToken/APITokenSettings.h @@ -15,6 +15,6 @@ struct FAPITokenSettings FString APIToken; }; -#if UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_2 +#if defined(UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_2) && UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_2 #include "CoreMinimal.h" #endif diff --git a/Source/Edgegap/Private/EdgegapSettings.h b/Source/Edgegap/Private/EdgegapSettings.h index e5a79f1..2c0ce23 100644 --- a/Source/Edgegap/Private/EdgegapSettings.h +++ b/Source/Edgegap/Private/EdgegapSettings.h @@ -153,6 +153,6 @@ class UEdgegapSettings : public UDeveloperSettings bool bIsTokenVerified = true; }; -#if UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_2 +#if defined(UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_2) && UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_2 #include "CoreMinimal.h" #endif diff --git a/Source/Edgegap/Private/EdgegapSettingsDetails.cpp b/Source/Edgegap/Private/EdgegapSettingsDetails.cpp index 1863300..94836dc 100644 --- a/Source/Edgegap/Private/EdgegapSettingsDetails.cpp +++ b/Source/Edgegap/Private/EdgegapSettingsDetails.cpp @@ -1037,6 +1037,9 @@ void FEdgegapSettingsDetails::PackageProject(const FName IniPlatformName) // this may delete UProjectPackagingSettings , don't hold it across this call FEdgegapSettingsDetails::SaveAll(); + // Re-get PackagingSettings after SaveAll() as it may have been invalidated + UProjectPackagingSettings* PackagingSettingsAfterSave = GetMutableDefault(); + // basic BuildCookRun params we always want FString BuildCookRunParams = FString::Printf(TEXT("-nop4 -utf8output %s -cook "), GetUATCompilationFlags()); @@ -1047,8 +1050,17 @@ void FEdgegapSettingsDetails::PackageProject(const FName IniPlatformName) BuildCookRunParams += FString::Printf(TEXT(" -project=\"%s\""), *ProjectPath); } + // Get build target info - in UE 5.7, use PackagingSettings instead of PlatformsSettings + const FTargetInfo* BuildTargetInfo = PackagingSettingsAfterSave->GetBuildTargetInfo(); bool bIsProjectBuildTarget = false; - const FTargetInfo* BuildTargetInfo = PlatformsSettings->GetBuildTargetInfoForPlatform(IniPlatformName, bIsProjectBuildTarget); + + // Check if this is a project build target (not engine target) + if (BuildTargetInfo) + { + FString ProjectDir = FPaths::GetPath(FPaths::GetProjectFilePath()); + FString TargetPath = BuildTargetInfo->Path; + bIsProjectBuildTarget = FPaths::IsUnderDirectory(TargetPath, ProjectDir); + } // Only add the -Target=... argument for code projects. Content projects will return UnrealGame/UnrealClient/UnrealServer here, but // may need a temporary target generated to enable/disable plugins. Specifying -Target in these cases will cause packaging to fail, @@ -1078,7 +1090,7 @@ void FEdgegapSettingsDetails::PackageProject(const FName IniPlatformName) } // optional settings - if (PackagingSettings->bSkipEditorContent) + if (PackagingSettingsAfterSave->bSkipEditorContent) { BuildCookRunParams += TEXT(" -SkipCookingEditorContent"); } @@ -1126,72 +1138,73 @@ void FEdgegapSettingsDetails::PackageProject(const FName IniPlatformName) BuildCookRunParams += TEXT(" -stage -archive -package"); const ITargetPlatform* TargetPlatform = GetTargetPlatformManager()->FindTargetPlatform(PlatformInfo->Name); - if (ShouldBuildProject(PackagingSettings, TargetPlatform)) + if (ShouldBuildProject(PackagingSettingsAfterSave, TargetPlatform)) { BuildCookRunParams += TEXT(" -build"); } - if (PackagingSettings->FullRebuild) + if (PackagingSettingsAfterSave->FullRebuild) { BuildCookRunParams += TEXT(" -clean"); } - if (PackagingSettings->bCompressed) + if (PackagingSettingsAfterSave->bCompressed) { BuildCookRunParams += TEXT(" -compressed"); } - if (PackagingSettings->bUseIoStore) + if (PackagingSettingsAfterSave->bUseIoStore) { BuildCookRunParams += TEXT(" -iostore"); // Pak file(s) must be used when using container file(s) - PackagingSettings->UsePakFile = true; + PackagingSettingsAfterSave->UsePakFile = true; } - if (PackagingSettings->UsePakFile) + if (PackagingSettingsAfterSave->UsePakFile) { BuildCookRunParams += TEXT(" -pak"); } - if (PackagingSettings->IncludePrerequisites) + if (PackagingSettingsAfterSave->IncludePrerequisites) { BuildCookRunParams += TEXT(" -prereqs"); } - if (!PackagingSettings->ApplocalPrerequisitesDirectory.Path.IsEmpty()) + if (!PackagingSettingsAfterSave->ApplocalPrerequisitesDirectory.Path.IsEmpty()) { - BuildCookRunParams += FString::Printf(TEXT(" -applocaldirectory=\"%s\""), *(PackagingSettings->ApplocalPrerequisitesDirectory.Path)); + BuildCookRunParams += FString::Printf(TEXT(" -applocaldirectory=\"%s\""), *(PackagingSettingsAfterSave->ApplocalPrerequisitesDirectory.Path)); } - else if (PackagingSettings->IncludeAppLocalPrerequisites) + else if (PackagingSettingsAfterSave->IncludeAppLocalPrerequisites) { BuildCookRunParams += TEXT(" -applocaldirectory=\"$(EngineDir)/Binaries/ThirdParty/AppLocalDependencies\""); } BuildCookRunParams += FString::Printf(TEXT(" -archivedirectory=\"%s\""), *PlatformsSettings->StagingDirectory.Path); - if (PackagingSettings->ForDistribution) + if (PackagingSettingsAfterSave->ForDistribution) { BuildCookRunParams += TEXT(" -distribution"); } - if (PackagingSettings->bGenerateChunks) + if (PackagingSettingsAfterSave->bGenerateChunks) { BuildCookRunParams += TEXT(" -manifests"); } // Whether to include the crash reporter. - if (PackagingSettings->IncludeCrashReporter && PlatformInfo->DataDrivenPlatformInfo->bCanUseCrashReporter) + if (PackagingSettingsAfterSave->IncludeCrashReporter && PlatformInfo->DataDrivenPlatformInfo->bCanUseCrashReporter) { BuildCookRunParams += TEXT(" -CrashReporter"); } - if (PackagingSettings->bBuildHttpChunkInstallData) + if (PackagingSettingsAfterSave->bBuildHttpChunkInstallData) { - BuildCookRunParams += FString::Printf(TEXT(" -manifests -createchunkinstall -chunkinstalldirectory=\"%s\" -chunkinstallversion=%s"), *(PackagingSettings->HttpChunkInstallDataDirectory.Path), *(PackagingSettings->HttpChunkInstallDataVersion)); + BuildCookRunParams += FString::Printf(TEXT(" -manifests -createchunkinstall -chunkinstalldirectory=\"%s\" -chunkinstallversion=%s"), *(PackagingSettingsAfterSave->HttpChunkInstallDataDirectory.Path), *(PackagingSettingsAfterSave->HttpChunkInstallDataVersion)); } - EProjectPackagingBuildConfigurations BuildConfig = PlatformsSettings->GetBuildConfigurationForPlatform(IniPlatformName); + // Get build configuration - in UE 5.7, use PackagingSettings instead of PlatformsSettings + EProjectPackagingBuildConfigurations BuildConfig = PackagingSettingsAfterSave->BuildConfiguration; UEdgegapSettings* EdgegapSettings = GetMutableDefault(); if(EdgegapSettings) { @@ -1205,7 +1218,7 @@ void FEdgegapSettingsDetails::PackageProject(const FName IniPlatformName) BuildCookRunParams += FString::Printf(TEXT(" -server -noclient -serverconfig=%s"), LexToString(ConfigurationInfo.Configuration)); - if (ConfigurationInfo.Configuration == EBuildConfiguration::Shipping && !PackagingSettings->IncludeDebugFiles) + if (ConfigurationInfo.Configuration == EBuildConfiguration::Shipping && !PackagingSettingsAfterSave->IncludeDebugFiles) { BuildCookRunParams += TEXT(" -nodebuginfo"); }