mirror of
https://git.stillkill.net/Stillkill/GiteaPublish.git
synced 2026-10-22 05:32:18 +01:00
Workflow test
This commit is contained in:
1 parent
518159ea7f
commit
ef25216552
17 files changed
+876
-25
No files matched your search
@@ -0,0 +1,72 @@
|
|||||||
|
name: Build Arch Package
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: archlinux:latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Arch build environment
|
||||||
|
run: |
|
||||||
|
pacman -Syu --noconfirm
|
||||||
|
pacman -S --noconfirm base-devel dotnet-sdk git
|
||||||
|
#will need this later for uploading the package
|
||||||
|
dotnet publish -c Release -r linux-x64 --self-contained \
|
||||||
|
-p:PublishSingleFile=true \
|
||||||
|
-p:PublishReadyToRun=true \
|
||||||
|
-p:UseAppHost=true \
|
||||||
|
-p:DebugType=embedded \
|
||||||
|
-o "/usr/local/bin" GiteaPublish
|
||||||
|
|
||||||
|
- name: Get application version
|
||||||
|
id: get_version
|
||||||
|
run: |
|
||||||
|
VERSION=$(dotnet run -v q --property WarningLevel=0 --project GiteaPublish -- --version)
|
||||||
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||||
|
echo "Application version: $VERSION"
|
||||||
|
|
||||||
|
- name: Prepare PKGBUILD
|
||||||
|
run: |
|
||||||
|
cd GiteaPublish
|
||||||
|
sed -i "s/<PKG-VER>/${{ steps.get_version.outputs.version }}/g" PKGBUILD
|
||||||
|
cat PKGBUILD
|
||||||
|
|
||||||
|
- name: Build Arch package
|
||||||
|
run: |
|
||||||
|
cd GiteaPublish
|
||||||
|
pwd
|
||||||
|
useradd -m builder
|
||||||
|
chown -R builder:builder .
|
||||||
|
echo "builder ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
|
||||||
|
su builder -c "makepkg -s --noconfirm"
|
||||||
|
|
||||||
|
- name: List built packages
|
||||||
|
run: |
|
||||||
|
cd GiteaPublish
|
||||||
|
pwd
|
||||||
|
ls -lah *.pkg.tar.zst
|
||||||
|
echo "package_file=$(ls *.pkg.tar.zst | head -n 1)" >> $GITHUB_OUTPUT
|
||||||
|
id: package_info
|
||||||
|
|
||||||
|
- name: Upload Arch package artifact
|
||||||
|
run: |
|
||||||
|
#I used the package to upload the package
|
||||||
|
GiteaPublish \
|
||||||
|
package arch publish --username ${{ secrets.USERNAME }} --password ${{ secrets.PASSWORD }} \
|
||||||
|
-b https://git.stillkill.net -o Stillkill -r GiteaPublish -f "GiteaPublish/${{ steps.package_info.outputs.package_file }}"
|
||||||
|
|
||||||
|
|
||||||
|
- name: Display package info
|
||||||
|
run: |
|
||||||
|
echo "Built package version: ${{ steps.get_version.outputs.version }}"
|
||||||
|
echo "Package file: ${{ steps.package_info.outputs.package_file }}"
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace GiteaPublish;
|
||||||
|
|
||||||
|
public static class ApplicationVersion
|
||||||
|
{
|
||||||
|
public static string Version
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Assembly? assembly = Assembly.GetEntryAssembly();
|
||||||
|
AssemblyName? assemblyName = assembly?.GetName();
|
||||||
|
Version? version = assemblyName?.Version;
|
||||||
|
return version?.ToString() ?? "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using GiteaPublish.Gitea;
|
||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace GiteaPublish.Commands;
|
||||||
|
|
||||||
|
public class AuthSettings : CommandSettings
|
||||||
|
{
|
||||||
|
[CommandOption("--username <USERNAME>")]
|
||||||
|
[Description("Username for authentication. Required if --auth-file is not used.")]
|
||||||
|
public string? Username { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("--password <PASSWORD>")]
|
||||||
|
[Description("Password or token for authentication. Required if --auth-file is not used.")]
|
||||||
|
public string? Password { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("--auth-file <AUTH_FILE>")]
|
||||||
|
[Description("Path to a file containing username and password/token on separate lines. Overrides --username and --password if provided.")]
|
||||||
|
public string? AuthFile { get; set; }
|
||||||
|
|
||||||
|
public BasicAuthModel GetAuth()
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(AuthFile))
|
||||||
|
{
|
||||||
|
string[] lines = File.ReadAllLines(AuthFile);
|
||||||
|
if (lines.Length < 2) {
|
||||||
|
AnsiConsole.MarkupLine("[red]Auth file must contain at least two lines: username on the first line and password on the second line.[/]");
|
||||||
|
throw new InvalidOperationException("Invalid auth file format.");
|
||||||
|
}
|
||||||
|
return new BasicAuthModel(lines[0].Trim(), lines[1].Trim());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(string.IsNullOrWhiteSpace(Username) || string.IsNullOrWhiteSpace(Password))
|
||||||
|
{
|
||||||
|
AnsiConsole.MarkupLine("[red]Username and password must be provided if auth file is not used.[/]");
|
||||||
|
throw new InvalidOperationException("Username and password are required.");
|
||||||
|
}
|
||||||
|
return new BasicAuthModel(Username!, Password!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
using GiteaPublish.Gitea;
|
||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace GiteaPublish.Commands.Package;
|
||||||
|
|
||||||
|
public class PackageDeleteArchCommand : AsyncCommand<PackageDeleteArchCommand.DeleteArchSettings>, ICommandLimiter<PackageSettings>
|
||||||
|
{
|
||||||
|
private readonly IPackageRepo _packageRepo;
|
||||||
|
private readonly IAnsiConsole _console;
|
||||||
|
|
||||||
|
public PackageDeleteArchCommand(IPackageRepo packageRepo, IAnsiConsole console)
|
||||||
|
{
|
||||||
|
_packageRepo = packageRepo;
|
||||||
|
_console = console;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<int> ExecuteAsync(CommandContext context, DeleteArchSettings settings, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_console.MarkupLine($"[blue]Deleting package {settings.Package} version {settings.Version} for architecture {settings.Architecture}...[/]");
|
||||||
|
bool success = await _packageRepo.DeletePackageAsync(settings.Owner, settings.Architecture, settings.Name, settings.Version, settings.BaseUrl);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
_console.MarkupLine("[green]Package deleted successfully![/]");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_console.MarkupLine("[red]Failed to delete package.[/]");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ValidationResult Validate(CommandContext context, DeleteArchSettings settings)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(settings.Package))
|
||||||
|
return ValidationResult.Error("Package is required.");
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(settings.Architecture))
|
||||||
|
return ValidationResult.Error("Architecture is required.");
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(settings.Name))
|
||||||
|
return ValidationResult.Error("Name is required.");
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(settings.Version))
|
||||||
|
return ValidationResult.Error("Version is required.");
|
||||||
|
|
||||||
|
if (!Uri.TryCreate(settings.BaseUrl, UriKind.Absolute, out Uri? uriResult) || (uriResult.Scheme != Uri.UriSchemeHttp && uriResult.Scheme != Uri.UriSchemeHttps))
|
||||||
|
return ValidationResult.Error("Base URL must be a valid HTTP or HTTPS URL.");
|
||||||
|
|
||||||
|
return ValidationResult.Success();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DeleteArchSettings : PackageSettings
|
||||||
|
{
|
||||||
|
[CommandOption("-p|--package <PACKAGE>", isRequired: true)]
|
||||||
|
public required string Package { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("-a|--architecture <ARCHITECTURE>", isRequired: true)]
|
||||||
|
public required string Architecture { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("-n|--name <NAME>", isRequired: true)]
|
||||||
|
public required string Name { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("-v|--version <VERSION>", isRequired: true)]
|
||||||
|
public required string Version { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
using GiteaPublish.Gitea;
|
||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
using ValidationResult = Spectre.Console.ValidationResult;
|
||||||
|
|
||||||
|
namespace GiteaPublish.Commands.Package;
|
||||||
|
|
||||||
|
public class PackagePublishArchCommand : AsyncCommand<PackagePublishArchCommand.PublishArchSettings>
|
||||||
|
{
|
||||||
|
private readonly ArchPackageRepo _packageRepo;
|
||||||
|
private readonly IAnsiConsole _console;
|
||||||
|
|
||||||
|
public PackagePublishArchCommand(IPackageRepo packageRepo, IAnsiConsole console)
|
||||||
|
{
|
||||||
|
_packageRepo = packageRepo as ArchPackageRepo
|
||||||
|
?? throw new ArgumentException("Package repository must be of type ArchPackageRepo.", nameof(packageRepo));
|
||||||
|
_console = console;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override async Task<int> ExecuteAsync(CommandContext context, PublishArchSettings settings, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_packageRepo.SetAuthentication(settings.GetAuth());
|
||||||
|
bool success = await _packageRepo.PublishPackageAsync(settings.Owner, settings.Repository, settings.File, settings.BaseUrl);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
_console.MarkupLine("[green]Package published successfully![/]");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_console.MarkupLine("[red]Failed to publish package.[/]");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ValidationResult Validate(CommandContext context, PublishArchSettings settings)
|
||||||
|
{
|
||||||
|
if (!File.Exists(settings.File))
|
||||||
|
return ValidationResult.Error($"File '{settings.File}' does not exist.");
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(settings.Owner))
|
||||||
|
return ValidationResult.Error("Owner is required.");
|
||||||
|
|
||||||
|
if(string.IsNullOrWhiteSpace(settings.Repository))
|
||||||
|
return ValidationResult.Error("Repository is required.");
|
||||||
|
|
||||||
|
if(string.IsNullOrWhiteSpace(settings.Username))
|
||||||
|
return ValidationResult.Error("Username is required.");
|
||||||
|
|
||||||
|
if(string.IsNullOrWhiteSpace(settings.Password))
|
||||||
|
return ValidationResult.Error("Password is required.");
|
||||||
|
|
||||||
|
if (!Uri.TryCreate(settings.BaseUrl, UriKind.Absolute, out Uri? uriResult) || (uriResult.Scheme != Uri.UriSchemeHttp && uriResult.Scheme != Uri.UriSchemeHttps))
|
||||||
|
return ValidationResult.Error("Base URL must be a valid HTTP or HTTPS URL.");
|
||||||
|
|
||||||
|
return ValidationResult.Success();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public sealed class PublishArchSettings : PackageSettings
|
||||||
|
{
|
||||||
|
|
||||||
|
[CommandOption("-f|--file <FILE>", isRequired: true)]
|
||||||
|
public required string File { get; init; }
|
||||||
|
|
||||||
|
[CommandOption("-r|--repository <REPOSITORY>", isRequired: true)]
|
||||||
|
public string Repository { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace GiteaPublish.Commands.Package;
|
||||||
|
|
||||||
|
public class PackageSettings : AuthSettings
|
||||||
|
{
|
||||||
|
[CommandOption("-o|--owner <OWNER>", isRequired: true)]
|
||||||
|
public string Owner { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[CommandOption("-b|--base-url <BASE_URL>", isRequired: true)]
|
||||||
|
public string BaseUrl { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
namespace GiteaPublish.Commands.Release;
|
||||||
|
|
||||||
|
public class AddAssetOptions
|
||||||
|
{
|
||||||
|
public string Owner { get; set; }
|
||||||
|
public string Repository { get; set; }
|
||||||
|
public int ReleaseId { get; set; }
|
||||||
|
public string AssetName { get; set; }
|
||||||
|
public byte[] AssetContent { get; set; }
|
||||||
|
|
||||||
|
public AddAssetOptions(string owner, string repository, int releaseId, string assetPath)
|
||||||
|
{
|
||||||
|
Owner = owner;
|
||||||
|
Repository = repository;
|
||||||
|
ReleaseId = releaseId;
|
||||||
|
AssetName = Path.GetFileName(assetPath);
|
||||||
|
AssetContent = File.ReadAllBytes(assetPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultipartFormDataContent ToFormContent()
|
||||||
|
{
|
||||||
|
var form = new MultipartFormDataContent();
|
||||||
|
|
||||||
|
form.Add(new StringContent(Owner), "owner");
|
||||||
|
form.Add(new StringContent(Repository), "repo");
|
||||||
|
form.Add(new StringContent(ReleaseId.ToString()), "id");
|
||||||
|
form.Add(new StringContent(AssetName), "name");
|
||||||
|
form.Add(new ByteArrayContent(AssetContent), "attachment");
|
||||||
|
return form;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace GiteaPublish.Commands.Release;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// CreateReleaseOption options when creating a release.
|
||||||
|
/// </summary>
|
||||||
|
public class CreateReleaseOption
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The release notes or description.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("body")]
|
||||||
|
public string? Body { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to create the release as a draft.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("draft")]
|
||||||
|
public bool Draft { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The display title of the release.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("name")]
|
||||||
|
public string? Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to mark the release as a prerelease.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("prerelease")]
|
||||||
|
public bool Prerelease { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The message for the git tag.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("tag_message")]
|
||||||
|
public string? TagMessage { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The tag name for the release (required).
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("tag_name")]
|
||||||
|
public string TagName { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The target commitish for the release.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("target_commitish")]
|
||||||
|
public string? TargetCommitish { get; set; }
|
||||||
|
|
||||||
|
public CreateReleaseOption()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public CreateReleaseOption(PublishReleaseCommandSettings settings)
|
||||||
|
{
|
||||||
|
Body = settings.Body;
|
||||||
|
Draft = settings.Draft;
|
||||||
|
Name = settings.Name;
|
||||||
|
Prerelease = settings.Prerelease;
|
||||||
|
TagMessage = settings.TagMessage;
|
||||||
|
TagName = settings.TagName;
|
||||||
|
TargetCommitish = settings.TargetCommitish;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public string ToJson()
|
||||||
|
=> JsonSerializer.Serialize(this);
|
||||||
|
}
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace GiteaPublish.Commands.Release;
|
||||||
|
|
||||||
|
public class CreateReleaseResponse
|
||||||
|
{
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("id")]
|
||||||
|
public int? Id { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("tag_name")]
|
||||||
|
public string TagName { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("target_commitish")]
|
||||||
|
public string TargetCommitish { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("body")]
|
||||||
|
public string Body { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("url")]
|
||||||
|
public Uri Url { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("html_url")]
|
||||||
|
public Uri HtmlUrl { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("tarball_url")]
|
||||||
|
public Uri TarballUrl { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("zipball_url")]
|
||||||
|
public Uri ZipballUrl { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("upload_url")]
|
||||||
|
public Uri UploadUrl { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("draft")]
|
||||||
|
public bool? Draft { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("prerelease")]
|
||||||
|
public bool? Prerelease { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("created_at")]
|
||||||
|
public DateTimeOffset? CreatedAt { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("published_at")]
|
||||||
|
public DateTimeOffset? PublishedAt { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("author")]
|
||||||
|
public AuthorModel Author { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("assets")]
|
||||||
|
public object[] Assets { get; set; }
|
||||||
|
|
||||||
|
public class AuthorModel
|
||||||
|
{
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("id")]
|
||||||
|
public long? Id { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("login")]
|
||||||
|
public string Login { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("login_name")]
|
||||||
|
public string LoginName { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("source_id")]
|
||||||
|
public long? SourceId { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("full_name")]
|
||||||
|
public string FullName { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("email")]
|
||||||
|
public string Email { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("avatar_url")]
|
||||||
|
public Uri AvatarUrl { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("html_url")]
|
||||||
|
public Uri HtmlUrl { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("language")]
|
||||||
|
public string Language { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("is_admin")]
|
||||||
|
public bool? IsAdmin { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("last_login")]
|
||||||
|
public DateTimeOffset? LastLogin { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("created")]
|
||||||
|
public DateTimeOffset? Created { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("restricted")]
|
||||||
|
public bool? Restricted { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("active")]
|
||||||
|
public bool? Active { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("prohibit_login")]
|
||||||
|
public bool? ProhibitLogin { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("location")]
|
||||||
|
public string Location { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("website")]
|
||||||
|
public Uri Website { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("description")]
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("visibility")]
|
||||||
|
public string Visibility { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("followers_count")]
|
||||||
|
public long? FollowersCount { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("following_count")]
|
||||||
|
public long? FollowingCount { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("starred_repos_count")]
|
||||||
|
public long? StarredReposCount { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
[JsonPropertyName("username")]
|
||||||
|
public string Username { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
using GiteaPublish.Gitea;
|
||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace GiteaPublish.Commands.Release;
|
||||||
|
|
||||||
|
public class PublishReleaseCommand : AsyncCommand<PublishReleaseCommandSettings>
|
||||||
|
{
|
||||||
|
private readonly ReleaseService _releaseService;
|
||||||
|
private readonly IAnsiConsole _console;
|
||||||
|
|
||||||
|
public PublishReleaseCommand(ReleaseService releaseService, IAnsiConsole console)
|
||||||
|
{
|
||||||
|
_releaseService = releaseService;
|
||||||
|
_console = console;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<int> ExecuteAsync(CommandContext context, PublishReleaseCommandSettings settings,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_releaseService.SetAuthorization(settings.GetAuth());
|
||||||
|
int releaseId = await _releaseService.CreateReleaseAsync(new CreateReleaseOption(settings), settings.Owner, settings.Repository, settings.BaseUrl);
|
||||||
|
if (releaseId != int.MinValue)
|
||||||
|
{
|
||||||
|
_console.MarkupLine("[green]Release created successfully![/]");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_console.MarkupLine("[red]Operation Failed.[/]");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.Files.Length == 0)
|
||||||
|
{
|
||||||
|
_console.MarkupLine("[yellow]No assets to upload.[/]");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_console.MarkupLine($"[blue]Uploading {settings.Files.Length} asset(s)...[/]");
|
||||||
|
foreach (var file in settings.Files)
|
||||||
|
{
|
||||||
|
if (!File.Exists(file))
|
||||||
|
{
|
||||||
|
_console.MarkupLine($"[red]File not found: {file}[/]");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddAssetOptions options = new AddAssetOptions(settings.Owner, settings.Repository, releaseId, file);
|
||||||
|
|
||||||
|
bool assetSuccess =
|
||||||
|
await _releaseService.AddAssetAsync(options, settings.BaseUrl);
|
||||||
|
if (assetSuccess)
|
||||||
|
_console.MarkupLine($"[green]Uploaded asset: {file}[/]");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ValidationResult Validate(CommandContext context, PublishReleaseCommandSettings settings)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(settings.Owner))
|
||||||
|
return ValidationResult.Error("Owner is required.");
|
||||||
|
if (string.IsNullOrWhiteSpace(settings.Repository))
|
||||||
|
return ValidationResult.Error("Repository is required.");
|
||||||
|
if (string.IsNullOrWhiteSpace(settings.BaseUrl))
|
||||||
|
return ValidationResult.Error("Base URL is required.");
|
||||||
|
if (string.IsNullOrWhiteSpace(settings.TagName))
|
||||||
|
return ValidationResult.Error("Tag name is required.");
|
||||||
|
if (string.IsNullOrWhiteSpace(settings.AuthFile) && (string.IsNullOrWhiteSpace(settings.Username) || string.IsNullOrWhiteSpace(settings.Password)))
|
||||||
|
return ValidationResult.Error("Either auth file or username/password must be provided.");
|
||||||
|
|
||||||
|
return ValidationResult.Success();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//release publish --auth-file "/home/gitea-package-token.txt" -o Stillkill -r GiteaPublish -b https://git.stillkill.net
|
||||||
|
//-e "Release body" -d -n "Release name" -p --tag-message "Tag message" --tag-name "v1.0.0" -tc "master" -f "/home/Downloads/ACTv3.zip" --file "/home/stillkill/Downloads/test.gif"
|
||||||
|
|
||||||
|
public class PublishReleaseCommandSettings : AuthSettings
|
||||||
|
{
|
||||||
|
[CommandOption("-o|--owner <OWNER>", isRequired: true)]
|
||||||
|
public string Owner { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[CommandOption("-r|--repository <REPOSITORY>", isRequired: true)]
|
||||||
|
public string Repository { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[CommandOption("-b|--base-url <BASE_URL>", isRequired: true)]
|
||||||
|
public string BaseUrl { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[CommandOption("-e|--body <BODY>")]
|
||||||
|
public string? Body { get; set; } = null;
|
||||||
|
|
||||||
|
[CommandOption("-d|--draft")]
|
||||||
|
public bool Draft { get; set; } = false;
|
||||||
|
|
||||||
|
[CommandOption("-n|--name <NAME>")]
|
||||||
|
public string? Name { get; set; } = null;
|
||||||
|
|
||||||
|
[CommandOption("-p|--prerelease")]
|
||||||
|
public bool Prerelease { get; set; } = false;
|
||||||
|
|
||||||
|
[CommandOption("--tag-message <TAG_MESSAGE>")]
|
||||||
|
public string? TagMessage { get; set; } = null;
|
||||||
|
|
||||||
|
[CommandOption("--tag-name <TAG_NAME>", isRequired: true)]
|
||||||
|
public string TagName { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[CommandOption("-c|--target-commitish <TARGET_COMMITISH>")]
|
||||||
|
public string? TargetCommitish { get; set; } = null;
|
||||||
|
|
||||||
|
[CommandOption("-f|--file <FILE>")]
|
||||||
|
public string[] Files { get; set; } = Array.Empty<string>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
using System.Net.Http.Json;
|
||||||
|
using GiteaPublish.Gitea;
|
||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace GiteaPublish.Commands.Release;
|
||||||
|
|
||||||
|
public class ReleaseService
|
||||||
|
{
|
||||||
|
private readonly IAnsiConsole _console;
|
||||||
|
private readonly HttpClient _client;
|
||||||
|
|
||||||
|
public ReleaseService(IAnsiConsole console, HttpClient client)
|
||||||
|
{
|
||||||
|
_console = console;
|
||||||
|
_client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> CreateReleaseAsync(CreateReleaseOption option, string owner, string repository, string baseUrl)
|
||||||
|
{
|
||||||
|
_console.MarkupLine($"[blue]Creating release '{option.TagName}' for {owner}/{repository}...[/]");
|
||||||
|
_client.BaseAddress ??= new Uri(baseUrl.TrimEnd('/'));
|
||||||
|
string endpoint = $"/api/v1/repos/{owner}/{repository}/releases";
|
||||||
|
var response = await _client.PostAsJsonAsync(endpoint, option);
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
var release = await response.Content.ReadFromJsonAsync<CreateReleaseResponse>();
|
||||||
|
if (release != null && release.Id.HasValue)
|
||||||
|
{
|
||||||
|
_console.MarkupLine($"[green]Release created with ID: {release.Id.Value}[/]");
|
||||||
|
return release.Id.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_console.MarkupLine($"[red]Failed to create release: {response.StatusCode} - {response.ReasonPhrase}[/]");
|
||||||
|
return int.MinValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> AddAssetAsync(AddAssetOptions options, string? baseUrl = null)
|
||||||
|
{
|
||||||
|
_console.MarkupLine($"[blue]Adding asset '{options.AssetName}' to release {options.ReleaseId}...[/]");
|
||||||
|
_client.BaseAddress ??= new Uri(baseUrl!.TrimEnd('/'));
|
||||||
|
|
||||||
|
MultipartFormDataContent form = options.ToFormContent();
|
||||||
|
var response = await _client.PostAsync($"/api/v1/repos/{options.Owner}/{options.Repository}/releases/{options.ReleaseId}/assets", form);
|
||||||
|
if (response.IsSuccessStatusCode) return true;
|
||||||
|
_console.MarkupLine($"[red]Failed to add asset: {response.StatusCode} - {response.ReasonPhrase}[/]");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAuthorization(BasicAuthModel auth)
|
||||||
|
{
|
||||||
|
_console.MarkupLine("[blue]Setting up authentication...[/]");
|
||||||
|
_client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", auth.AuthHeader);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,32 +3,50 @@ using Spectre.Console;
|
|||||||
|
|
||||||
namespace GiteaPublish.Gitea;
|
namespace GiteaPublish.Gitea;
|
||||||
|
|
||||||
public class ArchPackageRepo(HttpClient httpClient, IAnsiConsole ansiConsole, BasicAuthModel basicAuth)
|
public class ArchPackageRepo : IPackageRepo
|
||||||
: IPackageRepo
|
|
||||||
{
|
{
|
||||||
public async Task<bool> PublishPackageAsync(string owner, string repository, string filePath)
|
private BasicAuthModel BasicAuth { get; set; } = new BasicAuthModel();
|
||||||
|
|
||||||
|
private readonly IAnsiConsole _console;
|
||||||
|
private readonly HttpClient _httpClient;
|
||||||
|
|
||||||
|
public ArchPackageRepo(HttpClient httpClient, IAnsiConsole ansiConsole)
|
||||||
{
|
{
|
||||||
ansiConsole.MarkupLine($"[blue]Publishing package {filePath} to {owner}/{repository}...[/]");
|
_console = ansiConsole;
|
||||||
HttpRequestMessage request = new(HttpMethod.Put, $"api/packages/{owner}/arch/{repository}");
|
_httpClient = httpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> PublishPackageAsync(string owner, string repository, string filePath, string baseUrl)
|
||||||
|
{
|
||||||
|
_httpClient.BaseAddress = new Uri(baseUrl.TrimEnd('/'));
|
||||||
|
_console.MarkupLine($"[blue]Publishing package {filePath} to {owner}/{repository}...[/]");
|
||||||
|
HttpRequestMessage request = new(HttpMethod.Put, $"/api/packages/{owner}/arch/{repository}");
|
||||||
request.Content = new ByteArrayContent(await File.ReadAllBytesAsync(filePath));
|
request.Content = new ByteArrayContent(await File.ReadAllBytesAsync(filePath));
|
||||||
request.Headers.Authorization = new AuthenticationHeaderValue("Basic", basicAuth.AuthHeader);
|
request.Headers.Authorization = new AuthenticationHeaderValue("Basic", BasicAuth.AuthHeader);
|
||||||
HttpResponseMessage response = await httpClient.SendAsync(request);
|
HttpResponseMessage response = await _httpClient.SendAsync(request);
|
||||||
if (response.IsSuccessStatusCode) return true;
|
if (response.IsSuccessStatusCode) return true;
|
||||||
ansiConsole.MarkupLine($"[red]Failed to publish package: {response.StatusCode}[/]");
|
_console.MarkupLine($"[red]Failed to publish package: {response.StatusCode}[/]");
|
||||||
ansiConsole.MarkupLine($"[red]{(await response.Content.ReadAsStringAsync()).EscapeMarkup()}[/]");
|
_console.MarkupLine($"[red]{(await response.Content.ReadAsStringAsync()).EscapeMarkup()}[/]");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> DeletePackageAsync(string owner, string repository, string architecture, string packageName,
|
public async Task<bool> DeletePackageAsync(string owner, string repository, string packageName,
|
||||||
string packageVersion)
|
string packageVersion, string baseUrl)
|
||||||
{
|
{
|
||||||
|
_httpClient.BaseAddress = new Uri(baseUrl.TrimEnd('/'));
|
||||||
HttpRequestMessage request = new(HttpMethod.Delete,
|
HttpRequestMessage request = new(HttpMethod.Delete,
|
||||||
$"api/packages/{owner}/arch/{repository}/{architecture}/{packageName}/{packageVersion}");
|
$"/api/packages/{owner}/arch/{repository}/{packageName}/{packageVersion}");
|
||||||
request.Headers.Authorization = new AuthenticationHeaderValue("Basic", basicAuth.AuthHeader);
|
request.Headers.Authorization = new AuthenticationHeaderValue("Basic", BasicAuth.AuthHeader);
|
||||||
HttpResponseMessage response = await httpClient.SendAsync(request);
|
HttpResponseMessage response = await _httpClient.SendAsync(request);
|
||||||
if (response.IsSuccessStatusCode) return true;
|
if (response.IsSuccessStatusCode) return true;
|
||||||
ansiConsole.MarkupLine($"[red]Failed to delete package: {response.StatusCode}[/]");
|
_console.MarkupLine($"[red]Failed to delete package: {response.StatusCode}[/]");
|
||||||
ansiConsole.MarkupLine($"[red]{(await response.Content.ReadAsStringAsync()).EscapeMarkup()}[/]");
|
_console.MarkupLine($"[red]{(await response.Content.ReadAsStringAsync()).EscapeMarkup()}[/]");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetAuthentication(BasicAuthModel basicAuth)
|
||||||
|
{
|
||||||
|
BasicAuth = basicAuth;
|
||||||
|
_console.MarkupLine("[green]Authentication set.[/]");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -4,12 +4,16 @@ public class BasicAuthModel
|
|||||||
{
|
{
|
||||||
public string AuthHeader => Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes($"{_username}:{_password}"));
|
public string AuthHeader => Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes($"{_username}:{_password}"));
|
||||||
|
|
||||||
private readonly string _username;
|
private readonly string _username = string.Empty;
|
||||||
private readonly string _password;
|
private readonly string _password = string.Empty;
|
||||||
|
|
||||||
public BasicAuthModel(string username, string password)
|
public BasicAuthModel(string username, string password)
|
||||||
{
|
{
|
||||||
_username = username;
|
_username = username;
|
||||||
_password = password;
|
_password = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BasicAuthModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@ public interface IPackageRepo
|
|||||||
/// <param name="repository">The name of the repository</param>
|
/// <param name="repository">The name of the repository</param>
|
||||||
/// <param name="filePath">The path to the package file</param>
|
/// <param name="filePath">The path to the package file</param>
|
||||||
/// <returns>A bool representing whether the task was successful</returns>
|
/// <returns>A bool representing whether the task was successful</returns>
|
||||||
public Task<bool> PublishPackageAsync(string owner, string repository, string filePath);
|
public Task<bool> PublishPackageAsync(string owner, string repository, string filePath, string baseUrl);
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -21,5 +21,11 @@ public interface IPackageRepo
|
|||||||
/// <param name="packageName">The name of the package</param>
|
/// <param name="packageName">The name of the package</param>
|
||||||
/// <param name="packageVersion">The version of the package</param>
|
/// <param name="packageVersion">The version of the package</param>
|
||||||
/// <returns>A bool representing whether the task was successful</returns>
|
/// <returns>A bool representing whether the task was successful</returns>
|
||||||
public Task<bool> DeletePackageAsync(string owner, string repository, string architecture, string packageName, string packageVersion);
|
public Task<bool> DeletePackageAsync(string owner, string architecture, string packageName, string packageVersion, string baseUrl);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the authentication for the package repository. This method should be called before any operations that require authentication (e.g., publishing or deleting packages). The BasicAuthModel contains the necessary information for basic authentication, such as the username and password.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="basicAuth"></param>
|
||||||
|
public void SetAuthentication(BasicAuthModel basicAuth);
|
||||||
}
|
}
|
||||||
@@ -5,14 +5,18 @@
|
|||||||
<TargetFramework>net10.0</TargetFramework>
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.2" />
|
||||||
<PackageReference Include="Spectre.Console.Cli" Version="0.53.1" />
|
<PackageReference Include="Spectre.Console.Cli" Version="0.53.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Commands\" />
|
<None Update="PKGBUILD">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
pkgname=gitea-publish
|
||||||
|
pkgver=<PKG-VER>
|
||||||
|
pkgrel=1
|
||||||
|
pkgdesc=""
|
||||||
|
arch=('x86_64')
|
||||||
|
url="https://git.stillkill.net/Stillkill/GiteaPublish"
|
||||||
|
license=('BEERWARE')
|
||||||
|
depends=()
|
||||||
|
makedepends=('dotnet-sdk' 'git')
|
||||||
|
source=("git+https://git.stillkill.net/Stillkill/GiteaPublish.git#branch=master")
|
||||||
|
sha256sums=('SKIP')
|
||||||
|
|
||||||
|
build() {
|
||||||
|
cd "$srcdir/GiteaPublish"
|
||||||
|
git checkout "v${pkgver}" || true
|
||||||
|
dotnet publish -c Release -r linux-x64 --self-contained \
|
||||||
|
-p:PublishSingleFile=true \
|
||||||
|
-p:PublishReadyToRun=true \
|
||||||
|
-p:UseAppHost=true \
|
||||||
|
-p:DebugType=embedded \
|
||||||
|
-o "$srcdir/output"
|
||||||
|
echo "$srcdir/output"
|
||||||
|
}
|
||||||
|
|
||||||
|
package() {
|
||||||
|
cd "$srcdir/output"
|
||||||
|
pwd
|
||||||
|
install -Dm755 "GiteaPublish" "$pkgdir/usr/bin/gitea-publish"
|
||||||
|
}
|
||||||
+76
-4
@@ -1,5 +1,11 @@
|
|||||||
using GiteaPublish.Gitea;
|
using System.Globalization;
|
||||||
|
using GiteaPublish.Commands;
|
||||||
|
using GiteaPublish.Commands.Package;
|
||||||
|
using GiteaPublish.Commands.Release;
|
||||||
|
using GiteaPublish.Gitea;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Spectre.Console;
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
namespace GiteaPublish;
|
namespace GiteaPublish;
|
||||||
|
|
||||||
@@ -7,8 +13,74 @@ class Program
|
|||||||
{
|
{
|
||||||
static async Task Main(string[] args)
|
static async Task Main(string[] args)
|
||||||
{
|
{
|
||||||
var basicAuthModel = new BasicAuthModel("", "");
|
ServiceCollection services = new();
|
||||||
ArchPackageRepo repo = new(new HttpClient { BaseAddress = new Uri("https://git.stillkill.net") }, AnsiConsole.Console, basicAuthModel);
|
services.AddSingleton<IPackageRepo, ArchPackageRepo>();
|
||||||
await repo.PublishPackageAsync("Stillkill", "core", "/home/stillkill/CollectHorse.tar.gz");
|
services.AddSingleton(CreateHttpClient());
|
||||||
|
services.AddSingleton<ReleaseService>();
|
||||||
|
TypeRegistrar registrar = new TypeRegistrar(services);
|
||||||
|
CommandApp app = new CommandApp(registrar);
|
||||||
|
app.Configure(config =>
|
||||||
|
{
|
||||||
|
config.SetApplicationName("GiteaPublish");
|
||||||
|
config.SetApplicationVersion(ApplicationVersion.Version);
|
||||||
|
config.SetApplicationCulture(CultureInfo.GetCultureInfo("en-us"));
|
||||||
|
|
||||||
|
config.AddBranch("package", packageConfig =>
|
||||||
|
{
|
||||||
|
packageConfig.AddBranch("arch", archConfig =>
|
||||||
|
{
|
||||||
|
archConfig.AddCommand<PackagePublishArchCommand>("publish")
|
||||||
|
.WithDescription("Publish an Arch package to a Gitea repository")
|
||||||
|
.WithExample("package arch publish --username <username> --password <password or token> " +
|
||||||
|
"-o <repo owner> -r <repo name> -f <package file> -b <base url>");
|
||||||
|
|
||||||
|
// archConfig.AddCommand<PackageDeleteArchCommand>("delete")
|
||||||
|
// .WithDescription("Deletes an Arch package from a Gitea repository");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
config.AddBranch("release", releaseConfig =>
|
||||||
|
{
|
||||||
|
releaseConfig.AddCommand<PublishReleaseCommand>("publish")
|
||||||
|
.WithDescription("Publish a release to a Gitea repository")
|
||||||
|
.WithExample("release publish --username <username> --password <password or token> " +
|
||||||
|
"-o <repo owner> -r <repo name> -f <asset file> -b <base url> " +
|
||||||
|
"--tag-name <tag name> [--name <release name>] [--body <release notes>] " +
|
||||||
|
"[--draft] [--prerelease] [--tag-message <tag message>] [--target-commitish <target commitish>]");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await app.RunAsync(args);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteException(e);
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HttpClient CreateHttpClient()
|
||||||
|
{
|
||||||
|
HttpClient httpClient = new();
|
||||||
|
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd($"GiteaPublish/{ApplicationVersion.Version}");
|
||||||
|
return httpClient;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class TypeRegistrar(IServiceCollection services) : ITypeRegistrar
|
||||||
|
{
|
||||||
|
public ITypeResolver Build() => new TypeResolver(services.BuildServiceProvider());
|
||||||
|
|
||||||
|
public void Register(Type service, Type implementation) => services.AddSingleton(service, implementation);
|
||||||
|
|
||||||
|
public void RegisterInstance(Type service, object implementation) => services.AddSingleton(service, implementation);
|
||||||
|
|
||||||
|
public void RegisterLazy(Type service, Func<object> factory) => services.AddSingleton(service, _ => factory());
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class TypeResolver(IServiceProvider provider) : ITypeResolver
|
||||||
|
{
|
||||||
|
public object? Resolve(Type? type) => type == null ? null : provider.GetService(type);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user