616 lines
18 KiB
Plaintext
616 lines
18 KiB
Plaintext
#!/usr/bin/env nu
|
|
|
|
# Registry update tool - updates package manager registries
|
|
#
|
|
# Updates:
|
|
# - Homebrew formulas
|
|
# - APT/YUM repositories
|
|
# - Docker Hub descriptions
|
|
# - npm package registry
|
|
# - Cargo crates.io
|
|
# - GitHub registry packages
|
|
|
|
use std log
|
|
|
|
def main [
|
|
--registries: string = "homebrew" # Registries to update: homebrew,apt,yum,docker,npm,cargo,all
|
|
--version: string = "" # Version to update to (auto-detected if empty)
|
|
--package-urls: string = "" # Comma-separated URLs to package files
|
|
--registry-config: string = "" # Registry configuration file
|
|
--dry-run: bool = false # Show what would be updated without doing it
|
|
--auto-commit: bool = false # Automatically commit and push registry updates
|
|
--verbose: bool = false # Enable verbose logging
|
|
--force: bool = false # Force updates even if version already exists
|
|
] -> record {
|
|
|
|
let repo_root = ($env.PWD | path dirname | path dirname | path dirname)
|
|
|
|
# Determine version if not provided
|
|
let target_version = if $version == "" {
|
|
detect_current_version $repo_root
|
|
} else {
|
|
$version
|
|
}
|
|
|
|
let target_registries = if $registries == "all" {
|
|
["homebrew", "apt", "yum", "docker", "npm", "cargo"]
|
|
} else {
|
|
($registries | split row "," | each { str trim })
|
|
}
|
|
|
|
let registry_config = {
|
|
registries: $target_registries
|
|
version: $target_version
|
|
package_urls: (if $package_urls == "" { [] } else { $package_urls | split row "," | each { str trim } })
|
|
registry_config_file: (if $registry_config == "" { "" } else { $registry_config | path expand })
|
|
dry_run: $dry_run
|
|
auto_commit: $auto_commit
|
|
verbose: $verbose
|
|
force: $force
|
|
repo_root: $repo_root
|
|
}
|
|
|
|
log info $"Starting registry updates with config: ($registry_config)"
|
|
|
|
# Load registry configuration if provided
|
|
let config_data = if $registry_config.registry_config_file != "" {
|
|
load_registry_config $registry_config.registry_config_file
|
|
} else {
|
|
get_default_registry_config
|
|
}
|
|
|
|
# Update each registry
|
|
let update_results = $registry_config.registries | each {|registry|
|
|
update_registry $registry $registry_config $config_data
|
|
}
|
|
|
|
let summary = {
|
|
total_registries: ($registry_config.registries | length)
|
|
successful_updates: ($update_results | where status == "success" | length)
|
|
failed_updates: ($update_results | where status == "failed" | length)
|
|
skipped_updates: ($update_results | where status == "skipped" | length)
|
|
version: $registry_config.version
|
|
registry_config: $registry_config
|
|
results: $update_results
|
|
}
|
|
|
|
if $summary.failed_updates > 0 {
|
|
log error $"Registry updates completed with ($summary.failed_updates) failures"
|
|
exit 1
|
|
} else {
|
|
if $registry_config.dry_run {
|
|
log info $"Dry run completed - would update ($summary.total_registries) registries"
|
|
} else {
|
|
log info $"Registry updates completed successfully - ($summary.successful_updates) registries updated"
|
|
}
|
|
}
|
|
|
|
return $summary
|
|
}
|
|
|
|
# Detect current version from git tags
|
|
def detect_current_version [repo_root: string] -> string {
|
|
cd $repo_root
|
|
|
|
try {
|
|
let latest_tag = (git describe --tags --abbrev=0 2>/dev/null | str trim)
|
|
if $latest_tag != "" {
|
|
# Remove 'v' prefix if present
|
|
return ($latest_tag | str replace "^v" "")
|
|
}
|
|
return "0.1.0"
|
|
} catch {
|
|
return "0.1.0"
|
|
}
|
|
}
|
|
|
|
# Load registry configuration from file
|
|
def load_registry_config [config_file: string] -> record {
|
|
if not ($config_file | path exists) {
|
|
log warning $"Registry config file not found: ($config_file)"
|
|
return (get_default_registry_config)
|
|
}
|
|
|
|
try {
|
|
open $config_file
|
|
} catch {|err|
|
|
log warning $"Failed to load registry config: ($err.msg)"
|
|
return (get_default_registry_config)
|
|
}
|
|
}
|
|
|
|
# Get default registry configuration
|
|
def get_default_registry_config [] -> record {
|
|
{
|
|
homebrew: {
|
|
tap_repo: "your-org/homebrew-tap"
|
|
formula_name: "provisioning"
|
|
description: "Cloud-native infrastructure provisioning and management system"
|
|
homepage: "https://github.com/your-org/provisioning"
|
|
license: "MIT"
|
|
}
|
|
apt: {
|
|
repository: "https://apt.your-org.com/ubuntu"
|
|
distribution: "stable"
|
|
component: "main"
|
|
keyring: "/usr/share/keyrings/your-org-archive-keyring.gpg"
|
|
}
|
|
yum: {
|
|
repository: "https://yum.your-org.com/centos"
|
|
gpg_key: "https://yum.your-org.com/RPM-GPG-KEY-your-org"
|
|
}
|
|
docker: {
|
|
registry: "docker.io"
|
|
namespace: "your-org"
|
|
image_name: "provisioning"
|
|
}
|
|
npm: {
|
|
registry: "https://registry.npmjs.org"
|
|
scope: "@your-org"
|
|
package_name: "provisioning"
|
|
}
|
|
cargo: {
|
|
registry: "https://crates.io"
|
|
crate_name: "provisioning"
|
|
}
|
|
}
|
|
}
|
|
|
|
# Update specific registry
|
|
def update_registry [
|
|
registry: string
|
|
registry_config: record
|
|
config_data: record
|
|
] -> record {
|
|
log info $"Updating registry: ($registry)"
|
|
|
|
let start_time = (date now)
|
|
|
|
match $registry {
|
|
"homebrew" => { update_homebrew $registry_config $config_data }
|
|
"apt" => { update_apt_repository $registry_config $config_data }
|
|
"yum" => { update_yum_repository $registry_config $config_data }
|
|
"docker" => { update_docker_registry $registry_config $config_data }
|
|
"npm" => { update_npm_registry $registry_config $config_data }
|
|
"cargo" => { update_cargo_registry $registry_config $config_data }
|
|
_ => {
|
|
log warning $"Unknown registry: ($registry)"
|
|
{
|
|
registry: $registry
|
|
status: "failed"
|
|
reason: "unknown registry"
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# Update Homebrew formula
|
|
def update_homebrew [
|
|
registry_config: record
|
|
config_data: record
|
|
] -> record {
|
|
log info "Updating Homebrew formula..."
|
|
|
|
let start_time = (date now)
|
|
let homebrew_config = ($config_data.homebrew)
|
|
|
|
if $registry_config.dry_run {
|
|
return {
|
|
registry: "homebrew"
|
|
status: "success"
|
|
formula_name: $homebrew_config.formula_name
|
|
version: $registry_config.version
|
|
dry_run: true
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
|
|
try {
|
|
# Clone or update tap repository
|
|
let tap_dir = $"/tmp/homebrew-tap-(random uuid)"
|
|
let tap_url = $"https://github.com/($homebrew_config.tap_repo).git"
|
|
|
|
if $registry_config.verbose {
|
|
log info $"Cloning tap repository: ($tap_url)"
|
|
}
|
|
|
|
git clone $tap_url $tap_dir
|
|
cd $tap_dir
|
|
|
|
# Generate formula
|
|
let formula_content = generate_homebrew_formula $registry_config $homebrew_config
|
|
|
|
# Write formula file
|
|
let formula_file = $"Formula/($homebrew_config.formula_name).rb"
|
|
mkdir "Formula"
|
|
$formula_content | save $formula_file
|
|
|
|
# Commit and push if auto-commit is enabled
|
|
if $registry_config.auto_commit {
|
|
git add $formula_file
|
|
git commit -m $"Update ($homebrew_config.formula_name) to v($registry_config.version)"
|
|
git push origin main
|
|
}
|
|
|
|
# Cleanup
|
|
cd /tmp
|
|
rm -rf $tap_dir
|
|
|
|
log info $"Successfully updated Homebrew formula: ($homebrew_config.formula_name)"
|
|
|
|
{
|
|
registry: "homebrew"
|
|
status: "success"
|
|
formula_name: $homebrew_config.formula_name
|
|
version: $registry_config.version
|
|
tap_repo: $homebrew_config.tap_repo
|
|
auto_committed: $registry_config.auto_commit
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
|
|
} catch {|err|
|
|
{
|
|
registry: "homebrew"
|
|
status: "failed"
|
|
reason: $err.msg
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
}
|
|
|
|
# Generate Homebrew formula content
|
|
def generate_homebrew_formula [
|
|
registry_config: record
|
|
homebrew_config: record
|
|
] -> string {
|
|
# Generate download URLs and checksums for different platforms
|
|
let platforms = ["linux", "macos"]
|
|
let mut platform_blocks = []
|
|
|
|
for platform in $platforms {
|
|
let download_url = $"https://github.com/your-org/provisioning/releases/download/v($registry_config.version)/provisioning-($registry_config.version)-($platform)-complete.tar.gz"
|
|
|
|
# In a real implementation, you would download and calculate actual SHA256
|
|
let sha256 = "placeholder_sha256_hash_would_be_calculated_here"
|
|
|
|
let platform_block = match $platform {
|
|
"linux" => {
|
|
$" on_linux do
|
|
url \"($download_url)\"
|
|
sha256 \"($sha256)\"
|
|
end"
|
|
}
|
|
"macos" => {
|
|
$" on_macos do
|
|
url \"($download_url)\"
|
|
sha256 \"($sha256)\"
|
|
end"
|
|
}
|
|
_ => ""
|
|
}
|
|
|
|
$platform_blocks = ($platform_blocks | append $platform_block)
|
|
}
|
|
|
|
let formula = $"class ($homebrew_config.formula_name | str title-case) < Formula
|
|
desc \"($homebrew_config.description)\"
|
|
homepage \"($homebrew_config.homepage)\"
|
|
license \"($homebrew_config.license)\"
|
|
version \"($registry_config.version)\"
|
|
|
|
($platform_blocks | str join "\n\n")
|
|
|
|
def install
|
|
# Install binaries
|
|
bin.install Dir[\"platform/*\"]
|
|
|
|
# Install libraries
|
|
libexec.install Dir[\"core/*\"]
|
|
|
|
# Install configuration
|
|
etc.install Dir[\"config/*\"] => \"provisioning\"
|
|
|
|
# Create wrapper scripts
|
|
(bin/\"provisioning\").write_env_script libexec/\"bin/provisioning\", PROVISIONING_HOME: libexec
|
|
end
|
|
|
|
test do
|
|
system \"#{bin}/provisioning\", \"version\"
|
|
end
|
|
end
|
|
"
|
|
|
|
return $formula
|
|
}
|
|
|
|
# Update APT repository
|
|
def update_apt_repository [
|
|
registry_config: record
|
|
config_data: record
|
|
] -> record {
|
|
log info "Updating APT repository..."
|
|
|
|
let start_time = (date now)
|
|
|
|
if $registry_config.dry_run {
|
|
return {
|
|
registry: "apt"
|
|
status: "success"
|
|
version: $registry_config.version
|
|
dry_run: true
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
|
|
# APT repository update would involve:
|
|
# 1. Upload .deb packages to repository
|
|
# 2. Update Packages index
|
|
# 3. Sign repository with GPG key
|
|
# 4. Update Release file
|
|
|
|
log warning "APT repository update not fully implemented"
|
|
|
|
{
|
|
registry: "apt"
|
|
status: "skipped"
|
|
reason: "not fully implemented"
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
|
|
# Update YUM repository
|
|
def update_yum_repository [
|
|
registry_config: record
|
|
config_data: record
|
|
] -> record {
|
|
log info "Updating YUM repository..."
|
|
|
|
let start_time = (date now)
|
|
|
|
if $registry_config.dry_run {
|
|
return {
|
|
registry: "yum"
|
|
status: "success"
|
|
version: $registry_config.version
|
|
dry_run: true
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
|
|
# YUM repository update would involve:
|
|
# 1. Upload .rpm packages to repository
|
|
# 2. Run createrepo to update metadata
|
|
# 3. Sign packages with GPG key
|
|
|
|
log warning "YUM repository update not fully implemented"
|
|
|
|
{
|
|
registry: "yum"
|
|
status: "skipped"
|
|
reason: "not fully implemented"
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
|
|
# Update Docker registry
|
|
def update_docker_registry [
|
|
registry_config: record
|
|
config_data: record
|
|
] -> record {
|
|
log info "Updating Docker registry..."
|
|
|
|
let start_time = (date now)
|
|
let docker_config = ($config_data.docker)
|
|
|
|
if $registry_config.dry_run {
|
|
return {
|
|
registry: "docker"
|
|
status: "success"
|
|
image: $"($docker_config.namespace)/($docker_config.image_name):($registry_config.version)"
|
|
dry_run: true
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
|
|
# Docker registry update would involve:
|
|
# 1. Tag images with new version
|
|
# 2. Push to registry
|
|
# 3. Update image descriptions and README
|
|
|
|
log warning "Docker registry update not fully implemented"
|
|
|
|
{
|
|
registry: "docker"
|
|
status: "skipped"
|
|
reason: "not fully implemented"
|
|
image: $"($docker_config.namespace)/($docker_config.image_name):($registry_config.version)"
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
|
|
# Update npm registry
|
|
def update_npm_registry [
|
|
registry_config: record
|
|
config_data: record
|
|
] -> record {
|
|
log info "Updating npm registry..."
|
|
|
|
let start_time = (date now)
|
|
let npm_config = ($config_data.npm)
|
|
|
|
if $registry_config.dry_run {
|
|
return {
|
|
registry: "npm"
|
|
status: "success"
|
|
package: $"($npm_config.scope)/($npm_config.package_name)"
|
|
version: $registry_config.version
|
|
dry_run: true
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
|
|
# npm registry update would involve:
|
|
# 1. Update package.json with new version
|
|
# 2. Build package if needed
|
|
# 3. Publish to npm registry
|
|
|
|
log warning "npm registry update not fully implemented"
|
|
|
|
{
|
|
registry: "npm"
|
|
status: "skipped"
|
|
reason: "not fully implemented"
|
|
package: $"($npm_config.scope)/($npm_config.package_name)"
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
|
|
# Update Cargo registry
|
|
def update_cargo_registry [
|
|
registry_config: record
|
|
config_data: record
|
|
] -> record {
|
|
log info "Updating Cargo registry..."
|
|
|
|
let start_time = (date now)
|
|
let cargo_config = ($config_data.cargo)
|
|
|
|
if $registry_config.dry_run {
|
|
return {
|
|
registry: "cargo"
|
|
status: "success"
|
|
crate: $cargo_config.crate_name
|
|
version: $registry_config.version
|
|
dry_run: true
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
|
|
# Cargo registry update would involve:
|
|
# 1. Update Cargo.toml with new version
|
|
# 2. Publish to crates.io
|
|
|
|
log warning "Cargo registry update not fully implemented"
|
|
|
|
{
|
|
registry: "cargo"
|
|
status: "skipped"
|
|
reason: "not fully implemented"
|
|
crate: $cargo_config.crate_name
|
|
duration: ((date now) - $start_time)
|
|
}
|
|
}
|
|
|
|
# Show registry status
|
|
def "main status" [] {
|
|
let homebrew_available = (try { brew --version | complete } catch { { exit_code: 1 } }).exit_code == 0
|
|
let docker_available = (try { docker --version | complete } catch { { exit_code: 1 } }).exit_code == 0
|
|
let npm_available = (try { npm --version | complete } catch { { exit_code: 1 } }).exit_code == 0
|
|
let cargo_available = (try { cargo --version | complete } catch { { exit_code: 1 } }).exit_code == 0
|
|
|
|
let repo_root = ($env.PWD | path dirname | path dirname | path dirname)
|
|
let current_version = (detect_current_version $repo_root)
|
|
|
|
{
|
|
current_version: $current_version
|
|
available_tools: {
|
|
homebrew: $homebrew_available
|
|
docker: $docker_available
|
|
npm: $npm_available
|
|
cargo: $cargo_available
|
|
}
|
|
supported_registries: ["homebrew", "apt", "yum", "docker", "npm", "cargo"]
|
|
implemented_registries: ["homebrew"] # Only homebrew is fully implemented
|
|
}
|
|
}
|
|
|
|
# Generate registry configuration template
|
|
def "main init-config" [output_file: string = "registry-config.toml"] {
|
|
let config_template = $"# Registry Configuration for Package Distribution
|
|
|
|
[homebrew]
|
|
tap_repo = \"your-org/homebrew-tap\"
|
|
formula_name = \"provisioning\"
|
|
description = \"Cloud-native infrastructure provisioning and management system\"
|
|
homepage = \"https://github.com/your-org/provisioning\"
|
|
license = \"MIT\"
|
|
|
|
[apt]
|
|
repository = \"https://apt.your-org.com/ubuntu\"
|
|
distribution = \"stable\"
|
|
component = \"main\"
|
|
keyring = \"/usr/share/keyrings/your-org-archive-keyring.gpg\"
|
|
|
|
[yum]
|
|
repository = \"https://yum.your-org.com/centos\"
|
|
gpg_key = \"https://yum.your-org.com/RPM-GPG-KEY-your-org\"
|
|
|
|
[docker]
|
|
registry = \"docker.io\"
|
|
namespace = \"your-org\"
|
|
image_name = \"provisioning\"
|
|
|
|
[npm]
|
|
registry = \"https://registry.npmjs.org\"
|
|
scope = \"@your-org\"
|
|
package_name = \"provisioning\"
|
|
|
|
[cargo]
|
|
registry = \"https://crates.io\"
|
|
crate_name = \"provisioning\"
|
|
"
|
|
|
|
$config_template | save $output_file
|
|
log info $"Generated registry configuration template: ($output_file)"
|
|
|
|
{
|
|
config_file: $output_file
|
|
registries_configured: 6
|
|
template_generated: true
|
|
}
|
|
}
|
|
|
|
# Validate registry configuration
|
|
def "main validate" [config_file: string = "registry-config.toml"] {
|
|
let config_path = ($config_file | path expand)
|
|
|
|
if not ($config_path | path exists) {
|
|
return {
|
|
status: "failed"
|
|
reason: $"Configuration file not found: ($config_path)"
|
|
}
|
|
}
|
|
|
|
try {
|
|
let config = (open $config_path)
|
|
let expected_sections = ["homebrew", "apt", "yum", "docker", "npm", "cargo"]
|
|
let mut validation_results = []
|
|
|
|
for section in $expected_sections {
|
|
let section_exists = ($section in ($config | columns))
|
|
$validation_results = ($validation_results | append {
|
|
section: $section
|
|
exists: $section_exists
|
|
status: (if $section_exists { "valid" } else { "missing" })
|
|
})
|
|
}
|
|
|
|
let valid_sections = ($validation_results | where status == "valid" | length)
|
|
let total_sections = ($validation_results | length)
|
|
|
|
{
|
|
status: "success"
|
|
config_file: $config_path
|
|
valid_sections: $valid_sections
|
|
total_sections: $total_sections
|
|
validation_results: $validation_results
|
|
}
|
|
|
|
} catch {|err|
|
|
{
|
|
status: "failed"
|
|
reason: $"Failed to validate configuration: ($err.msg)"
|
|
}
|
|
}
|
|
} |