mirror of
https://github.com/luxfi/cli.git
synced 2026-10-30 17:01:20 +00:00
Deep audit changes: - Replace stub signature aggregator with real SDK warp implementation - Remove dead pkg/lpm package (SDK lpmintegration used instead) - Fix fs imports: use local utils.FileExists, DirExists, ExpandHome - Fix secp256k1fx imports: use node/vms/secp256k1fx - Fix platformvm imports: use node/vms/platformvm - Fix e2e test TODOs: uncomment BootstrapValidators assertions - Improve localnet stub implementations with real logic - Fix node.go fs.FileExists reference Note: Build requires GOWORK=off due to workspace dependency issues
146 lines
4.1 KiB
Go
146 lines
4.1 KiB
Go
// Copyright (C) 2022-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
// Package chain provides chain deployment and management utilities.
|
|
package chain
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
git "github.com/go-git/go-git/v5"
|
|
"github.com/go-git/go-git/v5/config"
|
|
"github.com/go-git/go-git/v5/plumbing/object"
|
|
"github.com/luxfi/cli/pkg/ux"
|
|
"github.com/luxfi/constants"
|
|
)
|
|
|
|
// Publisher defines the interface for publishing chain and VM configurations to a git repository.
|
|
type Publisher interface {
|
|
// Publish commits and pushes chain and VM YAML configurations to the repository.
|
|
Publish(r *git.Repository, chainName, vmName string, chainYAML []byte, vmYAML []byte) error
|
|
// GetRepo returns the git repository, cloning it if necessary.
|
|
GetRepo() (*git.Repository, error)
|
|
}
|
|
|
|
type publisherImpl struct {
|
|
alias string
|
|
repoURL string
|
|
repoPath string
|
|
}
|
|
|
|
var _ Publisher = &publisherImpl{}
|
|
|
|
// NewPublisher creates a new Publisher instance for the given repository.
|
|
func NewPublisher(repoDir, repoURL, alias string) Publisher {
|
|
repoPath := filepath.Join(repoDir, alias)
|
|
return &publisherImpl{
|
|
alias: alias,
|
|
repoURL: repoURL,
|
|
repoPath: repoPath,
|
|
}
|
|
}
|
|
|
|
// GetRepo returns the git repository, opening it if it exists locally or cloning it otherwise.
|
|
func (p *publisherImpl) GetRepo() (repo *git.Repository, err error) {
|
|
// path exists
|
|
if _, err := os.Stat(p.repoPath); err == nil {
|
|
return git.PlainOpen(p.repoPath)
|
|
}
|
|
return git.PlainClone(p.repoPath, false, &git.CloneOptions{
|
|
URL: p.repoURL,
|
|
Progress: os.Stdout,
|
|
})
|
|
}
|
|
|
|
// Publish writes the chain and VM YAML files to the repository,
|
|
// commits the changes, and pushes to the remote.
|
|
func (p *publisherImpl) Publish(
|
|
repo *git.Repository,
|
|
chainName, vmName string,
|
|
chainYAML []byte,
|
|
vmYAML []byte,
|
|
) error {
|
|
wt, err := repo.Worktree()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// Determine the correct path based on repo structure
|
|
chainPath := getChainPath(p.repoPath, chainName)
|
|
if err := os.MkdirAll(filepath.Dir(chainPath), constants.DefaultPerms755); err != nil {
|
|
return err
|
|
}
|
|
vmPath := filepath.Join(p.repoPath, constants.VMDir, vmName+constants.YAMLSuffix)
|
|
if err := os.MkdirAll(filepath.Dir(vmPath), constants.DefaultPerms755); err != nil {
|
|
return err
|
|
}
|
|
if err := os.WriteFile(chainPath, chainYAML, constants.DefaultPerms755); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := os.WriteFile(vmPath, vmYAML, constants.DefaultPerms755); err != nil {
|
|
return err
|
|
}
|
|
|
|
ux.Logger.PrintToUser("Adding resources to local git repo...")
|
|
|
|
if _, err := wt.Add("chains"); err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := wt.Add("vms"); err != nil {
|
|
return err
|
|
}
|
|
|
|
ux.Logger.PrintToUser("Committing resources to local git repo...")
|
|
now := time.Now()
|
|
commitStr := fmt.Sprintf("commit-%s", now.String())
|
|
|
|
// use the global git config to try identifying the author
|
|
conf, err := config.LoadConfig(config.GlobalScope)
|
|
authorName := conf.Author.Name
|
|
authorEmail := conf.Author.Email
|
|
if err != nil || authorName == "" || authorEmail == "" { // a commit must have both
|
|
authorName = constants.GitRepoCommitName
|
|
authorEmail = constants.GitRepoCommitEmail
|
|
}
|
|
|
|
commit, err := wt.Commit(commitStr, &git.CommitOptions{
|
|
Author: &object.Signature{
|
|
Name: authorName,
|
|
Email: authorEmail,
|
|
When: now,
|
|
},
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := repo.CommitObject(commit); err != nil {
|
|
return err
|
|
}
|
|
|
|
ux.Logger.PrintToUser("Pushing to remote...")
|
|
return repo.Push(&git.PushOptions{})
|
|
}
|
|
|
|
// getChainPath determines the correct path for the chain file based on repository structure
|
|
func getChainPath(repoPath, chainName string) string {
|
|
// Check if the repository has a custom structure
|
|
customPath := filepath.Join(repoPath, "chains", chainName+constants.YAMLSuffix)
|
|
if _, err := os.Stat(filepath.Dir(customPath)); err == nil {
|
|
return customPath
|
|
}
|
|
|
|
// Check for legacy structure
|
|
legacyPath := filepath.Join(repoPath, "chain", chainName+constants.YAMLSuffix)
|
|
if _, err := os.Stat(filepath.Dir(legacyPath)); err == nil {
|
|
return legacyPath
|
|
}
|
|
|
|
// Default to the standard structure
|
|
return filepath.Join(repoPath, constants.ChainsDir, chainName+constants.YAMLSuffix)
|
|
}
|