#!/usr/bin/env -S dotnet run #:package StudioWhy.Gitea.Net.API@1.25.0.2 using System.Net; using System.Text; using System.Text.RegularExpressions; using Gitea.Net.Api; using Gitea.Net.Client; using Gitea.Net.Extensions; using Gitea.Net.Model; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; string jsonInput = Environment.GetEnvironmentVariable("INPUTS") ?? "{}"; const string name = "Download Previous Artifacts"; Console.WriteLine($"::group::{name} - Inputs"); Console.WriteLine(jsonInput); Console.WriteLine("::endgroup::"); byte[] jsonBytes = Encoding.UTF8.GetBytes(jsonInput); using MemoryStream memoryStream = new(jsonBytes); string currentDir = Directory.GetCurrentDirectory(); IConfiguration configuration = new ConfigurationBuilder() .SetBasePath(currentDir) .AddJsonFile("appsettings.local.json", optional: true) .AddJsonStream(memoryStream) .AddEnvironmentVariables() .Build(); string host = configuration["host"] ?? string.Empty; string username = configuration["username"] ?? string.Empty; string password = configuration["password"] ?? string.Empty; string repoFullName = configuration["repoFullName"] ?? string.Empty; string[] repoParts = repoFullName.Split('/'); if (repoParts.Length != 2) { throw new ArgumentException("Invalid repository full name format. Expected 'owner/repo'."); } string repoOwner = repoParts[0]; string repoName = repoParts[1]; string workflowPattern = configuration["workflowPattern"] ?? "*"; Regex workflowRegex = WildcardToRegex(workflowPattern); string branchPattern = configuration["branchPattern"] ?? "*"; Regex branchRegex = WildcardToRegex(branchPattern); string artifactPattern = configuration["artifactPattern"] ?? "*"; Regex artifactRegex = WildcardToRegex(artifactPattern); string unzipDir = configuration["unzipDir"] ?? string.Empty; if (!string.IsNullOrEmpty(unzipDir) && !Path.IsPathFullyQualified(unzipDir)) { unzipDir = Path.Combine(currentDir, unzipDir); } bool.TryParse(configuration["deleteAfterUnzip"], out bool deleteAfterUnzip); // Configure services ServiceCollection services = new(); services.AddApi(o => { BasicToken basicToken = new(username, password); o.AddTokens(basicToken); }); UriBuilder hostUriBuilder = new(host); hostUriBuilder.Path = "/api/v1"; HttpClientHandler httpClientHandler = new() { AllowAutoRedirect = false, }; using HttpClient httpClient = new(httpClientHandler, true) { BaseAddress = hostUriBuilder.Uri, }; services.AddLogging(configure => configure.AddConsole()); services.AddSingleton(httpClient); services.AddSingleton(); ServiceProvider serviceProvider = services.BuildServiceProvider(); RepositoryApi repositoryApi = serviceProvider.GetRequiredService(); static Regex WildcardToRegex(string pattern, RegexOptions options = RegexOptions.IgnoreCase) { string regexString = "^" + Regex.Escape(pattern) .Replace(@"\*", ".*") .Replace(@"\?", ".") + "$"; return new(regexString, options); } Console.WriteLine($"Retrieving workflow runs for repository: {repoOwner}/{repoName} with pattern: {workflowPattern}"); IGetWorkflowRunsApiResponse getWorkflowRunsApiResponse = await repositoryApi.GetWorkflowRunsOrDefaultAsync(repoOwner, repoName, status: "success", page: 1, cancellationToken: CancellationToken.None); if (!getWorkflowRunsApiResponse.TryOk(out ActionWorkflowRunsResponse workflowRunResponse)) { Console.WriteLine("Failed to retrieve workflow runs."); return 1; } bool WorkflowMatchesBranch(ActionWorkflowRun workflowRun) { string[] pathParts = workflowRun.Path.Split('@'); if (pathParts.Length < 2) return false; string workflowName = pathParts[0]; string branch = pathParts[1]; return workflowRegex.IsMatch(workflowName) && branchRegex.IsMatch(branch); } ActionWorkflowRun? actionWorkflowRun = workflowRunResponse.WorkflowRuns.FirstOrDefault(WorkflowMatchesBranch); if (actionWorkflowRun is null) { Console.WriteLine("No matching workflow run found."); return 1; } IGetArtifactsOfRunApiResponse artifacts = await repositoryApi.GetArtifactsOfRunOrDefaultAsync(repoOwner, repoName, (int)actionWorkflowRun.Id!, string.Empty, CancellationToken.None); if (!artifacts.TryOk(out ActionArtifactsResponse artifactsResponse)) { Console.WriteLine("Failed to retrieve artifacts."); return 1; } ActionArtifact[] artifactsToDownload = artifactsResponse.Artifacts.Where(a => artifactRegex.IsMatch(a.Name)).ToArray(); if (artifactsToDownload.Length is 0) { Console.WriteLine("No artifacts found for the specified workflow run."); return 1; } StringBuilder namesBuilder = new(); namesBuilder.AppendLine("downloadedArtifactNames<