Adding support for creating Codespaces and getting available machine types (#2929)

Adding support for creating Codespaces
This commit is contained in:
Aaron Junker-Wildi
2024-07-29 22:43:50 +02:00
committed by GitHub
parent 148162a34b
commit 35f1784781
11 changed files with 181 additions and 3 deletions

View File

@@ -16,5 +16,7 @@ namespace Octokit.Reactive
IObservable<Codespace> Get(string codespaceName);
IObservable<Codespace> Start(string codespaceName);
IObservable<Codespace> Stop(string codespaceName);
IObservable<MachinesCollection> GetAvailableMachinesForRepo(string repoOwner, string repoName, string reference = null);
IObservable<Codespace> Create(string owner, string repo, NewCodespace newCodespace);
}
}

View File

@@ -25,6 +25,13 @@ namespace Octokit.Reactive
return _client.GetAll().ToObservable();
}
public IObservable<MachinesCollection> GetAvailableMachinesForRepo(string repoOwner, string repoName, string reference = null)
{
Ensure.ArgumentNotNull(repoOwner, nameof(repoOwner));
Ensure.ArgumentNotNull(repoName, nameof(repoName));
return _client.GetAvailableMachinesForRepo(repoOwner, repoName, reference).ToObservable();
}
public IObservable<CodespacesCollection> GetForRepository(string owner, string repo)
{
Ensure.ArgumentNotNull(owner, nameof(owner));
@@ -43,5 +50,13 @@ namespace Octokit.Reactive
Ensure.ArgumentNotNull(codespaceName, nameof(codespaceName));
return _client.Stop(codespaceName).ToObservable();
}
public IObservable<Codespace> Create(string owner, string repo, NewCodespace newCodespace)
{
Ensure.ArgumentNotNull(owner, nameof(owner));
Ensure.ArgumentNotNull(repo, nameof(repo));
Ensure.ArgumentNotNull(newCodespace, nameof(newCodespace));
return _client.Create(owner, repo, newCodespace).ToObservable();
}
}
}

View File

@@ -56,4 +56,19 @@ public class CodespacesClientTests
var retrieved = await _fixture.Stop(codespaceName);
Assert.NotNull(retrieved);
}
[IntegrationTest]
public async Task CanGetAvailableMachinesForRepo()
{
var retrieved = await _fixture.GetAvailableMachinesForRepo(Helper.UserName, Helper.RepositoryWithCodespaces);
Assert.NotNull(retrieved);
}
[IntegrationTest]
public async Task CanCreateCodespace()
{
MachinesCollection machinesCollection = (await _fixture.GetAvailableMachinesForRepo(Helper.UserName, Helper.RepositoryWithCodespaces));
var retrieved = await _fixture.Create(Helper.UserName, Helper.RepositoryWithCodespaces, new NewCodespace(machinesCollection.Machines.First()));
Assert.NotNull(retrieved);
}
}

View File

@@ -68,5 +68,24 @@ public class CodespacesClientTests
client.Stop("codespaceName");
connection.Received().Post<Codespace>(Arg.Is<Uri>(u => u.ToString() == "user/codespaces/codespaceName/stop"));
}
[Fact]
public void RequestsCorrectGetAvailableMachinesForRepoUrl()
{
var connection = Substitute.For<IApiConnection>();
var client = new CodespacesClient(connection);
client.GetAvailableMachinesForRepo("owner", "repo");
connection.Received().Get<MachinesCollection>(Arg.Is<Uri>(u => u.ToString() == "repos/owner/repo/codespaces/machines"));
}
[Fact]
public void RequestsCorrectCreateNewCodespaceUrl()
{
var connection = Substitute.For<IApiConnection>();
var client = new CodespacesClient(connection);
NewCodespace newCodespace = new NewCodespace(new Machine());
client.Create("owner", "repo", newCodespace);
connection.Received().Post<Codespace>(Arg.Is<Uri>(u => u.ToString() == "repos/owner/repo/codespaces"), newCodespace);
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using Octokit.Clients;
using System;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.CompilerServices;
@@ -23,8 +24,9 @@ namespace Octokit
public string WebUrl { get; private set; }
public string StartUrl { get; private set; }
public string StopUrl { get; private set; }
public StringEnum<CodespaceLocation> Location { get; private set; }
public Codespace(long id, string name, User owner, User billableOwner, Repository repository, Machine machine, DateTime createdAt, DateTime updatedAt, DateTime lastUsedAt, StringEnum<CodespaceState> state, string url, string machinesUrl, string webUrl, string startUrl, string stopUrl)
public Codespace(long id, string name, User owner, User billableOwner, Repository repository, Machine machine, DateTime createdAt, DateTime updatedAt, DateTime lastUsedAt, StringEnum<CodespaceState> state, string url, string machinesUrl, string webUrl, string startUrl, string stopUrl, StringEnum<CodespaceLocation> location)
{
Id = id;
Name = name;
@@ -41,6 +43,7 @@ namespace Octokit
WebUrl = webUrl;
StartUrl = startUrl;
StopUrl = stopUrl;
Location = location;
}
public Codespace() { }

View File

@@ -76,5 +76,29 @@ namespace Octokit
{
return ApiConnection.Post<Codespace>(ApiUrls.CodespaceStop(codespaceName));
}
/// <summary>
/// Returns available machines for the specified repository.
/// </summary>
[ManualRoute("GET", "/repos/{repoOwner}/{repoName}/machines")]
public Task<MachinesCollection> GetAvailableMachinesForRepo(string repoOwner, string repoName, string reference = null)
{
Ensure.ArgumentNotNullOrEmptyString(repoOwner, nameof(repoOwner));
Ensure.ArgumentNotNullOrEmptyString(repoName, nameof(repoName));
return ApiConnection.Get<MachinesCollection>(ApiUrls.GetAvailableMachinesForRepo(repoOwner, repoName, reference));
}
/// <summary>
/// Creates a new codespace for the authenticated user.
/// </summary>
[ManualRoute("POST", "/repos/{owner}/{repo}/codespaces")]
public Task<Codespace> Create(string owner, string repo, NewCodespace newCodespace)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(repo, nameof(repo));
return ApiConnection.Post<Codespace>(ApiUrls.CreateCodespace(owner, repo), newCodespace);
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Octokit
@@ -10,5 +11,7 @@ namespace Octokit
Task<Codespace> Get(string codespaceName);
Task<Codespace> Start(string codespaceName);
Task<Codespace> Stop(string codespaceName);
Task<MachinesCollection> GetAvailableMachinesForRepo(string repoOwner, string repoName, string reference = null);
Task<Codespace> Create(string owner, string repo, NewCodespace newCodespace);
}
}

View File

@@ -0,0 +1,26 @@
using Octokit.Internal;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
namespace Octokit
{
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class MachinesCollection
{
public MachinesCollection(IReadOnlyList<Machine> machines, int count)
{
Machines = machines;
Count = count;
}
public MachinesCollection() { }
[Parameter(Key = "total_count")]
public int Count { get; private set; }
[Parameter(Key = "machines")]
public IReadOnlyList<Machine> Machines { get; private set; } = new List<Machine>();
internal string DebuggerDisplay => string.Format(CultureInfo.CurrentCulture, "MachinesCollection: Count: {0}", Count);
}
}

View File

@@ -5604,6 +5604,22 @@ namespace Octokit
return "orgs/{0}/actions/runner-groups/{1}/repositories".FormatUri(org, runnerGroupId);
}
/// <summary>
/// Returns the <see cref="Uri"/> that handles the machine availability for a repository.
/// </summary>
/// <param name="owner">The owner of the repository.</param>
/// <param name="repo">The name of the repository.</param>
/// <param name="reference">The reference to check the machine availability for.</param>
public static Uri GetAvailableMachinesForRepo(string owner, string repo, string reference)
{
if (reference is null)
{
return "repos/{0}/{1}/codespaces/machines".FormatUri(owner, repo);
}
return "repos/{0}/{1}/actions/runners/availability?ref={3}".FormatUri(owner, repo, reference);
}
/// <summary>
/// Returns the <see cref="Uri"/> that handles adding or removing of copilot licenses for an organisation
/// </summary>
@@ -5659,6 +5675,11 @@ namespace Octokit
return "user/codespaces/{0}/stop".FormatUri(codespaceName);
}
public static Uri CreateCodespace(string owner, string repo)
{
return "repos/{0}/{1}/codespaces".FormatUri(owner, repo);
}
/// <summary>
/// Returns the <see cref="Uri"/> that lists the artifacts for a repository.
/// </summary>

View File

@@ -0,0 +1,16 @@
using Octokit.Internal;
namespace Octokit
{
public enum CodespaceLocation
{
[Parameter(Value = "EuropeWest")]
EuropeWest,
[Parameter(Value = "SoutheastAsia")]
SoutheastAsia,
[Parameter(Value = "UsEast")]
UsEast,
[Parameter(Value = "UsWest")]
UsWest
}
}

View File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Text;
namespace Octokit
{
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class NewCodespace
{
public string MachineType { get; set; }
public string Reference { get; set; }
public CodespaceLocation? Location { get; set; }
public string DisplayName { get; set; }
public NewCodespace(Machine machineType, string reference = "main", CodespaceLocation? location = null, string displayName = null)
{
MachineType = machineType.Name;
Reference = reference;
Location = location;
DisplayName = displayName;
}
internal string DebuggerDisplay
{
get
{
return string.Format(CultureInfo.InvariantCulture, "NewCodespace Repo: {0}", DisplayName);
}
}
}
}