diff --git a/Apps.GitLab/Actions/CommitActions.cs b/Apps.GitLab/Actions/CommitActions.cs index 837a8d4..ccf3fd0 100644 --- a/Apps.GitLab/Actions/CommitActions.cs +++ b/Apps.GitLab/Actions/CommitActions.cs @@ -1,4 +1,5 @@ using Apps.Gitlab.Actions.Base; +using Apps.Gitlab.Extensions; using Apps.Gitlab.Models.Branch.Requests; using Apps.Gitlab.Models.Commit.Requests; using Apps.Gitlab.Models.Respository.Requests; @@ -7,29 +8,28 @@ using Apps.GitLab.Dtos; using Apps.GitLab.Models.Commit.Requests; using Apps.GitLab.Models.Commit.Responses; -using Apps.GitLab.Models.Respository.Requests; +using Apps.GitLab.Utils.File; using Blackbird.Applications.Sdk.Common; using Blackbird.Applications.Sdk.Common.Actions; using Blackbird.Applications.Sdk.Common.Exceptions; using Blackbird.Applications.Sdk.Common.Invocation; -using Blackbird.Applications.Sdk.Utils.Extensions.Files; using Blackbird.Applications.SDK.Extensions.FileManagement.Interfaces; +using Blackbird.Filters.Constants; +using Blackbird.Filters.Enums; +using Blackbird.Filters.Extensions; +using Blackbird.Filters.Transformations; using GitLabApiClient.Models.Commits.Responses; +using GitLabApiClient.Models.Projects.Responses; using RestSharp; +using System.Net; namespace Apps.Gitlab.Actions; [ActionList("Commit")] -public class CommitActions : GitLabActions +public class CommitActions(InvocationContext invocationContext, IFileManagementClient fileManagementClient) + : GitLabActions(invocationContext) { private const int CommitsPageSize = 100; - private readonly IFileManagementClient _fileManagementClient; - - public CommitActions(InvocationContext invocationContext, IFileManagementClient fileManagementClient) - : base(invocationContext) - { - _fileManagementClient = fileManagementClient; - } [Action("Search commits", Description = "Search commits in a repository")] public async Task ListRepositoryCommits( @@ -202,67 +202,115 @@ public async Task ListAddedOrModifiedInHours }; } - [Action("Create or update file", Description = "Create file or update existing file in a repository")] - public async Task PushFile( + [Action("Upload file", Description = "Create file or update existing file in a repository")] + public async Task PushFile( [ActionParameter] GetRepositoryRequest repositoryRequest, [ActionParameter] GetOptionalBranchRequest branchRequest, [ActionParameter] PushFileRequest input) { var projectId = ParseProjectId(repositoryRequest.RepositoryId); + var repository = await RestClient.GetProject(projectId); + var branch = branchRequest.Name ?? repository.DefaultBranch; + + var action = await CheckFileExists(projectId, input.DestinationFilePath, branch) + ? GitLabCommitActions.Update + : GitLabCommitActions.Create; + + return await CommitFile(repository, branch, input, action); + } - var repContent = - await new RepositoryActions(InvocationContext, _fileManagementClient).ListRepositoryContent( - repositoryRequest, branchRequest, new FolderContentWithTypeRequest { IncludeSubfolders = true }); + [Action("Update file", Description = "Update existing file in a repository")] + public async Task UpdateFile( + [ActionParameter] GetRepositoryRequest repositoryRequest, + [ActionParameter] GetOptionalBranchRequest branchRequest, + [ActionParameter] PushFileRequest input) + { + var projectId = ParseProjectId(repositoryRequest.RepositoryId); + var repository = await RestClient.GetProject(projectId); + var branch = branchRequest.Name ?? repository.DefaultBranch; + + var fileExists = await CheckFileExists(projectId, input.DestinationFilePath, branch); + if (!fileExists) + throw new PluginMisconfigurationException("File does not exist"); + + return await CommitFile(repository, branch, input, GitLabCommitActions.Update); + } + + private async Task CommitFile( + Project repository, + string branch, + PushFileRequest input, + string action) + { + int projectId = repository.Id; + var fileStream = await fileManagementClient.DownloadAsync(input.File); + var transformationResult = Transformation.Load(fileStream, input.File.Name, input.File.ContentType); - if (repContent.Content.Where(x => x.Type == GitLabItemTypes.Blob).Any(p => p.Path == input.DestinationFilePath)) + string? content = null; + var contentResult = transformationResult.Target(); + if (contentResult.Success) { - return await UpdateFile( - repositoryRequest, - branchRequest, - new PushFileRequest - { - DestinationFilePath = input.DestinationFilePath, - File = input.File, - CommitMessage = input.CommitMessage - }); + content = contentResult.Value.ToStream(MetadataHandling.Exclude).ReadString(); } - - if (repContent.Content.Where(x => x.Type == GitLabItemTypes.Tree).Select(x => x.Path) - .Contains(input.DestinationFilePath.Trim('/'))) + else { - throw new PluginMisconfigurationException("Destination file path is invalid!"); + InvocationContext.Logger?.LogInformation($"Not a Blackbird interoperable file: {transformationResult.Error}", []); + content = fileStream.ReadString(); } - var file = await _fileManagementClient.DownloadAsync(input.File); - var fileBytes = await file.GetByteData(); - var pushFileResult = await RestClient.PushChanges(projectId, branchRequest.Name, input.CommitMessage, - input.DestinationFilePath, fileBytes, GitLabCommitActions.Create); + var pushResult = await RestClient.PushChanges( + projectId, + branch, + input.CommitMessage, + input.DestinationFilePath, + System.Text.Encoding.UTF8.GetBytes(content), + action); + + var commitDto = new CommitDto(pushResult); - return new(pushFileResult); - } + if (!transformationResult.Success) + return new(commitDto, input.File); - [Action("Update file", Description = "Update existing file in a repository")] - public async Task UpdateFile( - [ActionParameter] GetRepositoryRequest repositoryRequest, - [ActionParameter] GetOptionalBranchRequest branchRequest, - [ActionParameter] PushFileRequest input) - { - var projectId = ParseProjectId(repositoryRequest.RepositoryId); + var (blobUrl, editUrl) = TransformationExtensions.BuildUrls(input.DestinationFilePath, branch, RestClient.BaseUrl); + + var transformation = transformationResult.Value; + transformation.TargetSystemReference.ContentName = input.File.Name; + transformation.TargetSystemReference.AdminUrl = editUrl; + transformation.TargetSystemReference.SystemName = "Gitlab"; + transformation.TargetSystemReference.SystemRef = "https://gitlab.com/"; - var repContent = - await new RepositoryActions(InvocationContext, _fileManagementClient).ListRepositoryContent( - repositoryRequest, branchRequest, - new FolderContentWithTypeRequest { IncludeSubfolders = true, ContentType = GitLabItemTypes.Blob }); + if (transformationResult.WasBilingual) + { + var transformedFile = await fileManagementClient.UploadAsync( + transformation.ToStream(), + MediaTypes.Xliff2, + transformation.BilingualFileName); + + return new(commitDto, transformedFile); + } + + var targetResult = transformation.Target(); + if (!targetResult.Success) throw new PluginMisconfigurationException(targetResult.Error); - if (!repContent.Content.Select(x => x.Path).Contains(input.DestinationFilePath.Trim('/'))) - throw new PluginApplicationException("File does not exist by specified file path!"); + var target = targetResult.Value; + target.SystemReference = transformation.TargetSystemReference; - var file = await _fileManagementClient.DownloadAsync(input.File); - var fileBytes = await file.GetByteData(); - var fileUpload = await RestClient.PushChanges(projectId, branchRequest.Name, input.CommitMessage, - input.DestinationFilePath, fileBytes, GitLabCommitActions.Update); + var targetFile = await fileManagementClient.UploadAsync( + target.ToStream(), + target.OriginalMediaType, + target.OriginalName); - return new(fileUpload); + return new(commitDto, targetFile); + + } + + public async Task CheckFileExists(int projectId, string filePath, string branch) + { + var endpoint = $"/projects/{projectId}/repository/files/{Uri.EscapeDataString(filePath.Trim('/'))}"; + var request = RestClient.CreateRequest(endpoint, Method.Head).AddQueryParameter("ref", branch); + + var response = await RestClient.ExecuteWithErrorHandling(request, HttpStatusCode.NotFound); + return response.IsSuccessStatusCode; } [Action("Delete file", Description = "Delete file from a repository")] diff --git a/Apps.GitLab/Actions/RepositoryActions.cs b/Apps.GitLab/Actions/RepositoryActions.cs index 74510be..4e8d8ac 100644 --- a/Apps.GitLab/Actions/RepositoryActions.cs +++ b/Apps.GitLab/Actions/RepositoryActions.cs @@ -11,7 +11,6 @@ using Blackbird.Applications.Sdk.Common; using Blackbird.Applications.Sdk.Common.Actions; using Blackbird.Applications.Sdk.Common.Exceptions; -using Blackbird.Applications.Sdk.Common.Files; using Blackbird.Applications.Sdk.Common.Invocation; using Blackbird.Applications.Sdk.Utils.Extensions.Files; using Blackbird.Applications.Sdk.Utils.Extensions.Http; @@ -21,20 +20,14 @@ using GitLabApiClient.Models.Trees.Responses; using RestSharp; using System.Net.Mime; +using Apps.GitLab.Utils.File; namespace Apps.Gitlab.Actions; [ActionList("Repository")] -public class RepositoryActions : GitLabActions +public class RepositoryActions(InvocationContext invocationContext, IFileManagementClient fileManagementClient) + : GitLabActions(invocationContext) { - private readonly IFileManagementClient _fileManagementClient; - - public RepositoryActions(InvocationContext invocationContext, IFileManagementClient fileManagementClient) - : base(invocationContext) - { - _fileManagementClient = fileManagementClient; - } - [Action("Create new repository", Description = "Create repository with selected settings")] public async Task CreateRepository([ActionParameter] CreateRepositoryInput input) { @@ -50,39 +43,30 @@ public async Task CreateRepository([ActionParameter] CreateR return RepositoryResponse.FromProject(project); } - [Action("Get repository file", Description = "Get file from a repository by file path")] + [Action("Download file", Description = "Download a file from a repository by file path")] public async Task GetFile( [ActionParameter] GetRepositoryRequest repositoryRequest, [ActionParameter] GetOptionalBranchRequest branchRequest, [ActionParameter] GetFileRequest getFileRequest) { var projectId = ParseProjectId(repositoryRequest.RepositoryId); - var repository = await GetProject(projectId); + var repository = await RestClient.GetProject(projectId); var branch = branchRequest.Name ?? repository.DefaultBranch; - var request = RestClient.CreateRequest( - $"/projects/{projectId}/repository/files/{Uri.EscapeDataString(getFileRequest.FilePath)}", - Method.Get); - request.AddQueryParameter("ref", branch); - - var fileData = await RestClient.ExecuteWithErrorHandling(request); - if (fileData == null) - throw new PluginMisconfigurationException($"File does not exist ({getFileRequest.FilePath})"); - - var filename = Path.GetFileName(getFileRequest.FilePath); - if (!MimeTypes.TryGetMimeType(filename, out var mimeType)) - mimeType = MediaTypeNames.Application.Octet; - - FileReference file; - using (var stream = new MemoryStream(Convert.FromBase64String(fileData.Content))) - { - file = await _fileManagementClient.UploadAsync(stream, mimeType, filename); - } - + var fileInfo = await RestClient.GetFileInfo(projectId, getFileRequest.FilePath, branch); + var fileToProcess = new DownloadedFile( + fileInfo.Content, + getFileRequest.FilePath, + repository.WebUrl, + branch, + RestClient.BaseUrl); + var fileData = FileHelper.ProcessDownloadedFile(fileToProcess, InvocationContext.Logger, getFileRequest.LanguageCode, getFileRequest.ContentId); + + var fileReference = await fileManagementClient.UploadAsync(fileData.FileStream, fileData.MimeType, fileData.FileName); return new GetFileResponse { FilePath = getFileRequest.FilePath, - File = file, + File = fileReference, FileExtension = Path.GetExtension(getFileRequest.FilePath) }; } @@ -132,7 +116,7 @@ public async Task GetAllFilesInFolder( if (!MimeTypes.TryGetMimeType(filename, out var mimeType)) mimeType = MediaTypeNames.Application.Octet; - var uploadedFile = await _fileManagementClient.UploadAsync(file.FileStream, mimeType, filename); + var uploadedFile = await fileManagementClient.UploadAsync(file.FileStream, mimeType, filename); resultFiles.Add(new GitLabFile { File = uploadedFile, @@ -146,7 +130,7 @@ public async Task GetAllFilesInFolder( [Action("Get repository", Description = "Get repository details")] public async Task GetRepositoryById([ActionParameter] GetRepositoryRequest input) { - var project = await GetProject(ParseProjectId(input.RepositoryId)); + var project = await RestClient.GetProject(ParseProjectId(input.RepositoryId)); return RepositoryResponse.FromProject(project); } @@ -249,10 +233,4 @@ public async Task BranchExists( var branches = await RestClient.ExecuteWithErrorHandling>(request); return branches.Any(x => x.Name == branchNameRequest); } - - private Task GetProject(int projectId) - { - var request = RestClient.CreateRequest($"/projects/{projectId}", Method.Get); - return RestClient.ExecuteWithErrorHandling(request); - } } diff --git a/Apps.GitLab/Apps.GitLab.csproj b/Apps.GitLab/Apps.GitLab.csproj index 274984d..8e195fe 100644 --- a/Apps.GitLab/Apps.GitLab.csproj +++ b/Apps.GitLab/Apps.GitLab.csproj @@ -6,7 +6,7 @@ enable GitLab GitLab is a developer platform that allows developers to create, store, and manage their code. This app focuses on connecting repository events and file actions into the Blackbird ecosystem. - 1.0.14 + 1.0.16 Apps.GitLab @@ -14,6 +14,7 @@ + @@ -25,6 +26,12 @@ - + + + + + README.md + Always + diff --git a/Apps.GitLab/BlackbirdGitLabClient.cs b/Apps.GitLab/BlackbirdGitLabClient.cs index 72a3264..3c80220 100644 --- a/Apps.GitLab/BlackbirdGitLabClient.cs +++ b/Apps.GitLab/BlackbirdGitLabClient.cs @@ -1,14 +1,17 @@ +using System.Net; using Apps.GitLab.Constants; using Apps.GitLab.Dtos; using Apps.Gitlab.Constants; +using Apps.GitLab.Models.Respository.Responses; using Blackbird.Applications.Sdk.Common.Authentication; using Blackbird.Applications.Sdk.Common.Exceptions; using Blackbird.Applications.Sdk.Utils.Extensions.Sdk; using Blackbird.Applications.Sdk.Utils.Extensions.String; using Blackbird.Applications.Sdk.Utils.RestSharp; -using GitLabApiClient.Models.Commits.Responses; +using GitLabApiClient.Models.Projects.Responses; using Newtonsoft.Json; using RestSharp; +using Commit = GitLabApiClient.Models.Commits.Responses.Commit; namespace Apps.Gitlab; @@ -30,6 +33,15 @@ public BlackbirdGitlabClient(IEnumerable auth _authenticationCredentials = authenticationCredentialsProviders; BaseUrl = GetBaseUrl(authenticationCredentialsProviders); } + + public async Task ExecuteWithErrorHandling(RestRequest request, params HttpStatusCode[] allowedStatuses) + { + var response = await ExecuteAsync(request); + if (response.IsSuccessStatusCode || allowedStatuses.Contains(response.StatusCode)) + return response; + + throw ConfigureErrorException(response); + } public static string GetBaseUrl(IEnumerable creds) { @@ -53,6 +65,20 @@ public async Task ExecuteForBytesWithErrorHandling(RestRequest request) return response.RawBytes ?? []; } + + public async Task GetProject(int projectId) + { + var request = CreateRequest($"/projects/{projectId}", Method.Get); + return await ExecuteWithErrorHandling(request); + } + + public async Task GetFileInfo(int projectId, string filePath, string branch) + { + string endpoint = $"/projects/{projectId}/repository/files/{Uri.EscapeDataString(filePath)}"; + var request = CreateRequest(endpoint, Method.Get).AddQueryParameter("ref", branch); + + return await ExecuteWithErrorHandling(request); + } public async Task GetArchive(int projectId, string? branchName) { @@ -65,13 +91,12 @@ public async Task GetArchive(int projectId, string? branchName) public async Task PushChanges(int projectId, string? branchName, string commitMessage, string filePath, byte[]? file, string action) { - var repository = await ExecuteWithErrorHandling( - CreateRequest($"/projects/{projectId}", Method.Get)); + var branch = string.IsNullOrWhiteSpace(branchName) ? (await GetProject(projectId)).DefaultBranch : branchName; var request = CreateRequest($"/projects/{projectId}/repository/commits", Method.Post); request.AddJsonBody(new { - branch = branchName ?? repository.DefaultBranch, + branch, commit_message = commitMessage, actions = new[] { diff --git a/Apps.GitLab/Extensions/TransformationExtensions.cs b/Apps.GitLab/Extensions/TransformationExtensions.cs new file mode 100644 index 0000000..00b755c --- /dev/null +++ b/Apps.GitLab/Extensions/TransformationExtensions.cs @@ -0,0 +1,12 @@ +using Blackbird.Filters.Transformations; + +namespace Apps.Gitlab.Extensions; + +public static class TransformationExtensions +{ + public static (string blobUrl, string editUrl) BuildUrls(string filePath, string branchName, string repoWebUrl) + { + var encodedPath = string.Join("/", filePath.Split('/').Select(Uri.EscapeDataString)); + return ($"{repoWebUrl}/-/blob/{branchName}/{encodedPath}", $"{repoWebUrl}/-/edit/{branchName}/{encodedPath}"); + } +} \ No newline at end of file diff --git a/Apps.GitLab/Models/Commit/Responses/UploadFileResponse.cs b/Apps.GitLab/Models/Commit/Responses/UploadFileResponse.cs new file mode 100644 index 0000000..d94fd60 --- /dev/null +++ b/Apps.GitLab/Models/Commit/Responses/UploadFileResponse.cs @@ -0,0 +1,6 @@ +using Apps.GitLab.Dtos; +using Blackbird.Applications.Sdk.Common.Files; + +namespace Apps.GitLab.Models.Commit.Responses; + +public record UploadFileResponse(CommitDto Commit, FileReference File); \ No newline at end of file diff --git a/Apps.GitLab/Models/Respository/Requests/GetFileRequest.cs b/Apps.GitLab/Models/Respository/Requests/GetFileRequest.cs index af7ee36..7fdee25 100644 --- a/Apps.GitLab/Models/Respository/Requests/GetFileRequest.cs +++ b/Apps.GitLab/Models/Respository/Requests/GetFileRequest.cs @@ -9,4 +9,10 @@ public class GetFileRequest [Display("File path")] [FileDataSource(typeof(FilePickerDataHandler))] public string FilePath { get; set; } + + [Display("Source language code", Description = "The language of the file used in later Actions.")] + public string? LanguageCode { get; set; } + + [Display("Content ID", Description = "The ID of the content, used by Blacklake when diffing.")] + public string? ContentId { get; set; } } diff --git a/Apps.GitLab/Models/Respository/Responses/RepositoryFileResponse.cs b/Apps.GitLab/Models/Respository/Responses/RepositoryFileResponse.cs index cad7760..8ac1f1c 100644 --- a/Apps.GitLab/Models/Respository/Responses/RepositoryFileResponse.cs +++ b/Apps.GitLab/Models/Respository/Responses/RepositoryFileResponse.cs @@ -1,7 +1,18 @@ -namespace Apps.GitLab.Models.Respository.Responses; +using Newtonsoft.Json; + +namespace Apps.GitLab.Models.Respository.Responses; public class RepositoryFileResponse { + [JsonProperty("content")] public string Content { get; set; } = string.Empty; + + [JsonProperty("file_path")] + public string FilePath { get; set; } = string.Empty; + + [JsonProperty("file_name")] + public string FileName { get; set; } = string.Empty; + + } diff --git a/Apps.GitLab/Utils/File/DownloadedFile.cs b/Apps.GitLab/Utils/File/DownloadedFile.cs new file mode 100644 index 0000000..1c3918d --- /dev/null +++ b/Apps.GitLab/Utils/File/DownloadedFile.cs @@ -0,0 +1,3 @@ +namespace Apps.GitLab.Utils.File; + +public record DownloadedFile(string Content, string Path, string RepoWebUrl, string BranchName, string BaseUrl); \ No newline at end of file diff --git a/Apps.GitLab/Utils/File/FileHelper.cs b/Apps.GitLab/Utils/File/FileHelper.cs new file mode 100644 index 0000000..114275d --- /dev/null +++ b/Apps.GitLab/Utils/File/FileHelper.cs @@ -0,0 +1,41 @@ +using Apps.Gitlab.Extensions; +using Blackbird.Applications.Sdk.Common.Exceptions; +using Blackbird.Applications.Sdk.Common.Invocation; +using Blackbird.Applications.Sdk.Utils.Extensions.Files; +using Blackbird.Filters.Enums; +using Blackbird.Filters.Transformations; +using System.Net.Mime; + +namespace Apps.GitLab.Utils.File; + +public static class FileHelper +{ + public static ProcessedDownloadedFile ProcessDownloadedFile(DownloadedFile downloadedFile, Logger? logger, string? language, string? contentId) + { + var filename = Path.GetFileName(downloadedFile.Path); + if (!MimeTypes.TryGetMimeType(filename, out var mimeType)) + mimeType = MediaTypeNames.Application.Octet; + + var stream = new MemoryStream(Convert.FromBase64String(downloadedFile.Content)); + var fileResult = Transformation.Load(stream, filename, mimeType).Source(); + + if (!fileResult.Success) + { + stream.Position = 0; + logger?.LogInformation($"Not a Blackbird interoperable file: {fileResult.Error}", []); + return new(stream, mimeType, filename); + } + + var fileContent = fileResult.Value; + var (blobUrl, editUrl) = TransformationExtensions.BuildUrls(downloadedFile.Path, downloadedFile.BranchName, downloadedFile.RepoWebUrl); + + fileContent.Language = language; + fileContent.SystemReference.ContentId = contentId; + fileContent.SystemReference.AdminUrl = editUrl; + fileContent.SystemReference.ContentName = filename; + fileContent.SystemReference.SystemName = "Gitlab"; + fileContent.SystemReference.SystemRef = "https://gitlab.com/"; + + return new(fileContent.ToStream(), mimeType, filename); + } +} \ No newline at end of file diff --git a/Apps.GitLab/Utils/File/ProcessedDownloadedFile.cs b/Apps.GitLab/Utils/File/ProcessedDownloadedFile.cs new file mode 100644 index 0000000..ab186b2 --- /dev/null +++ b/Apps.GitLab/Utils/File/ProcessedDownloadedFile.cs @@ -0,0 +1,3 @@ +namespace Apps.GitLab.Utils.File; + +public record ProcessedDownloadedFile(Stream FileStream, string MimeType, string FileName); \ No newline at end of file diff --git a/Apps.GitLab/Utils/File/ProcessedUploadedFile.cs b/Apps.GitLab/Utils/File/ProcessedUploadedFile.cs new file mode 100644 index 0000000..dc760aa --- /dev/null +++ b/Apps.GitLab/Utils/File/ProcessedUploadedFile.cs @@ -0,0 +1,5 @@ +using Blackbird.Filters.Transformations; + +namespace Apps.GitLab.Utils.File; + +public record ProcessedUploadedFile(byte[] FileBytes, Transformation? Transformation); \ No newline at end of file diff --git a/Apps.GitLab/Utils/File/UploadedFile.cs b/Apps.GitLab/Utils/File/UploadedFile.cs new file mode 100644 index 0000000..c6b4655 --- /dev/null +++ b/Apps.GitLab/Utils/File/UploadedFile.cs @@ -0,0 +1,3 @@ +namespace Apps.GitLab.Utils.File; + +public record UploadedFile(Stream Stream, string Name, string ContentType); \ No newline at end of file diff --git a/README.md b/README.md index 55255f9..2a12207 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ If your GitLab instance is hosted on a custom domain, use the **OAuth Self-manag - **Enable printing merge request link**: Option to print merge request links. - **CI config path**: CI config file path. - **Initialize with README**: Option to create an initial README file. -- **Get repository file** Get file from a repository by file path. +- **Download file** Download a file from a repository by file path. Advanced settings: - **Branch name**: Branch to use instead of the default branch. - **Get all files in folder** Get files from a repository folder. @@ -121,7 +121,7 @@ If your GitLab instance is hosted on a custom domain, use the **OAuth Self-manag - **List added or modified files in X hours** Search files added or modified during specified number of hours. Advanced settings: - **Path pattern**: Use forward slash '/' to represent directory separator. Use '*' to represent wildcards in file and directory names. Use '**' to represent arbitrary directory depth. -- **Create or update file** Create file or update existing file in a repository. +- **Upload file** Create file or update existing file in a repository. - **Update file** Update existing file in a repository. - **Delete file** Delete file from a repository. diff --git a/Tests.GitLab/CommitActionTests.cs b/Tests.GitLab/CommitActionTests.cs index ff34a13..d8f5aa0 100644 --- a/Tests.GitLab/CommitActionTests.cs +++ b/Tests.GitLab/CommitActionTests.cs @@ -2,7 +2,9 @@ using Apps.Gitlab.Models.Branch.Requests; using Apps.Gitlab.Models.Respository.Requests; using Apps.GitLab.Constants; +using Apps.Gitlab.Models.Commit.Requests; using Apps.GitLab.Models.Commit.Requests; +using Blackbird.Applications.Sdk.Common.Files; using Blackbird.Applications.Sdk.Common.Invocation; using Tests.GitLab.Base; @@ -195,4 +197,27 @@ public async Task FindCommit_WithCommitBeforeExactBoundary_ExcludesBoundaryCommi Assert.AreEqual("9e41fdbe88e1a2099db6dd31c769267a2bf420f3", result.Id); } + + [TestMethod, ContextDataSource(ConnectionTypes.OAuth)] + public async Task PushFile_WithValidFile_ReturnsUploadResponse(InvocationContext context) + { + // Arrange + string fileName = "ja-JP.test.html"; + var actions = new CommitActions(context, FileManagementClient); + var repoRequest = new GetRepositoryRequest { RepositoryId = "84026361" }; + var branchRequest = new GetOptionalBranchRequest { }; + var pushFileInput = new PushFileRequest + { + CommitMessage = "test from tests", + DestinationFilePath = fileName, + File = new FileReference { Name = fileName } + }; + + // Act + var result = await actions.PushFile(repoRequest, branchRequest, pushFileInput); + + // Assert + PrintResult(result); + Assert.IsNotNull(result); + } } diff --git a/Tests.GitLab/RepositoryActionTests.cs b/Tests.GitLab/RepositoryActionTests.cs index 2e5ce75..a96e12e 100644 --- a/Tests.GitLab/RepositoryActionTests.cs +++ b/Tests.GitLab/RepositoryActionTests.cs @@ -1,6 +1,7 @@ using Apps.Gitlab.Actions; using Apps.Gitlab.Models.Respository.Requests; using Apps.GitLab.Constants; +using Apps.Gitlab.Models.Branch.Requests; using Apps.GitLab.Models.Respository.Requests; using Blackbird.Applications.Sdk.Common.Invocation; using Tests.GitLab.Base; @@ -37,5 +38,22 @@ public async Task CreateRepository_WithExistingRepository_ReturnsRepository(Invo Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(result, Newtonsoft.Json.Formatting.Indented)); Assert.IsNotNull(result); } + + [TestMethod, ContextDataSource(ConnectionTypes.OAuth)] + public async Task GetFile_WithExistingFile_ReturnsFile(InvocationContext context) + { + // Arrange + var action = new RepositoryActions(context, FileManagementClient); + var repoRequest = new GetRepositoryRequest { RepositoryId = "84026361" }; + var branchRequest = new GetOptionalBranchRequest { }; + var fileRequest = new GetFileRequest { FilePath = "uk-UA.test.html" }; + + // Act + var result = await action.GetFile(repoRequest, branchRequest, fileRequest); + + // Assert + PrintResult(result); + Assert.IsNotNull(result); + } }