Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 5 additions & 81 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,56 +42,9 @@ jobs:
test_matrix=`just print_test_matrix_json`
echo "test_matrix=$test_matrix" >> $GITHUB_OUTPUT

fetch-openapi:
name: Fetch OpenAPI spec
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v6
- name: Determine OpenAPI versions and download specs
run: |
set -e -o pipefail

CURL_OPTS=(--retry 3 \
--retry-all-errors \
--fail \
--verbose \
--no-progress-meter \
--show-error)

LATEST_OPENAPI_VERSION=$(curl https://api.github.com/repos/stripe/openapi/releases/latest -s | jq .name -r)
CURRENT_OPENAPI_VERSION=$(cat OPENAPI_VERSION)
if [[ "$PR_BODY" == *"TEST USING LATEST OPENAPI"* ]]; then
OPENAPI_VERSION=$LATEST_OPENAPI_VERSION
else
OPENAPI_VERSION=$CURRENT_OPENAPI_VERSION
fi

SPEC_NAME="spec3.sdk.yaml"
FIXTURES_NAME="fixtures3.json"
if [[ "$GITHUB_BASE" == *"b"* ]]; then
SPEC_NAME="spec3.beta.sdk.yaml"
FIXTURES_NAME="fixtures3.beta.json"
fi
curl "${CURL_OPTS[@]}" https://raw.githubusercontent.com/stripe/openapi/$OPENAPI_VERSION/openapi/${SPEC_NAME%.yaml}.json -o latest.json
curl "${CURL_OPTS[@]}" https://raw.githubusercontent.com/stripe/openapi/$OPENAPI_VERSION/openapi/$FIXTURES_NAME -o fixtures.json

env:
PR_BODY: ${{ github.event.pull_request.body }}
GITHUB_BASE: ${{ github.base_ref || github.ref_name }}

- name: Upload OpenAPI spec
uses: actions/upload-artifact@v4
with:
name: openapi-spec
path: |
latest.json
fixtures.json

test:
name: Test (${{ matrix.framework }})
needs: [prepare-dotnet-versions, fetch-openapi]
name: Test (${{ matrix.framework }}, ubuntu)
needs: [prepare-dotnet-versions]
runs-on: ubuntu-latest
permissions:
contents: read
Expand Down Expand Up @@ -126,23 +79,14 @@ jobs:
echo "Building ${{ matrix.framework }} using dotnet v$(dotnet --version)"
dotnet build src/StripeTests/StripeTests.csproj -c Release -f ${{ matrix.framework }} /p:ContinuousIntegrationBuild=true

- name: Download OpenAPI spec
uses: actions/download-artifact@v4
with:
name: openapi-spec

- uses: stripe/openapi/actions/stripe-mock@master
with:
base: ${{ github.base_ref || github.ref_name }}
fixtures: "/workspace/fixtures.json"
spec_path: "/workspace/latest.json"

- name: Run tests
run: dotnet test --no-build -f ${{ matrix.framework }} src/StripeTests/StripeTests.csproj -c Release

test-net462:
name: Test (net462)
needs: [prepare-dotnet-versions, fetch-openapi]
name: Test (net462, windows)
needs: [prepare-dotnet-versions]
runs-on: windows-latest
permissions:
contents: read
Expand All @@ -163,27 +107,7 @@ jobs:
echo "Building net462 using dotnet v$(dotnet --version)"
dotnet build src/StripeTests/StripeTests.csproj -c Release -f net462 /p:ContinuousIntegrationBuild=true

- name: Download OpenAPI spec
uses: actions/download-artifact@v4
with:
name: openapi-spec

- name: Start stripe-mock
shell: bash
run: |
MOCK_VERSION=$(curl -s https://api.github.com/repos/stripe/stripe-mock/releases/latest | jq -r '.tag_name' | sed 's/^v//')
curl -L "https://github.com/stripe/stripe-mock/releases/download/v${MOCK_VERSION}/stripe-mock_${MOCK_VERSION}_windows_amd64.zip" -o stripe-mock.zip
unzip stripe-mock.zip -d stripe-mock

BETA_ARG=""
if [[ "${{ github.base_ref || github.ref_name }}" == *"b"* ]]; then
BETA_ARG="-beta"
fi

./stripe-mock/stripe-mock.exe $BETA_ARG \
-fixtures "${{ github.workspace }}/fixtures.json" \
-spec "${{ github.workspace }}/latest.json" &
sleep 5
- uses: stripe/openapi/actions/stripe-mock@master

- name: Run tests
run: dotnet test --no-build --configuration Release --framework net462 src/StripeTests/StripeTests.csproj
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

[![NuGet](https://img.shields.io/nuget/v/stripe.net.svg)](https://www.nuget.org/packages/Stripe.net/)
[![Build Status](https://github.com/stripe/stripe-dotnet/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/stripe/stripe-dotnet/actions?query=branch%3Amaster)
[![Coverage Status](https://coveralls.io/repos/github/stripe/stripe-dotnet/badge.svg?branch=master)](https://coveralls.io/github/stripe/stripe-dotnet?branch=master)

> [!TIP]
> Want to chat live with Stripe engineers? Join us on our [Discord server](https://stripe.com/go/discord/dotnet).
Expand Down
42 changes: 6 additions & 36 deletions src/Stripe.net/Infrastructure/Public/SystemNetHttpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ namespace Stripe
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
Expand Down Expand Up @@ -135,9 +133,6 @@ public SystemNetHttpClient(
/// </summary>
public static TimeSpan MinNetworkRetriesDelay => TimeSpan.FromMilliseconds(500);

/// <summary>Gets or sets the cached source hash.</summary>
internal static string SourceHash { get; set; } = ComputeSourceHash();

/// <summary>
/// Gets whether telemetry was enabled for this client.
/// </summary>
Expand Down Expand Up @@ -227,35 +222,6 @@ internal static string DetectAIAgent(Func<string, string> getEnv)
return string.Empty;
}

internal static string ComputeSourceHash()
{
try
{
var parts = new System.Collections.Generic.List<string>
{
System.Runtime.InteropServices.RuntimeInformation.OSDescription,
};
try
{
parts.Add(Environment.MachineName);
}
catch
{
}

var inputBytes = Encoding.UTF8.GetBytes(string.Join(" ", parts));
using (var md5 = MD5.Create())
{
var hashBytes = md5.ComputeHash(inputBytes);
return BitConverter.ToString(hashBytes).Replace("-", string.Empty).ToLowerInvariant();
}
}
catch
{
return string.Empty;
}
}

private async Task<(HttpResponseMessage responseMessage, int retries)> SendHttpRequest(
StripeRequest request,
CancellationToken cancellationToken)
Expand Down Expand Up @@ -331,9 +297,13 @@ private string BuildStripeClientUserAgentString()
{ "lang", ".net" },
{ "stripe_net_target_framework", StripeNetTargetFramework },
};
if (!string.IsNullOrEmpty(SourceHash))
if (this.EnableTelemetry)
{
values["source"] = SourceHash;
var telemetryId = TelemetryId.Get();
if (!string.IsNullOrEmpty(telemetryId))
{
values["telemetry_id"] = telemetryId;
}
}

// The following values are in try/catch blocks on the off chance that the
Expand Down
132 changes: 132 additions & 0 deletions src/Stripe.net/Infrastructure/TelemetryId.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
namespace Stripe.Infrastructure
{
using System;
using System.IO;
using System.Security.Cryptography;

internal static class TelemetryId
{
private static readonly object LockObj = new object();

private static string cachedId;
private static bool loaded;

// For testing: overrides GetConfigDir() when set.
internal static string ConfigDirOverride { get; set; }

public static string Get()
{
if (loaded)
{
return cachedId;
}

lock (LockObj)
{
if (loaded)
{
return cachedId;
}

cachedId = Resolve();
loaded = true;
}

return cachedId;
}

internal static string GetConfigDir()
Comment thread
xavdid marked this conversation as resolved.
{
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
var appData = Environment.GetFolderPath(
Environment.SpecialFolder.ApplicationData);
if (string.IsNullOrEmpty(appData))
{
return null;
}

return Path.Combine(appData, "Stripe");
}

var xdg = Environment.GetEnvironmentVariable("XDG_CONFIG_HOME");
if (!string.IsNullOrEmpty(xdg))
{
return Path.Combine(xdg, "stripe");
}

var home = Environment.GetFolderPath(
Environment.SpecialFolder.UserProfile);
if (string.IsNullOrEmpty(home))
{
return null;
}

return Path.Combine(home, ".config", "stripe");
}

private static string Resolve()
{
var configDir = ConfigDirOverride ?? GetConfigDir();
if (configDir == null)
{
return null;
}

var filePath = Path.Combine(configDir, "telemetry_id");

try
{
if (File.Exists(filePath))
{
var content = File.ReadAllText(filePath).Trim();
if (!string.IsNullOrEmpty(content))
{
return content;
}
}
}
catch
{
return null;
}

var newId = GenerateId();
try
{
Directory.CreateDirectory(configDir);
File.WriteAllText(filePath, newId);
}
catch
{
return null;
}

return newId;
}

private static string GenerateId()
{
var bytes = new byte[16];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(bytes);
}

return BitConverter.ToString(bytes)
.Replace("-", string.Empty)
.ToLowerInvariant();
}

// For testing
internal static void Reset()
{
lock (LockObj)
{
cachedId = null;
loaded = false;
ConfigDirOverride = null;
}
}
}
}
Loading
Loading