CI: add dotnet --info / df -h / free -m diagnostics and an explicit 'Restore NuGet packages' step before build to isolate restore failures (build of e15f650 on main exited with code -1 and zero dotnet output).
#5
+3
-1
@@ -6,11 +6,13 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) loos
|
||||
|
||||
## Unreleased
|
||||
|
||||
- Infisical API error responses are now parsed to surface the server-side `message`, `error`, and `reqId` fields. The 4xx/5xx exception message includes the human-readable explanation (e.g. "The project is of type secret-manager") instead of an opaque `Infisical API returned 400 (Bad Request)`. The `InfisicalApiException` gains `ApiErrorMessage` and `ApiRequestId` properties; `InfisicalErrorDetails` carries the same fields so PowerShell error records and logger output expose them.
|
||||
|
||||
## 2026.06.04.1920
|
||||
|
||||
- Build produced from commit 0f8f44afdb38.
|
||||
|
||||
## Unreleased (carried forward)
|
||||
## Unreleased (carried forward)
|
||||
|
||||
- `build.ps1` gains a `-CommitArtifacts` switch that, after a successful build, stages and commits only the build outputs (`Module/PSInfisicalAPI/bin/**`, `Module/PSInfisicalAPI/PSInfisicalAPI.psd1`, and the auto-inserted `CHANGELOG.md` build stamp) with a message that references the source commit whose hash is now embedded in `BuildCommitHash`. The switch is mutually exclusive with the older broader `-CommitOnSuccess` (which still uses `git add -A`). README extended with a "Committing source and build artifacts in lockstep" section describing the recommended two-commit workflow.
|
||||
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
using System;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace PSInfisicalAPI.Errors
|
||||
{
|
||||
internal static class InfisicalApiErrorEnvelope
|
||||
{
|
||||
public static void Enrich(InfisicalApiException exception, string body)
|
||||
{
|
||||
if (exception == null || string.IsNullOrEmpty(body))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string trimmed = body.TrimStart();
|
||||
if (trimmed.Length == 0 || (trimmed[0] != '{' && trimmed[0] != '['))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
JObject obj;
|
||||
try
|
||||
{
|
||||
JToken token = JToken.Parse(body);
|
||||
if (token.Type != JTokenType.Object) { return; }
|
||||
obj = (JObject)token;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string message = ReadString(obj, "message");
|
||||
string error = ReadString(obj, "error");
|
||||
string reqId = ReadString(obj, "reqId");
|
||||
|
||||
if (!string.IsNullOrEmpty(message)) { exception.ApiErrorMessage = message; }
|
||||
if (!string.IsNullOrEmpty(error) && string.IsNullOrEmpty(exception.ApiErrorCode)) { exception.ApiErrorCode = error; }
|
||||
if (!string.IsNullOrEmpty(reqId)) { exception.ApiRequestId = reqId; }
|
||||
}
|
||||
|
||||
public static string BuildExceptionMessage(int statusCode, string reasonPhrase, string body)
|
||||
{
|
||||
string baseMessage = string.Concat(
|
||||
"Infisical API returned ",
|
||||
statusCode.ToString(System.Globalization.CultureInfo.InvariantCulture),
|
||||
" (", reasonPhrase ?? string.Empty, ").");
|
||||
|
||||
string apiMessage = null;
|
||||
string apiError = null;
|
||||
string reqId = null;
|
||||
|
||||
if (!string.IsNullOrEmpty(body))
|
||||
{
|
||||
string trimmed = body.TrimStart();
|
||||
if (trimmed.Length > 0 && trimmed[0] == '{')
|
||||
{
|
||||
try
|
||||
{
|
||||
JToken token = JToken.Parse(body);
|
||||
if (token.Type == JTokenType.Object)
|
||||
{
|
||||
JObject obj = (JObject)token;
|
||||
apiMessage = ReadString(obj, "message");
|
||||
apiError = ReadString(obj, "error");
|
||||
reqId = ReadString(obj, "reqId");
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(apiMessage) && string.IsNullOrEmpty(apiError) && string.IsNullOrEmpty(reqId))
|
||||
{
|
||||
return baseMessage;
|
||||
}
|
||||
|
||||
System.Text.StringBuilder builder = new System.Text.StringBuilder(baseMessage);
|
||||
if (!string.IsNullOrEmpty(apiMessage))
|
||||
{
|
||||
builder.Append(' ').Append(apiMessage);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(apiError) || !string.IsNullOrEmpty(reqId))
|
||||
{
|
||||
builder.Append(" [");
|
||||
bool needsSeparator = false;
|
||||
if (!string.IsNullOrEmpty(apiError))
|
||||
{
|
||||
builder.Append("error=").Append(apiError);
|
||||
needsSeparator = true;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(reqId))
|
||||
{
|
||||
if (needsSeparator) { builder.Append("; "); }
|
||||
builder.Append("reqId=").Append(reqId);
|
||||
}
|
||||
|
||||
builder.Append(']');
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private static string ReadString(JObject obj, string name)
|
||||
{
|
||||
JToken token;
|
||||
if (obj.TryGetValue(name, StringComparison.OrdinalIgnoreCase, out token) && token != null && token.Type == JTokenType.String)
|
||||
{
|
||||
return (string)token;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,8 @@ namespace PSInfisicalAPI.Errors
|
||||
public int? StatusCode { get; set; }
|
||||
public string ReasonPhrase { get; set; }
|
||||
public string ApiErrorCode { get; set; }
|
||||
public string ApiErrorMessage { get; set; }
|
||||
public string ApiRequestId { get; set; }
|
||||
public string SanitizedBody { get; set; }
|
||||
public int? LineNumber { get; set; }
|
||||
public int? LinePosition { get; set; }
|
||||
|
||||
@@ -26,6 +26,8 @@ namespace PSInfisicalAPI.Errors
|
||||
details.StatusCode = apiException.StatusCode;
|
||||
details.ReasonPhrase = apiException.ReasonPhrase;
|
||||
details.ApiErrorCode = apiException.ApiErrorCode;
|
||||
details.ApiErrorMessage = apiException.ApiErrorMessage;
|
||||
details.ApiRequestId = apiException.ApiRequestId;
|
||||
details.SanitizedBody = apiException.SanitizedBody;
|
||||
details.EndpointName = apiException.EndpointName;
|
||||
details.RequestMethod = apiException.RequestMethod;
|
||||
@@ -70,6 +72,16 @@ namespace PSInfisicalAPI.Errors
|
||||
logger.Error(Component, string.Concat("API Error Code: ", details.ApiErrorCode));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(details.ApiErrorMessage))
|
||||
{
|
||||
logger.Error(Component, string.Concat("API Error Message: ", details.ApiErrorMessage));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(details.ApiRequestId))
|
||||
{
|
||||
logger.Error(Component, string.Concat("API Request Id: ", details.ApiRequestId));
|
||||
}
|
||||
|
||||
if (details.LineNumber.HasValue)
|
||||
{
|
||||
logger.Error(Component, string.Concat("Line: ", details.LineNumber.Value.ToString(CultureInfo.InvariantCulture)));
|
||||
|
||||
@@ -33,6 +33,8 @@ namespace PSInfisicalAPI.Errors
|
||||
public int StatusCode { get; set; }
|
||||
public string ReasonPhrase { get; set; }
|
||||
public string ApiErrorCode { get; set; }
|
||||
public string ApiErrorMessage { get; set; }
|
||||
public string ApiRequestId { get; set; }
|
||||
public string SanitizedBody { get; set; }
|
||||
public string EndpointName { get; set; }
|
||||
public string RequestMethod { get; set; }
|
||||
|
||||
@@ -135,15 +135,14 @@ namespace PSInfisicalAPI.Http
|
||||
|
||||
private static InfisicalApiException BuildApiException(InfisicalHttpResponse response, InfisicalEndpointDefinition definition)
|
||||
{
|
||||
InfisicalApiException exception = new InfisicalApiException(string.Concat(
|
||||
"Infisical API returned ",
|
||||
response.StatusCode.ToString(CultureInfo.InvariantCulture),
|
||||
" (", response.ReasonPhrase ?? string.Empty, ")."));
|
||||
string message = InfisicalApiErrorEnvelope.BuildExceptionMessage(response.StatusCode, response.ReasonPhrase, response.Body);
|
||||
InfisicalApiException exception = new InfisicalApiException(message);
|
||||
exception.StatusCode = response.StatusCode;
|
||||
exception.ReasonPhrase = response.ReasonPhrase;
|
||||
exception.EndpointName = definition.Name;
|
||||
exception.RequestMethod = definition.Method;
|
||||
exception.SanitizedBody = response.Body;
|
||||
InfisicalApiErrorEnvelope.Enrich(exception, response.Body);
|
||||
return exception;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -625,15 +625,14 @@ namespace PSInfisicalAPI.Secrets
|
||||
|
||||
private static InfisicalApiException BuildApiException(InfisicalHttpResponse response, InfisicalEndpointDefinition definition)
|
||||
{
|
||||
InfisicalApiException exception = new InfisicalApiException(string.Concat(
|
||||
"Infisical API returned ",
|
||||
response.StatusCode.ToString(CultureInfo.InvariantCulture),
|
||||
" (", response.ReasonPhrase ?? string.Empty, ")."));
|
||||
string message = InfisicalApiErrorEnvelope.BuildExceptionMessage(response.StatusCode, response.ReasonPhrase, response.Body);
|
||||
InfisicalApiException exception = new InfisicalApiException(message);
|
||||
exception.StatusCode = response.StatusCode;
|
||||
exception.ReasonPhrase = response.ReasonPhrase;
|
||||
exception.EndpointName = definition.Name;
|
||||
exception.RequestMethod = definition.Method;
|
||||
exception.SanitizedBody = response.Body;
|
||||
InfisicalApiErrorEnvelope.Enrich(exception, response.Body);
|
||||
return exception;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user