provisioning-core/nulib/domain/gitea/api_client.nu

434 lines
9.5 KiB
Text

# Gitea API Client
#
# REST API v1 client for Gitea operations
#
# Version: 1.0.0
# Dependencies: http, nu_plugin_tera
use ../config/loader.nu get-config
# Get Gitea configuration from global config
export def get-gitea-config [] -> record {
let config = get-config
if "gitea" not-in $config {
error make {
msg: "Gitea not configured"
help: "Add gitea section to configuration"
}
}
$config.gitea
}
# Get Gitea auth token
export def get-gitea-token [
gitea_config: record
] -> string {
let token_path = $gitea_config.auth.token_path | path expand
if not ($token_path | path exists) {
error make {
msg: $"Token file not found: ($token_path)"
help: "Create token file with Gitea access token"
}
}
# Check if encrypted (SOPS)
if ($token_path | str ends-with ".enc") {
# Decrypt with SOPS
^sops --decrypt $token_path | str trim
} else {
open $token_path | str trim
}
}
# Get base API URL
export def get-api-url [
gitea_config: record
] -> string {
if $gitea_config.mode == "local" {
let port = $gitea_config.local.port
$"http://localhost:($port)/api/v1"
} else {
$gitea_config.remote.api_url
}
}
# Make API call to Gitea
export def gitea-api-call [
endpoint: string
method: string = "GET"
body?: record
--gitea-config: record
] -> record {
let config = if ($gitea_config | is-empty) {
get-gitea-config
} else {
$gitea_config
}
let token = get-gitea-token $config
let base_url = get-api-url $config
let url = $"($base_url)/($endpoint)"
let headers = [
"Authorization" $"token ($token)"
"Content-Type" "application/json"
"Accept" "application/json"
]
let result = if $method == "GET" {
http get --headers $headers $url
} else if $method == "POST" {
if ($body | is-empty) {
http post --headers $headers $url ""
} else {
http post --headers $headers $url ($body | to json)
}
} else if $method == "PUT" {
if ($body | is-empty) {
http put --headers $headers $url ""
} else {
http put --headers $headers $url ($body | to json)
}
} else if $method == "DELETE" {
http delete --headers $headers $url
} else if $method == "PATCH" {
if ($body | is-empty) {
http patch --headers $headers $url ""
} else {
http patch --headers $headers $url ($body | to json)
}
} else {
error make {
msg: $"Unsupported HTTP method: ($method)"
}
}
$result
}
# Repository Operations
# Create repository
export def create-repository [
org: string
repo_name: string
description?: string
private: bool = false
auto_init: bool = true
] -> record {
let body = {
name: $repo_name
description: ($description | default "")
private: $private
auto_init: $auto_init
default_branch: "main"
}
gitea-api-call $"orgs/($org)/repos" "POST" $body
}
# Get repository
export def get-repository [
owner: string
repo_name: string
] -> record {
gitea-api-call $"repos/($owner)/($repo_name)" "GET"
}
# Delete repository
export def delete-repository [
owner: string
repo_name: string
--force (-f)
] -> bool {
if not $force {
print $"⚠️ About to delete repository ($owner)/($repo_name)"
let confirm = input "Type repository name to confirm: "
if $confirm != $repo_name {
print "Deletion cancelled"
return false
}
}
gitea-api-call $"repos/($owner)/($repo_name)" "DELETE"
true
}
# List repositories in organization
export def list-repositories [
org: string
] -> list {
gitea-api-call $"orgs/($org)/repos" "GET"
}
# List user repositories
export def list-user-repositories [
username?: string
] -> list {
let user = if ($username | is-empty) {
(get-current-user).login
} else {
$username
}
gitea-api-call $"users/($user)/repos" "GET"
}
# Release Operations
# Create release
export def create-release [
owner: string
repo_name: string
tag_name: string
release_name: string
body?: string
draft: bool = false
prerelease: bool = false
] -> record {
let release_body = {
tag_name: $tag_name
name: $release_name
body: ($body | default "")
draft: $draft
prerelease: $prerelease
target_commitish: "main"
}
gitea-api-call $"repos/($owner)/($repo_name)/releases" "POST" $release_body
}
# Upload release asset
export def upload-release-asset [
owner: string
repo_name: string
release_id: int
file_path: string
] -> bool {
let config = get-gitea-config
let token = get-gitea-token $config
let base_url = get-api-url $config
let filename = $file_path | path basename
let url = $"($base_url)/repos/($owner)/($repo_name)/releases/($release_id)/assets?name=($filename)"
# Use curl for file upload (http command doesn't support multipart/form-data well)
let result = ^curl -X POST \
-H $"Authorization: token ($token)" \
-F $"attachment=@($file_path)" \
$url
true
}
# Get release by tag
export def get-release-by-tag [
owner: string
repo_name: string
tag: string
] -> record {
gitea-api-call $"repos/($owner)/($repo_name)/releases/tags/($tag)" "GET"
}
# List releases
export def list-releases [
owner: string
repo_name: string
] -> list {
gitea-api-call $"repos/($owner)/($repo_name)/releases" "GET"
}
# Delete release
export def delete-release [
owner: string
repo_name: string
release_id: int
] -> bool {
gitea-api-call $"repos/($owner)/($repo_name)/releases/($release_id)" "DELETE"
true
}
# Issue Operations (for locking)
# Create issue
export def create-issue [
owner: string
repo_name: string
title: string
body: string
labels: list = []
assignee?: string
] -> record {
let issue_body = {
title: $title
body: $body
labels: $labels
}
let issue_with_assignee = if ($assignee | is-not-empty) {
$issue_body | merge {assignee: $assignee}
} else {
$issue_body
}
gitea-api-call $"repos/($owner)/($repo_name)/issues" "POST" $issue_with_assignee
}
# Close issue
export def close-issue [
owner: string
repo_name: string
issue_number: int
] -> bool {
let body = {state: "closed"}
gitea-api-call $"repos/($owner)/($repo_name)/issues/($issue_number)" "PATCH" $body
true
}
# List issues
export def list-issues [
owner: string
repo_name: string
state: string = "open"
labels?: string
] -> list {
let endpoint = if ($labels | is-empty) {
$"repos/($owner)/($repo_name)/issues?state=($state)"
} else {
$"repos/($owner)/($repo_name)/issues?state=($state)&labels=($labels)"
}
gitea-api-call $endpoint "GET"
}
# Get issue
export def get-issue [
owner: string
repo_name: string
issue_number: int
] -> record {
gitea-api-call $"repos/($owner)/($repo_name)/issues/($issue_number)" "GET"
}
# Organization Operations
# Create organization
export def create-organization [
org_name: string
description?: string
visibility: string = "private"
] -> record {
let body = {
username: $org_name
description: ($description | default "")
visibility: $visibility
}
gitea-api-call "orgs" "POST" $body
}
# Get organization
export def get-organization [
org_name: string
] -> record {
gitea-api-call $"orgs/($org_name)" "GET"
}
# List organizations
export def list-organizations [] -> list {
gitea-api-call "user/orgs" "GET"
}
# User/Auth Operations
# Get current user
export def get-current-user [] -> record {
gitea-api-call "user" "GET"
}
# Validate token
export def validate-token [
gitea_config?: record
] {
let config = if ($gitea_config | is-empty) {
get-gitea-config
} else {
$gitea_config
}
let result = (do {
gitea-api-call "user" "GET" --gitea-config $config
} | complete)
if $result.exit_code == 0 {
let user = $result.stdout | from json
$user.login? != null
} else {
false
}
}
# Branch Operations
# Create branch
export def create-branch [
owner: string
repo_name: string
branch_name: string
base_branch: string = "main"
] -> record {
let body = {
new_branch_name: $branch_name
old_branch_name: $base_branch
}
gitea-api-call $"repos/($owner)/($repo_name)/branches" "POST" $body
}
# List branches
export def list-branches [
owner: string
repo_name: string
] -> list {
gitea-api-call $"repos/($owner)/($repo_name)/branches" "GET"
}
# Get branch
export def get-branch [
owner: string
repo_name: string
branch_name: string
] -> record {
gitea-api-call $"repos/($owner)/($repo_name)/branches/($branch_name)" "GET"
}
# Tag Operations
# Create tag
export def create-tag [
owner: string
repo_name: string
tag_name: string
message?: string
target?: string
] -> record {
let body = {
tag_name: $tag_name
message: ($message | default "")
target: ($target | default "main")
}
gitea-api-call $"repos/($owner)/($repo_name)/tags" "POST" $body
}
# List tags
export def list-tags [
owner: string
repo_name: string
] -> list {
gitea-api-call $"repos/($owner)/($repo_name)/tags" "GET"
}