Skip to content

Commit

Permalink
Adding support for creating Codespaces and getting available machine …
Browse files Browse the repository at this point in the history
…types (#2929)

Adding support for creating Codespaces
  • Loading branch information
Aaron-Junker authored Jul 29, 2024
1 parent 148162a commit 35f1784
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 3 deletions.
2 changes: 2 additions & 0 deletions Octokit.Reactive/IObservableCodespacesClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,7 @@ public interface IObservableCodespacesClient
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);
}
}
15 changes: 15 additions & 0 deletions Octokit.Reactive/ObservableCodespacesClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ public IObservable<CodespacesCollection> GetAll()
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));
Expand All @@ -43,5 +50,13 @@ public IObservable<Codespace> Stop(string codespaceName)
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();
}
}
}
15 changes: 15 additions & 0 deletions Octokit.Tests.Integration/Clients/CodespacesClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,19 @@ public async Task CanStopCodespace()
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);
}
}
19 changes: 19 additions & 0 deletions Octokit.Tests/Clients/CodespacesClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,24 @@ public void RequestsCorrectStopUrl()
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);
}
}
}
7 changes: 5 additions & 2 deletions Octokit/Clients/Codespace.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Octokit.Clients;
using System;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.CompilerServices;
Expand All @@ -23,8 +24,9 @@ public class Codespace
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;
Expand All @@ -41,6 +43,7 @@ public Codespace(long id, string name, User owner, User billableOwner, Repositor
WebUrl = webUrl;
StartUrl = startUrl;
StopUrl = stopUrl;
Location = location;
}

public Codespace() { }
Expand Down
24 changes: 24 additions & 0 deletions Octokit/Clients/CodespacesClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,29 @@ public Task<Codespace> Stop(string codespaceName)
{
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);
}
}
}
5 changes: 4 additions & 1 deletion Octokit/Clients/ICodespacesClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Octokit
Expand All @@ -10,5 +11,7 @@ public interface ICodespacesClient
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);
}
}
26 changes: 26 additions & 0 deletions Octokit/Clients/MachinesCollection.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
21 changes: 21 additions & 0 deletions Octokit/Helpers/ApiUrls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5604,6 +5604,22 @@ public static Uri ActionsListOrganizationRunnerGroupRepositories(string org, lon
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>
Expand Down Expand Up @@ -5659,6 +5675,11 @@ public static Uri CodespaceStop(string codespaceName)
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>
Expand Down
16 changes: 16 additions & 0 deletions Octokit/Models/Common/CodespaceLocation.cs
Original file line number Diff line number Diff line change
@@ -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
}
}
34 changes: 34 additions & 0 deletions Octokit/Models/Request/NewCodespace.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}

}
}

0 comments on commit 35f1784

Please sign in to comment.