Skip to content

Commit

Permalink
[feat]: SDKs for ActionsArtifacts APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
thomhurst authored Sep 25, 2023
1 parent 03e7644 commit 958bc5f
Show file tree
Hide file tree
Showing 20 changed files with 621 additions and 30 deletions.
44 changes: 43 additions & 1 deletion Octokit.Reactive/Clients/IObservableActionsArtifactsClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
namespace Octokit.Reactive
using System;
using System.IO;
using System.Reactive;

namespace Octokit.Reactive
{
/// <summary>
/// A client for GitHub's Actions Artifacts API.
Expand All @@ -8,5 +12,43 @@
/// </remarks>
public interface IObservableActionsArtifactsClient
{
IObservable<ListArtifactsResponse> ListArtifacts(string owner, string repository, ListArtifactsRequest listArtifactsRequest = null);

/// <summary>
/// Gets the specified artifact
/// </summary>
/// <param name="owner"></param>
/// <param name="repository"></param>
/// <param name="artifactId"></param>
/// <returns></returns>
IObservable<Artifact> GetArtifact(string owner, string repository, long artifactId);

/// <summary>
/// Deletes the specified artifact
/// </summary>
/// <param name="owner"></param>
/// <param name="repository"></param>
/// <param name="artifactId"></param>
/// <returns></returns>
IObservable<Unit> DeleteArtifact(string owner, string repository, long artifactId);

/// <summary>
/// Downloads the specified artifact's contents
/// </summary>
/// <param name="owner"></param>
/// <param name="repository"></param>
/// <param name="artifactId"></param>
/// <param name="archiveFormat"></param>
/// <returns></returns>
IObservable<Stream> DownloadArtifact(string owner, string repository, long artifactId, string archiveFormat);

/// <summary>
/// Lists the artifacts for a specific workflow run
/// </summary>
/// <param name="owner"></param>
/// <param name="repository"></param>
/// <param name="runId"></param>
/// <returns></returns>
IObservable<ListArtifactsResponse> ListWorkflowArtifacts(string owner, string repository, long runId, ListArtifactsRequest listArtifactsRequest = null);
}
}
37 changes: 36 additions & 1 deletion Octokit.Reactive/Clients/ObservableActionsArtifactsClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
namespace Octokit.Reactive
using System;
using System.IO;
using System.Reactive;
using System.Reactive.Threading.Tasks;

namespace Octokit.Reactive
{
public class ObservableActionsArtifactsClient : IObservableActionsArtifactsClient
{
Expand All @@ -14,5 +19,35 @@ public ObservableActionsArtifactsClient(IGitHubClient client)

_client = client.Actions.Artifacts;
}

/// <inheritdoc/>
public IObservable<ListArtifactsResponse> ListArtifacts(string owner, string repository, ListArtifactsRequest listArtifactsRequest = null)
{
return _client.ListArtifacts(owner, repository, listArtifactsRequest).ToObservable();
}

/// <inheritdoc/>
public IObservable<Artifact> GetArtifact(string owner, string repository, long artifactId)
{
return _client.GetArtifact(owner, repository, artifactId).ToObservable();
}

/// <inheritdoc/>
public IObservable<Unit> DeleteArtifact(string owner, string repository, long artifactId)
{
return _client.DeleteArtifact(owner, repository, artifactId).ToObservable();
}

/// <inheritdoc/>
public IObservable<Stream> DownloadArtifact(string owner, string repository, long artifactId, string archiveFormat)
{
return _client.DownloadArtifact(owner, repository, artifactId, archiveFormat).ToObservable();
}

/// <inheritdoc/>
public IObservable<ListArtifactsResponse> ListWorkflowArtifacts(string owner, string repository, long runId, ListArtifactsRequest listArtifactsRequest = null)
{
return _client.ListWorkflowArtifacts(owner, repository, runId, listArtifactsRequest).ToObservable();
}
}
}
8 changes: 5 additions & 3 deletions Octokit.Tests/Http/HttpClientAdapterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,9 @@ public async Task BuildsResponseFromResponseMessage(HttpStatusCode httpStatusCod
Assert.Equal(httpStatusCode, response.StatusCode);
Assert.Null(response.ContentType);
}

[Fact]
public async Task BuildsByteArrayResponseFromResponseMessage()
public async Task BuildsStreamResponseFromResponseMessage()
{
var responseMessage = new HttpResponseMessage
{
Expand All @@ -157,7 +157,9 @@ public async Task BuildsByteArrayResponseFromResponseMessage()

var response = await tester.BuildResponseTester(responseMessage);

Assert.Equal(new byte[] { 0, 1, 1, 0, 1 }, response.Body);
var memoryStream = Assert.IsType<MemoryStream>(response.Body);

Assert.Equal(new byte[] { 0, 1, 1, 0, 1 }, memoryStream.ToArray());
Assert.Equal("image/png", response.ContentType);
}

Expand Down
98 changes: 98 additions & 0 deletions Octokit.Tests/Models/ArtifactsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using System;
using Octokit.Internal;
using Xunit;

namespace Octokit.Tests.Models
{
public class ArtifactsTests
{
[Fact]
public void CanBeDeserialized()
{
var json = @"{
""total_count"": 2,
""artifacts"": [
{
""id"": 11,
""node_id"": ""MDg6QXJ0aWZhY3QxMQ=="",
""name"": ""Rails"",
""size_in_bytes"": 556,
""url"": ""https://api.github.com/repos/octo-org/octo-docs/actions/artifacts/11"",
""archive_download_url"": ""https://api.github.com/repos/octo-org/octo-docs/actions/artifacts/11/zip"",
""expired"": false,
""created_at"": ""2020-01-10T14:59:22Z"",
""expires_at"": ""2020-03-21T14:59:22Z"",
""updated_at"": ""2020-02-21T14:59:22Z"",
""workflow_run"": {
""id"": 2332938,
""repository_id"": 1296269,
""head_repository_id"": 1296269,
""head_branch"": ""main"",
""head_sha"": ""328faa0536e6fef19753d9d91dc96a9931694ce3""
}
},
{
""id"": 13,
""node_id"": ""MDg6QXJ0aWZhY3QxMw=="",
""name"": ""Test output"",
""size_in_bytes"": 453,
""url"": ""https://api.github.com/repos/octo-org/octo-docs/actions/artifacts/13"",
""archive_download_url"": ""https://api.github.com/repos/octo-org/octo-docs/actions/artifacts/13/zip"",
""expired"": false,
""created_at"": ""2020-01-10T14:59:22Z"",
""expires_at"": ""2020-03-21T14:59:22Z"",
""updated_at"": ""2020-02-21T14:59:22Z"",
""workflow_run"": {
""id"": 2332942,
""repository_id"": 1296269,
""head_repository_id"": 1296269,
""head_branch"": ""main"",
""head_sha"": ""178f4f6090b3fccad4a65b3e83d076a622d59652""
}
}
]
}";

var serializer = new SimpleJsonSerializer();

var payload = serializer.Deserialize<ListArtifactsResponse>(json);

Assert.NotNull(payload);

Assert.Equal(2, payload.TotalCount);
Assert.Equal(2, payload.Artifacts.Count);

Assert.Equal(11, payload.Artifacts[0].Id);
Assert.Equal("MDg6QXJ0aWZhY3QxMQ==", payload.Artifacts[0].NodeId);
Assert.Equal("Rails", payload.Artifacts[0].Name);
Assert.Equal(556, payload.Artifacts[0].SizeInBytes);
Assert.Equal("https://api.github.com/repos/octo-org/octo-docs/actions/artifacts/11", payload.Artifacts[0].Url);
Assert.Equal("https://api.github.com/repos/octo-org/octo-docs/actions/artifacts/11/zip", payload.Artifacts[0].ArchiveDownloadUrl);
Assert.False(payload.Artifacts[0].Expired);
Assert.Equal(new DateTime(2020, 1, 10, 14, 59, 22, DateTimeKind.Utc), payload.Artifacts[0].CreatedAt);
Assert.Equal(new DateTime(2020, 3, 21, 14, 59, 22, DateTimeKind.Utc), payload.Artifacts[0].ExpiresAt);
Assert.Equal(new DateTime(2020, 2, 21, 14, 59, 22, DateTimeKind.Utc), payload.Artifacts[0].UpdatedAt);
Assert.Equal(2332938, payload.Artifacts[0].WorkflowRun.Id);
Assert.Equal(1296269, payload.Artifacts[0].WorkflowRun.RepositoryId);
Assert.Equal(1296269, payload.Artifacts[0].WorkflowRun.HeadRepositoryId);
Assert.Equal("main", payload.Artifacts[0].WorkflowRun.HeadBranch);
Assert.Equal("328faa0536e6fef19753d9d91dc96a9931694ce3", payload.Artifacts[0].WorkflowRun.HeadSha);

Assert.Equal(13, payload.Artifacts[1].Id);
Assert.Equal("MDg6QXJ0aWZhY3QxMw==", payload.Artifacts[1].NodeId);
Assert.Equal("Test output", payload.Artifacts[1].Name);
Assert.Equal(453, payload.Artifacts[1].SizeInBytes);
Assert.Equal("https://api.github.com/repos/octo-org/octo-docs/actions/artifacts/13", payload.Artifacts[1].Url);
Assert.Equal("https://api.github.com/repos/octo-org/octo-docs/actions/artifacts/13/zip", payload.Artifacts[1].ArchiveDownloadUrl);
Assert.False(payload.Artifacts[1].Expired);
Assert.Equal(new DateTime(2020, 1, 10, 14, 59, 22, DateTimeKind.Utc), payload.Artifacts[1].CreatedAt);
Assert.Equal(new DateTime(2020, 3, 21, 14, 59, 22, DateTimeKind.Utc), payload.Artifacts[1].ExpiresAt);
Assert.Equal(new DateTime(2020, 2, 21, 14, 59, 22, DateTimeKind.Utc), payload.Artifacts[1].UpdatedAt);
Assert.Equal(2332942, payload.Artifacts[1].WorkflowRun.Id);
Assert.Equal(1296269, payload.Artifacts[1].WorkflowRun.RepositoryId);
Assert.Equal(1296269, payload.Artifacts[1].WorkflowRun.HeadRepositoryId);
Assert.Equal("main", payload.Artifacts[1].WorkflowRun.HeadBranch);
Assert.Equal("178f4f6090b3fccad4a65b3e83d076a622d59652", payload.Artifacts[1].WorkflowRun.HeadSha);
}
}
}
4 changes: 1 addition & 3 deletions Octokit/Caching/CachedResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ public V1(object body, IReadOnlyDictionary<string, string> headers, ApiInfo apiI
ContentType = contentType;
}

/// <summary>
/// Raw response body. Typically a string, but when requesting images, it will be a byte array.
/// </summary>
/// <inheritdoc/>
public object Body { get; private set; }
/// <summary>
/// Information about the API.
Expand Down
60 changes: 59 additions & 1 deletion Octokit/Clients/ActionsArtifactsClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
namespace Octokit
using System.IO;
using System.Threading.Tasks;

namespace Octokit
{
/// <summary>
/// A client for GitHub's Actions Artifacts API.
Expand All @@ -15,5 +18,60 @@ public class ActionsArtifactsClient : ApiClient, IActionsArtifactsClient
public ActionsArtifactsClient(IApiConnection apiConnection) : base(apiConnection)
{
}

/// <inheritdoc/>
[ManualRoute("GET", "/repos/{owner}/{repository}/actions/artifacts")]
public Task<ListArtifactsResponse> ListArtifacts(string owner, string repository, ListArtifactsRequest listArtifactsRequest = null)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(repository, nameof(repository));

return ApiConnection.Get<ListArtifactsResponse>(ApiUrls.ListArtifacts(owner, repository), listArtifactsRequest?.ToParametersDictionary());
}

/// <inheritdoc/>
[ManualRoute("GET", "/repos/{owner}/{repository}/actions/artifacts/{artifact_id}")]
public Task<Artifact> GetArtifact(string owner, string repository, long artifactId)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(repository, nameof(repository));
Ensure.ArgumentNotNullOrDefault(artifactId, nameof(artifactId));

return ApiConnection.Get<Artifact>(ApiUrls.Artifact(owner, repository, artifactId), null);
}

/// <inheritdoc/>
[ManualRoute("DELETE", "/repos/{owner}/{repository}/actions/artifacts/{artifact_id}")]
public Task DeleteArtifact(string owner, string repository, long artifactId)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(repository, nameof(repository));
Ensure.ArgumentNotNullOrDefault(artifactId, nameof(artifactId));

return ApiConnection.Delete(ApiUrls.Artifact(owner, repository, artifactId), null);
}

/// <inheritdoc/>
[ManualRoute("GET", "/repos/{owner}/{repository}/actions/artifacts/{artifact_id}/{archive_format}")]
public Task<Stream> DownloadArtifact(string owner, string repository, long artifactId, string archiveFormat)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(repository, nameof(repository));
Ensure.ArgumentNotNullOrDefault(artifactId, nameof(artifactId));
Ensure.ArgumentNotNullOrEmptyString(repository, nameof(archiveFormat));

return ApiConnection.GetRawStream(ApiUrls.DownloadArtifact(owner, repository, artifactId, archiveFormat), null);
}

/// <inheritdoc/>
[ManualRoute("GET", "/repos/{owner}/{repo}/actions/runs/{run_id}/artifacts")]
public Task<ListArtifactsResponse> ListWorkflowArtifacts(string owner, string repository, long runId, ListArtifactsRequest listArtifactsRequest = null)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(repository, nameof(repository));
Ensure.ArgumentNotNullOrDefault(runId, nameof(runId));

return ApiConnection.Get<ListArtifactsResponse>(ApiUrls.ListWorkflowArtifacts(owner, repository, runId), listArtifactsRequest?.ToParametersDictionary());
}
}
}
46 changes: 45 additions & 1 deletion Octokit/Clients/IActionsArtifactsClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

namespace Octokit
Expand All @@ -11,5 +11,49 @@ namespace Octokit
/// </remarks>
public interface IActionsArtifactsClient
{
/// <summary>
/// Lists artifacts for a repository
/// </summary>
/// <param name="owner"></param>
/// <param name="repository"></param>
/// <returns></returns>
Task<ListArtifactsResponse> ListArtifacts(string owner, string repository, ListArtifactsRequest listArtifactsRequest = null);

/// <summary>
/// Gets the specified artifact
/// </summary>
/// <param name="owner"></param>
/// <param name="repository"></param>
/// <param name="artifactId"></param>
/// <returns></returns>
Task<Artifact> GetArtifact(string owner, string repository, long artifactId);

/// <summary>
/// Deletes the specified artifact
/// </summary>
/// <param name="owner"></param>
/// <param name="repository"></param>
/// <param name="artifactId"></param>
/// <returns></returns>
Task DeleteArtifact(string owner, string repository, long artifactId);

/// <summary>
/// Downloads the specified artifact's contents
/// </summary>
/// <param name="owner"></param>
/// <param name="repository"></param>
/// <param name="artifactId"></param>
/// <param name="archiveFormat"></param>
/// <returns></returns>
Task<Stream> DownloadArtifact(string owner, string repository, long artifactId, string archiveFormat);

/// <summary>
/// Lists the artifacts for a specific workflow run
/// </summary>
/// <param name="owner"></param>
/// <param name="repository"></param>
/// <param name="runId"></param>
/// <returns></returns>
Task<ListArtifactsResponse> ListWorkflowArtifacts(string owner, string repository, long runId, ListArtifactsRequest listArtifactsRequest = null);
}
}
Loading

0 comments on commit 958bc5f

Please sign in to comment.