mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-27 07:04:57 +01:00
Merge pull request #555 from Cyberboss/OkayWhatNow
Repository reporting 100%
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Linq;
|
||||
@@ -11,6 +10,7 @@ using Tgstation.Server.Host.Components.Compiler;
|
||||
using Tgstation.Server.Host.Components.Repository;
|
||||
using Tgstation.Server.Host.Components.Watchdog;
|
||||
using Tgstation.Server.Host.Core;
|
||||
using Tgstation.Server.Host.Models;
|
||||
|
||||
namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
@@ -122,14 +122,15 @@ namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
await Task.Delay(new TimeSpan(0, minutes, 0), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
string accessToken = null, projectName = null;
|
||||
RepositorySettings repositorySettings = null;
|
||||
string projectName = null;
|
||||
int timeout = 0;
|
||||
var dbTask = databaseContextFactory.UseContext(async (db) =>
|
||||
{
|
||||
var instanceQuery = db.Instances.Where(x => x.Id == metadata.Id);
|
||||
var timeoutTask = instanceQuery.Select(x => x.DreamDaemonSettings.StartupTimeout).FirstAsync(cancellationToken);
|
||||
var projectNameTask = instanceQuery.Select(x => x.DreamMakerSettings.ProjectName).FirstOrDefaultAsync(cancellationToken);
|
||||
accessToken = await instanceQuery.Select(x => x.RepositorySettings.AccessToken).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
|
||||
repositorySettings = await instanceQuery.Select(x => x.RepositorySettings).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
|
||||
projectName = await projectNameTask.ConfigureAwait(false);
|
||||
timeout = (await timeoutTask.ConfigureAwait(false)).Value;
|
||||
});
|
||||
@@ -150,8 +151,27 @@ namespace Tgstation.Server.Host.Components
|
||||
}
|
||||
if (repo == null)
|
||||
continue;
|
||||
await repo.FetchOrigin(accessToken, null, cancellationToken).ConfigureAwait(false);
|
||||
await repo.ResetToOrigin(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
await repo.FetchOrigin(repositorySettings.AccessUser, repositorySettings.AccessToken, null, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var startSha = repo.Head;
|
||||
bool shouldSyncTracked;
|
||||
if (repositorySettings.AutoUpdatesKeepTestMerges.Value)
|
||||
{
|
||||
var result = await repo.MergeOrigin(repositorySettings.CommitterName, repositorySettings.CommitterEmail, cancellationToken).ConfigureAwait(false);
|
||||
if (!result.HasValue)
|
||||
continue;
|
||||
shouldSyncTracked = result.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
await repo.ResetToOrigin(cancellationToken).ConfigureAwait(false);
|
||||
shouldSyncTracked = true;
|
||||
}
|
||||
|
||||
if (repositorySettings.AutoUpdatesSynchronize.Value && startSha != repo.Head)
|
||||
await repo.Sychronize(repositorySettings.AccessUser, repositorySettings.AccessToken, shouldSyncTracked, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var job = await DreamMaker.Compile(projectName, timeout, repo, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,20 +59,23 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
/// <param name="targetCommit">The commit in the pull request to merge</param>
|
||||
/// <param name="committerName">The name of the merge committer</param>
|
||||
/// <param name="committerEmail">The e-mail of the merge committer</param>
|
||||
/// <param name="accessString">The access string to fetch from the origin repository</param>
|
||||
/// <param name="commitMessage">The commit message</param>
|
||||
/// <param name="username">The username to fetch from the origin repository</param>
|
||||
/// <param name="password">The password to fetch from the origin repository</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <param name="progressReporter">Optional function to report 0-100 progress of the clone</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in a <see cref="Nullable{T}"/> <see cref="bool"/> representing the merge result that is <see langword="true"/> after a fast forward or up to date, <see langword="false"/> on a merge, <see langword="null"/> on a conflict</returns>
|
||||
Task<bool?> AddTestMerge(int pullRequestNumber, string targetCommit, string committerName, string committerEmail, string accessString, Action<int> progressReporter, CancellationToken cancellationToken);
|
||||
Task<bool?> AddTestMerge(int pullRequestNumber, string targetCommit, string committerName, string committerEmail, string commitMessage, string username, string password, Action<int> progressReporter, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Fetch commits from the origin repository
|
||||
/// </summary>
|
||||
/// <param name="accessString">The access string to fetch from the origin repository</param>
|
||||
/// <param name="username">The username to fetch from the origin repository</param>
|
||||
/// <param name="password">The password to fetch from the origin repository</param>
|
||||
/// <param name="progressReporter">Optional function to report 0-100 progress of the clone</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task"/> representing the running operation</returns>
|
||||
Task FetchOrigin(string accessString, Action<int> progressReporter, CancellationToken cancellationToken);
|
||||
Task FetchOrigin(string username, string password, Action<int> progressReporter, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Requires the current HEAD to be a tracked reference. Hard resets the reference to what it tracks on the origin repository
|
||||
@@ -81,6 +84,14 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in the SHA of the new HEAD</returns>
|
||||
Task ResetToOrigin(CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Requires the current HEAD to be a reference. Hard resets the reference to the given sha
|
||||
/// </summary>
|
||||
/// <param name="sha">The sha hash to reset to</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in the SHA of the new HEAD</returns>
|
||||
Task ResetToSha(string sha, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Requires the current HEAD to be a tracked reference. Merges the reference to what it tracks on the origin repository
|
||||
/// </summary>
|
||||
@@ -90,21 +101,15 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in a <see cref="Nullable{T}"/> <see cref="bool"/> representing the merge result that is <see langword="true"/> after a fast forward or up to date, <see langword="false"/> on a merge, <see langword="null"/> on a conflict</returns>
|
||||
Task<bool?> MergeOrigin(string committerName, string committerEmail, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Force push the current repository HEAD to <see cref="Repository.RemoteTemporaryBranchName"/>;
|
||||
/// </summary>
|
||||
/// <param name="accessString">The access string to fetch from the origin repository</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task"/> representing the running operation</returns>
|
||||
Task PushHeadToTemporaryBranch(string accessString, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Runs the synchronize event script and attempts to push any changes made to the <see cref="IRepository"/> if on a tracked branch
|
||||
/// </summary>
|
||||
/// <param name="accessString">The access string to push to the origin repository</param>
|
||||
/// <param name="username">The username to fetch from the origin repository</param>
|
||||
/// <param name="password">The password to fetch from the origin repository</param>
|
||||
/// <param name="synchronizeTrackedBranch">If the synchronizations should be made to the tracked reference as opposed to a temporary branch</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task"/> representing the running operation</returns>
|
||||
Task Sychronize(string accessString, CancellationToken cancellationToken);
|
||||
Task Sychronize(string username, string password, bool synchronizeTrackedBranch, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Copies the current working directory to a given <paramref name="path"/>
|
||||
|
||||
@@ -21,11 +21,12 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
/// </summary>
|
||||
/// <param name="url">The <see cref="Uri"/> of the remote repository to clone</param>
|
||||
/// <param name="initialBranch">The branch to clone</param>
|
||||
/// <param name="accessString">The access string to clone from <paramref name="url"/></param>
|
||||
/// <param name="username">The username to clone from <paramref name="url"/></param>
|
||||
/// <param name="password">The password to clone from <paramref name="url"/></param>
|
||||
/// <param name="progressReporter">A function to report 0-100 progress of the clone</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>The newly cloned <see cref="IRepository"/>, <see langword="null"/> if one already exists</returns>
|
||||
Task<IRepository> CloneRepository(Uri url, string initialBranch, string accessString, Action<int> progressReporter, CancellationToken cancellationToken);
|
||||
Task<IRepository> CloneRepository(Uri url, string initialBranch, string username, string password, Action<int> progressReporter, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Delete the current repository
|
||||
|
||||
@@ -106,24 +106,6 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
repository.Dispose();
|
||||
onDispose.Invoke();
|
||||
}
|
||||
/// <summary>
|
||||
/// Convert <paramref name="url"/> to an "https://<paramref name="accessString"/>@{url} equivalent
|
||||
/// </summary>
|
||||
/// <param name="url">The URL to convert</param>
|
||||
/// <param name="accessString">The <see cref="string"/> containing authentication info for the remote repository</param>
|
||||
/// <returns>An authenticated URL for accessing the remote repository</returns>
|
||||
public static string GenerateAuthUrl(string url, string accessString)
|
||||
{
|
||||
if (url == null)
|
||||
throw new ArgumentNullException(nameof(url));
|
||||
if (String.IsNullOrWhiteSpace(accessString))
|
||||
return url;
|
||||
const string HttProtocolSecure = "HTTPS://";
|
||||
if (!url.ToUpperInvariant().StartsWith(HttProtocolSecure, StringComparison.InvariantCulture))
|
||||
throw new InvalidOperationException("Cannot use access string without HTTPS remote!");
|
||||
//ONLY support https urls
|
||||
return url.ToUpperInvariant().Replace(HttProtocolSecure, String.Concat(HttProtocolSecure, accessString, '@'), StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs a blocking force checkout to <paramref name="committish"/>
|
||||
@@ -139,7 +121,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<bool?> AddTestMerge(int pullRequestNumber, string targetCommit, string committerName, string committerEmail, string accessString, Action<int> progressReporter, CancellationToken cancellationToken)
|
||||
public async Task<bool?> AddTestMerge(int pullRequestNumber, string targetCommit, string committerName, string committerEmail, string commitMessage, string username, string password, Action<int> progressReporter, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
if (!IsGitHubRepository)
|
||||
@@ -154,12 +136,13 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
var originalCommit = repository.Head;
|
||||
|
||||
MergeResult result = null;
|
||||
|
||||
var sig = new Signature(new Identity(committerName, committerEmail), DateTimeOffset.Now);
|
||||
await Task.Factory.StartNew(() =>
|
||||
{
|
||||
var remote = repository.Network.Remotes.Add("temp_pr_fetch", GenerateAuthUrl(Origin, accessString));
|
||||
try
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var remote = repository.Network.Remotes.First();
|
||||
Commands.Fetch((LibGit2Sharp.Repository)repository, remote.Name, Refspec, new FetchOptions
|
||||
{
|
||||
Prune = true,
|
||||
@@ -170,23 +153,24 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
progressReporter?.Invoke((int)percentage);
|
||||
return !cancellationToken.IsCancellationRequested;
|
||||
},
|
||||
OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested
|
||||
OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
|
||||
CredentialsProvider = (a, b, c) => username != null ? (Credentials)new UsernamePasswordCredentials
|
||||
{
|
||||
Username = username,
|
||||
Password = password
|
||||
} : new DefaultCredentials()
|
||||
}, logMessage);
|
||||
}
|
||||
catch (UserCancelledException) { }
|
||||
finally
|
||||
catch (UserCancelledException)
|
||||
{
|
||||
repository.Network.Remotes.Remove(remote.Name);
|
||||
//commit is there and we never gc so
|
||||
repository.Branches.Remove(localBranchName);
|
||||
repository.Branches.Remove(prBranchName);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
result = repository.Merge(targetCommit, new Signature(new Identity(committerName, committerEmail), DateTimeOffset.Now), new MergeOptions
|
||||
result = repository.Merge(targetCommit, sig, new MergeOptions
|
||||
{
|
||||
CommitOnSuccess = true,
|
||||
CommitOnSuccess = commitMessage == null,
|
||||
FailOnConflict = true,
|
||||
FastForwardStrategy = FastForwardStrategy.NoFastForward,
|
||||
SkipReuc = true
|
||||
@@ -209,6 +193,12 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
return false;
|
||||
}
|
||||
|
||||
if (commitMessage != null)
|
||||
repository.Commit(commitMessage, sig, sig, new CommitOptions
|
||||
{
|
||||
PrettifyMessage = true
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -222,7 +212,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task FetchOrigin(string accessString, Action<int> progressReporter, CancellationToken cancellationToken) => Task.WhenAll(
|
||||
public Task FetchOrigin(string username, string password, Action<int> progressReporter, CancellationToken cancellationToken) => Task.WhenAll(
|
||||
eventConsumer.HandleEvent(EventType.RepoFetch, Array.Empty<string>(), cancellationToken),
|
||||
Task.Factory.StartNew(() =>
|
||||
{
|
||||
@@ -239,7 +229,12 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
progressReporter?.Invoke((int)percentage);
|
||||
return !cancellationToken.IsCancellationRequested;
|
||||
},
|
||||
OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested
|
||||
OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
|
||||
CredentialsProvider = (a, b, c) => username != null ? (Credentials)new UsernamePasswordCredentials
|
||||
{
|
||||
Username = username,
|
||||
Password = password
|
||||
} : new DefaultCredentials()
|
||||
}, "Fetch origin commits");
|
||||
}
|
||||
catch (UserCancelledException)
|
||||
@@ -248,34 +243,37 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
}
|
||||
}, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current));
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task PushHeadToTemporaryBranch(string accessString, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
|
||||
/// <summary>
|
||||
/// Force push the current repository HEAD to <see cref="Repository.RemoteTemporaryBranchName"/>;
|
||||
/// </summary>
|
||||
/// <param name="username">The username to fetch from the origin repository</param>
|
||||
/// <param name="password">The password to fetch from the origin repository</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task"/> representing the running operation</returns>
|
||||
Task PushHeadToTemporaryBranch(string username, string password, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
|
||||
{
|
||||
var branch = repository.CreateBranch(RemoteTemporaryBranchName);
|
||||
try
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var remote = repository.Network.Remotes.Add("temp_push", GenerateAuthUrl(Origin, accessString));
|
||||
var remote = repository.Network.Remotes.First();
|
||||
try
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
try
|
||||
repository.Network.Push(remote, String.Format(CultureInfo.InvariantCulture, "+{0}:{0}", branch.CanonicalName), new PushOptions
|
||||
{
|
||||
repository.Network.Push(remote, String.Format(CultureInfo.InvariantCulture, "+{0}:{0}", branch.CanonicalName), new PushOptions
|
||||
OnPackBuilderProgress = (a, b, c) => !cancellationToken.IsCancellationRequested,
|
||||
OnNegotiationCompletedBeforePush = (a) => !cancellationToken.IsCancellationRequested,
|
||||
OnPushTransferProgress = (a, b, c) => !cancellationToken.IsCancellationRequested,
|
||||
CredentialsProvider = (a, b, c) => username != null ? (Credentials)new UsernamePasswordCredentials
|
||||
{
|
||||
OnPackBuilderProgress = (a, b, c) => !cancellationToken.IsCancellationRequested,
|
||||
OnNegotiationCompletedBeforePush = (a) => !cancellationToken.IsCancellationRequested,
|
||||
OnPushTransferProgress = (a, b, c) => !cancellationToken.IsCancellationRequested
|
||||
});
|
||||
}
|
||||
catch (UserCancelledException)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
Username = username,
|
||||
Password = password
|
||||
} : new DefaultCredentials()
|
||||
});
|
||||
}
|
||||
finally
|
||||
catch (UserCancelledException)
|
||||
{
|
||||
repository.Network.Remotes.Remove(remote.Name);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -291,17 +289,17 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
throw new InvalidOperationException("Cannot reset to origin while not on a tracked reference!");
|
||||
var trackedBranch = repository.Head.TrackedBranch;
|
||||
await eventConsumer.HandleEvent(EventType.RepoResetOrigin, new List<string> { trackedBranch.FriendlyName, trackedBranch.Tip.Sha }, cancellationToken).ConfigureAwait(false);
|
||||
await Task.Factory.StartNew(() =>
|
||||
{
|
||||
Commands.Checkout((LibGit2Sharp.Repository)repository, repository.Head.TrackedBranch, new CheckoutOptions
|
||||
{
|
||||
CheckoutModifiers = CheckoutModifiers.Force
|
||||
});
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
repository.RemoveUntrackedFiles();
|
||||
}, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
|
||||
await ResetToSha(trackedBranch.Tip.Sha, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task ResetToSha(string sha, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
|
||||
{
|
||||
repository.Reset(ResetMode.Hard, sha);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
repository.RemoveUntrackedFiles();
|
||||
}, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task CopyTo(string path, CancellationToken cancellationToken)
|
||||
{
|
||||
@@ -353,40 +351,43 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task Sychronize(string accessString, CancellationToken cancellationToken)
|
||||
public async Task Sychronize(string username, string password, bool synchronizeTrackedBranch, CancellationToken cancellationToken)
|
||||
{
|
||||
var startHead = Head;
|
||||
|
||||
if (!await eventConsumer.HandleEvent(EventType.RepoPreSynchronize, new List<string> { ioMananger.ResolvePath(".") }, cancellationToken).ConfigureAwait(false))
|
||||
return;
|
||||
|
||||
if (!synchronizeTrackedBranch)
|
||||
{
|
||||
await PushHeadToTemporaryBranch(username, password, cancellationToken).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Head == startHead || !repository.Head.IsTracking)
|
||||
return;
|
||||
|
||||
await Task.Factory.StartNew(() =>
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var remote = repository.Network.Remotes.Add("temp_push", GenerateAuthUrl(Origin, accessString));
|
||||
var remote = repository.Network.Remotes.First();
|
||||
try
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
try
|
||||
repository.Network.Push(repository.Head, new PushOptions
|
||||
{
|
||||
repository.Network.Push(repository.Head, new PushOptions
|
||||
OnPackBuilderProgress = (a, b, c) => !cancellationToken.IsCancellationRequested,
|
||||
OnNegotiationCompletedBeforePush = (a) => !cancellationToken.IsCancellationRequested,
|
||||
OnPushTransferProgress = (a, b, c) => !cancellationToken.IsCancellationRequested,
|
||||
CredentialsProvider = (a, b, c) => username != null ? (Credentials)new UsernamePasswordCredentials
|
||||
{
|
||||
OnPackBuilderProgress = (a, b, c) => !cancellationToken.IsCancellationRequested,
|
||||
OnNegotiationCompletedBeforePush = (a) => !cancellationToken.IsCancellationRequested,
|
||||
OnPushTransferProgress = (a, b, c) => !cancellationToken.IsCancellationRequested
|
||||
});
|
||||
}
|
||||
catch (UserCancelledException)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
Username = username,
|
||||
Password = password
|
||||
} : new DefaultCredentials()
|
||||
});
|
||||
}
|
||||
finally
|
||||
catch (UserCancelledException)
|
||||
{
|
||||
repository.Network.Remotes.Remove(remote.Name);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
}, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
public void Dispose() => semaphore.Dispose();
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IRepository> CloneRepository(Uri url, string initialBranch, string accessString, Action<int> progressReporter, CancellationToken cancellationToken)
|
||||
public async Task<IRepository> CloneRepository(Uri url, string initialBranch, string username, string password, Action<int> progressReporter, CancellationToken cancellationToken)
|
||||
{
|
||||
using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
|
||||
if (!await ioManager.DirectoryExists(".", cancellationToken).ConfigureAwait(false))
|
||||
@@ -60,7 +60,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
string path = null;
|
||||
try
|
||||
{
|
||||
path = LibGit2Sharp.Repository.Clone(Repository.GenerateAuthUrl(url.ToString(), accessString), ioManager.ResolvePath("."), new CloneOptions
|
||||
path = LibGit2Sharp.Repository.Clone(url.ToString(), ioManager.ResolvePath("."), new CloneOptions
|
||||
{
|
||||
OnProgress = (a) => !cancellationToken.IsCancellationRequested,
|
||||
OnTransferProgress = (a) =>
|
||||
@@ -72,7 +72,12 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
RecurseSubmodules = true,
|
||||
OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
|
||||
RepositoryOperationStarting = (a) => !cancellationToken.IsCancellationRequested,
|
||||
BranchName = initialBranch
|
||||
BranchName = initialBranch,
|
||||
CredentialsProvider = (a, b, c) => username != null ? (Credentials)new UsernamePasswordCredentials
|
||||
{
|
||||
Username = username,
|
||||
Password = password
|
||||
} : new DefaultCredentials()
|
||||
});
|
||||
}
|
||||
catch (UserCancelledException) { }
|
||||
|
||||
@@ -158,7 +158,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogInformation("Request made by User ID {0}. Api version: {1}. User-Agent: {2}", AuthenticationContext.User?.Id.ToString(CultureInfo.InvariantCulture) ?? "NULL", ApiHeaders.ApiVersion, ApiHeaders.UserAgent);
|
||||
Logger.LogInformation("Request made by User ID {0}. Api version: {1}. User-Agent: {2}", AuthenticationContext?.User.Id.ToString(CultureInfo.InvariantCulture) ?? "NULL", ApiHeaders.ApiVersion, ApiHeaders.UserAgent);
|
||||
await base.OnActionExecutionAsync(context, next).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
Path = model.Path,
|
||||
RepositorySettings = new RepositorySettings
|
||||
{
|
||||
CommitterEmail = "tgstation-server@user.noreply.github.com",
|
||||
CommitterEmail = "tgstation-server@users.noreply.github.com",
|
||||
CommitterName = application.VersionString,
|
||||
PushTestMergeCommits = false,
|
||||
ShowTestMergeCommitters = true,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -56,36 +57,41 @@ namespace Tgstation.Server.Host.Controllers
|
||||
this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
|
||||
}
|
||||
|
||||
static string GetAccessString(Api.Models.Internal.RepositorySettings repositorySettings) => repositorySettings.AccessUser != null ? String.Concat(repositorySettings.AccessUser, '@', repositorySettings.AccessToken) : null;
|
||||
|
||||
async Task<bool> LoadRevisionInformation(Components.Repository.IRepository repository, string lastOriginCommitSha, Action<Models.RevisionInformation> revInfoSink, CancellationToken cancellationToken)
|
||||
static async Task<bool> LoadRevisionInformation(Components.Repository.IRepository repository, IDatabaseContext databaseContext, Models.Instance instance, string lastOriginCommitSha, Action<Models.RevisionInformation> revInfoSink, CancellationToken cancellationToken)
|
||||
{
|
||||
var repoSha = repository.Head;
|
||||
var revisionInfo = await DatabaseContext.RevisionInformations.Where(x => x.CommitSha == repoSha)
|
||||
|
||||
IQueryable<Models.RevisionInformation> queryTarget = databaseContext.RevisionInformations;
|
||||
|
||||
var revisionInfo = await databaseContext.RevisionInformations.Where(x => x.CommitSha == repoSha && x.Instance.Id == instance.Id)
|
||||
.Include(x => x.CompileJobs)
|
||||
.Include(x => x.ActiveTestMerges) //minimal info, they can query the rest if they're allowed
|
||||
.Include(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge) //minimal info, they can query the rest if they're allowed
|
||||
.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); //search every rev info because LOL SHA COLLISIONS
|
||||
|
||||
if (revisionInfo == default)
|
||||
revisionInfo = databaseContext.RevisionInformations.Local.Where(x => x.CommitSha == repoSha).FirstOrDefault();
|
||||
|
||||
var needsDbUpdate = revisionInfo == default;
|
||||
if (needsDbUpdate)
|
||||
{
|
||||
//needs insertion
|
||||
revisionInfo = new Models.RevisionInformation
|
||||
{
|
||||
Instance = instance,
|
||||
CommitSha = repoSha,
|
||||
CompileJobs = new List<Models.CompileJob>(),
|
||||
ActiveTestMerges = new List<RevInfoTestMerge>() //non null vals for api returns
|
||||
};
|
||||
|
||||
lock (DatabaseContext) //cleaner this way
|
||||
DatabaseContext.RevisionInformations.Add(revisionInfo);
|
||||
lock (databaseContext) //cleaner this way
|
||||
databaseContext.RevisionInformations.Add(revisionInfo);
|
||||
}
|
||||
revisionInfo.OriginCommitSha = revisionInfo.OriginCommitSha ?? lastOriginCommitSha ?? repository.Head;
|
||||
revInfoSink?.Invoke(revisionInfo);
|
||||
return needsDbUpdate;
|
||||
}
|
||||
|
||||
async Task<bool> PopulateApi(Repository model, Components.Repository.IRepository repository, string lastOriginCommitSha, Action<Models.RevisionInformation> revInfoSink, CancellationToken cancellationToken)
|
||||
static async Task<bool> PopulateApi(Repository model, Components.Repository.IRepository repository, IDatabaseContext databaseContext, Models.Instance instance, string lastOriginCommitSha, Action<Models.RevisionInformation> revInfoSink, CancellationToken cancellationToken)
|
||||
{
|
||||
model.IsGitHub = repository.IsGitHubRepository;
|
||||
model.Origin = repository.Origin;
|
||||
@@ -93,7 +99,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
|
||||
//rev info stuff
|
||||
Models.RevisionInformation revisionInfo = null;
|
||||
var needsDbUpdate = await LoadRevisionInformation(repository, lastOriginCommitSha, x => revisionInfo = x, cancellationToken).ConfigureAwait(false);
|
||||
var needsDbUpdate = await LoadRevisionInformation(repository, databaseContext, instance, lastOriginCommitSha, x => revisionInfo = x, cancellationToken).ConfigureAwait(false);
|
||||
model.RevisionInformation = revisionInfo.ToApi();
|
||||
revInfoSink?.Invoke(revisionInfo);
|
||||
return needsDbUpdate;
|
||||
@@ -149,11 +155,11 @@ namespace Tgstation.Server.Host.Controllers
|
||||
var api = currentModel.ToApi();
|
||||
await jobManager.RegisterOperation(job, async (paramJob, serviceProvider, progressReporter, ct) =>
|
||||
{
|
||||
using (var repos = await repoManager.CloneRepository(new Uri(origin), cloneBranch, GetAccessString(currentModel), progressReporter, cancellationToken).ConfigureAwait(false))
|
||||
using (var repos = await repoManager.CloneRepository(new Uri(origin), cloneBranch, currentModel.AccessUser, currentModel.AccessToken, progressReporter, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
if (repos == null)
|
||||
throw new Exception("Filesystem conflict while cloning repository!");
|
||||
await PopulateApi(api, repo, null, null, cancellationToken).ConfigureAwait(false);
|
||||
await PopulateApi(api, repo, DatabaseContext, Instance, null, null, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@@ -211,7 +217,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
|
||||
using (var repo = await instanceManager.GetInstance(Instance).RepositoryManager.LoadRepository(cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
if (repo != null && await PopulateApi(api, repo, null, null, cancellationToken).ConfigureAwait(false))
|
||||
if (repo != null && await PopulateApi(api, repo, DatabaseContext, Instance, null, null, cancellationToken).ConfigureAwait(false))
|
||||
//user may have fucked with the repo without telling us, do what we can
|
||||
await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
|
||||
return Json(api);
|
||||
@@ -273,8 +279,15 @@ namespace Tgstation.Server.Host.Controllers
|
||||
|| (model.UpdateFromOrigin == true && !userRights.HasFlag(RepositoryRights.UpdateBranch)))
|
||||
return Forbid();
|
||||
|
||||
//no, just one save changes at the end for sanity
|
||||
//await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
|
||||
if (currentModel.AccessToken.Length == 0 || currentModel.AccessUser.Length == 0)
|
||||
{
|
||||
//setting an empty string clears everything
|
||||
currentModel.AccessUser = null;
|
||||
currentModel.AccessToken = null;
|
||||
}
|
||||
|
||||
//this is just db stuf so stow it away
|
||||
await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var job = new Models.Job
|
||||
{
|
||||
@@ -294,13 +307,13 @@ namespace Tgstation.Server.Host.Controllers
|
||||
|
||||
var modelHasShaOrReference = model.CheckoutSha != null || model.Reference != null;
|
||||
|
||||
var startReference = repo.Reference;
|
||||
var startSha = repo.Head;
|
||||
|
||||
if (newTestMerges && !repo.IsGitHubRepository)
|
||||
throw new InvalidOperationException("Cannot test merge on a non GitHub based repository!");
|
||||
|
||||
var committerName = currentModel.ShowTestMergeCommitters.Value ? AuthenticationContext.User.Name : currentModel.CommitterName;
|
||||
var accessString = GetAccessString(currentModel);
|
||||
|
||||
var numFetches = (model.NewTestMerges?.Count ?? 0) + (model.UpdateFromOrigin == true ? 1 : 0);
|
||||
var doneFetches = 0;
|
||||
@@ -309,13 +322,21 @@ namespace Tgstation.Server.Host.Controllers
|
||||
|
||||
//get a base line for where we are
|
||||
Models.RevisionInformation lastRevisionInfo = null;
|
||||
await LoadRevisionInformation(repo, null, x => lastRevisionInfo = x, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var databaseContext = serviceProvider.GetRequiredService<IDatabaseContext>();
|
||||
var attachedInstance = new Models.Instance
|
||||
{
|
||||
Id = Instance.Id
|
||||
};
|
||||
databaseContext.Instances.Attach(attachedInstance);
|
||||
|
||||
await LoadRevisionInformation(repo, databaseContext, attachedInstance, null, x => lastRevisionInfo = x, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
//apply new rev info, tracking applied test merges
|
||||
async Task UpdateRevInfo()
|
||||
{
|
||||
var last = lastRevisionInfo;
|
||||
await LoadRevisionInformation(repo, last.OriginCommitSha, x => lastRevisionInfo = x, cancellationToken).ConfigureAwait(false);
|
||||
await LoadRevisionInformation(repo, databaseContext, attachedInstance, last.OriginCommitSha, x => lastRevisionInfo = x, cancellationToken).ConfigureAwait(false);
|
||||
lastRevisionInfo.ActiveTestMerges.AddRange(last.ActiveTestMerges);
|
||||
};
|
||||
|
||||
@@ -326,7 +347,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
{
|
||||
if (!repo.Tracking && model.Reference == null)
|
||||
throw new InvalidOperationException("Not on an updatable reference!");
|
||||
await repo.FetchOrigin(accessString, x => progressReporter(x / numFetches), cancellationToken).ConfigureAwait(false);
|
||||
await repo.FetchOrigin(currentModel.AccessUser, currentModel.AccessToken, x => progressReporter(x / numFetches), cancellationToken).ConfigureAwait(false);
|
||||
doneFetches = 1;
|
||||
if (!modelHasShaOrReference)
|
||||
{
|
||||
@@ -338,7 +359,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
lastRevisionInfo.OriginCommitSha = repo.Head;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//checkout/hard reset
|
||||
if (modelHasShaOrReference)
|
||||
{
|
||||
@@ -346,7 +367,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
|| (model.Reference != null && repo.Reference != model.Reference))
|
||||
{
|
||||
await repo.CheckoutObject(model.CheckoutSha ?? model.Reference, cancellationToken).ConfigureAwait(false);
|
||||
await LoadRevisionInformation(repo, null, x => lastRevisionInfo = x, cancellationToken).ConfigureAwait(false); //we've either seen origin before or what we're checking out is on origin
|
||||
await LoadRevisionInformation(repo, databaseContext, attachedInstance, null, x => lastRevisionInfo = x, cancellationToken).ConfigureAwait(false); //we've either seen origin before or what we're checking out is on origin
|
||||
}
|
||||
|
||||
if (model.UpdateFromOrigin == true && model.Reference != null)
|
||||
@@ -354,7 +375,8 @@ namespace Tgstation.Server.Host.Controllers
|
||||
if (!repo.Tracking)
|
||||
throw new InvalidOperationException("Checked out reference does not track a remote object!");
|
||||
await repo.ResetToOrigin(cancellationToken).ConfigureAwait(false);
|
||||
await LoadRevisionInformation(repo, null, x => lastRevisionInfo = x, cancellationToken).ConfigureAwait(false);
|
||||
await repo.Sychronize(currentModel.AccessUser, currentModel.AccessToken, true, cancellationToken).ConfigureAwait(false);
|
||||
await LoadRevisionInformation(repo, databaseContext, attachedInstance, null, x => lastRevisionInfo = x, cancellationToken).ConfigureAwait(false);
|
||||
//repo head is on origin so force this
|
||||
//will update the db if necessary
|
||||
lastRevisionInfo.OriginCommitSha = repo.Head;
|
||||
@@ -364,26 +386,21 @@ namespace Tgstation.Server.Host.Controllers
|
||||
//test merging
|
||||
if (newTestMerges)
|
||||
{
|
||||
var contextUser = new Models.User
|
||||
{
|
||||
Id = AuthenticationContext.User.Id
|
||||
};
|
||||
databaseContext.Users.Attach(contextUser);
|
||||
|
||||
var repoOwner = repo.GitHubOwner;
|
||||
var repoName = repo.GitHubRepoName;
|
||||
foreach (var I in model.NewTestMerges)
|
||||
{
|
||||
var prTask = gitHubClient.PullRequest.Get(repoOwner, repoName, I.Number);
|
||||
|
||||
var mergeResult = await repo.AddTestMerge(I.Number, I.PullRequestRevision, committerName, currentModel.CommitterEmail, accessString, x => progressReporter((x + 100 * doneFetches) / numFetches), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (!mergeResult.HasValue) //conflict, we don't care, dd already knows
|
||||
continue;
|
||||
|
||||
++doneFetches;
|
||||
|
||||
var revInfoUpdateTask = UpdateRevInfo();
|
||||
|
||||
Octokit.PullRequest pr = null;
|
||||
string errorMessage = null;
|
||||
try
|
||||
{
|
||||
pr = await prTask.ConfigureAwait(false);
|
||||
pr = await gitHubClient.PullRequest.Get(repoOwner, repoName, I.Number).ConfigureAwait(false);
|
||||
}
|
||||
catch (Octokit.RateLimitExceededException)
|
||||
{
|
||||
@@ -396,20 +413,27 @@ namespace Tgstation.Server.Host.Controllers
|
||||
errorMessage = "P.R.E. NOT FOUND";
|
||||
}
|
||||
|
||||
var mergeResult = await repo.AddTestMerge(I.Number, I.PullRequestRevision, committerName, currentModel.CommitterEmail, String.Format(CultureInfo.InvariantCulture, "Test merge of pull request #{0}{1}{2}", I.Number, I.Comment != null ? Environment.NewLine : null, I.Comment), currentModel.AccessUser, currentModel.AccessToken, x => progressReporter((x + 100 * doneFetches) / numFetches), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (!mergeResult.HasValue) //conflict, we don't care, dd already knows
|
||||
continue;
|
||||
|
||||
++doneFetches;
|
||||
|
||||
var revInfoUpdateTask = UpdateRevInfo();
|
||||
|
||||
var tm = new Models.TestMerge
|
||||
{
|
||||
Author = pr?.User.Login ?? errorMessage,
|
||||
BodyAtMerge = pr?.Body,
|
||||
BodyAtMerge = pr?.Body ?? errorMessage ?? String.Empty,
|
||||
MergedAt = DateTimeOffset.Now,
|
||||
TitleAtMerge = pr?.Title ?? errorMessage,
|
||||
TitleAtMerge = pr?.Title ?? errorMessage ?? String.Empty,
|
||||
Comment = I.Comment,
|
||||
Number = I.Number,
|
||||
MergedBy = AuthenticationContext.User,
|
||||
MergedBy = contextUser,
|
||||
PullRequestRevision = I.PullRequestRevision,
|
||||
Url = pr?.HtmlUrl ?? errorMessage
|
||||
};
|
||||
if (pr == null)
|
||||
tm.BodyAtMerge = errorMessage;
|
||||
|
||||
await revInfoUpdateTask.ConfigureAwait(false);
|
||||
|
||||
@@ -423,15 +447,17 @@ namespace Tgstation.Server.Host.Controllers
|
||||
|
||||
if (startSha != repo.Head)
|
||||
{
|
||||
await repo.Sychronize(accessString, ct).ConfigureAwait(false);
|
||||
await repo.Sychronize(currentModel.AccessUser, currentModel.AccessToken, false, ct).ConfigureAwait(false);
|
||||
await UpdateRevInfo().ConfigureAwait(false);
|
||||
}
|
||||
await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
|
||||
await databaseContext.Save(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//the stuff didn't make it into the db, forget what we've done and abort
|
||||
await repo.CheckoutObject(startSha, default).ConfigureAwait(false);
|
||||
await repo.CheckoutObject(startReference ?? startSha, default).ConfigureAwait(false);
|
||||
if (startReference != null && repo.Head != startSha)
|
||||
await repo.ResetToSha(startSha, default).ConfigureAwait(false);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Tgstation.Server.Api.Models;
|
||||
|
||||
namespace Tgstation.Server.Host.Models
|
||||
@@ -21,19 +22,19 @@ namespace Tgstation.Server.Host.Models
|
||||
/// </summary>
|
||||
[Required]
|
||||
public Instance Instance { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public Repository ToApi() => new Repository {
|
||||
public Repository ToApi() => new Repository
|
||||
{
|
||||
//AccessToken = AccessToken, //never show this
|
||||
AccessUser = AccessUser,
|
||||
AutoUpdatesKeepTestMerges = AutoUpdatesKeepTestMerges,
|
||||
AutoUpdatesSynchronize = AutoUpdatesSynchronize,
|
||||
CommitterEmail = CommitterEmail,
|
||||
CommitterName = CommitterName,
|
||||
//intentionally don't populate origin just in case
|
||||
PushTestMergeCommits = PushTestMergeCommits,
|
||||
//revision information and the rest retrieved by controller
|
||||
ShowTestMergeCommitters = ShowTestMergeCommitters
|
||||
//revision information and the rest retrieved by controller
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
|
||||
namespace Tgstation.Server.Host.Models
|
||||
@@ -14,6 +15,7 @@ namespace Tgstation.Server.Host.Models
|
||||
/// <summary>
|
||||
/// The <see cref="Models.Instance"/> the <see cref="RevisionInformation"/> belongs to
|
||||
/// </summary>
|
||||
[Required]
|
||||
public Instance Instance { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.DirectoryServices.AccountManagement;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -1658,7 +1658,93 @@
|
||||
],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n\t\"updateReference\": true\n}"
|
||||
"raw": "{\n\t\"updateFromOrigin\": true\n}"
|
||||
},
|
||||
"url": {
|
||||
"raw": "localhost:5000/Repository",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "5000",
|
||||
"path": [
|
||||
"Repository"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "Set access info",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [
|
||||
{
|
||||
"key": "Accept",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "User-Agent",
|
||||
"value": "Postman/1.0"
|
||||
},
|
||||
{
|
||||
"key": "User-Agent",
|
||||
"value": "Tgstation.Server.Api/4.0.0.0"
|
||||
},
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "InstanceId",
|
||||
"value": "1"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n\t\"accessUser\": \"Cyberboss\",\n\t\"accessToken\": \"this can be a password or personal access token, you should use the latter\"\n}"
|
||||
},
|
||||
"url": {
|
||||
"raw": "localhost:5000/Repository",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "5000",
|
||||
"path": [
|
||||
"Repository"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "Reset to origin",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [
|
||||
{
|
||||
"key": "Accept",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "User-Agent",
|
||||
"value": "Postman/1.0"
|
||||
},
|
||||
{
|
||||
"key": "User-Agent",
|
||||
"value": "Tgstation.Server.Api/4.0.0.0"
|
||||
},
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "InstanceId",
|
||||
"value": "1"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n\t\"updateFromOrigin\": true,\n\t\"reference\": \"master\"\n}"
|
||||
},
|
||||
"url": {
|
||||
"raw": "localhost:5000/Repository",
|
||||
@@ -1701,7 +1787,7 @@
|
||||
],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n\t\"updateReference\": true,\n\t\"reference\": \"master\",\n\t\"newTestMerges\": [\n\t\t{\n\t\t\t\"number\": 39476,\n\t\t\t\"pullRequestRevision\": \"11edfe5\"\n\t\t},\n\t\t{\n\t\t\t\"number\": 39469,\n\t\t\t\"pullRequestRevision\": \"ee4f00d\",\n\t\t\t\"comment\": \"babby's first pr\"\n\t\t}\n\t\t]\n}"
|
||||
"raw": "{\n\t\"updateFromOrigin\": true,\n\t\"reference\": \"master\",\n\t\"newTestMerges\": [\n\t\t{\n\t\t\t\"number\": 39514,\n\t\t\t\"pullRequestRevision\": \"28c6762\",\n\t\t\t\"comment\": \"babby's first pr\"\n\t\t},\n\t\t{\n\t\t\t\"number\": 39512,\n\t\t\t\"pullRequestRevision\": \"09be343791fd233444fb3985ef54496e277397f7\",\n\t\t\t\"comment\": \"gud boi antur\"\n\t\t}\n\t\t]\n}"
|
||||
},
|
||||
"url": {
|
||||
"raw": "localhost:5000/Repository",
|
||||
@@ -1805,6 +1891,56 @@
|
||||
],
|
||||
"_postman_isSubFolder": true
|
||||
},
|
||||
{
|
||||
"name": "Compiler",
|
||||
"description": "",
|
||||
"item": [
|
||||
{
|
||||
"name": "Read Info Copy",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [
|
||||
{
|
||||
"key": "Accept",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "User-Agent",
|
||||
"value": "Postman/1.0"
|
||||
},
|
||||
{
|
||||
"key": "User-Agent",
|
||||
"value": "Tgstation.Server.Api/4.0.0.0"
|
||||
},
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "InstanceId",
|
||||
"value": "1"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"id\": 1,\n \"online\": false\n}"
|
||||
},
|
||||
"url": {
|
||||
"raw": "localhost:5000/Repository",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "5000",
|
||||
"path": [
|
||||
"Repository"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
}
|
||||
],
|
||||
"_postman_isSubFolder": true
|
||||
},
|
||||
{
|
||||
"name": "Online Instance ID 1",
|
||||
"request": {
|
||||
|
||||
Reference in New Issue
Block a user