Documentation
¶
Index ¶
- func CleanupExtractedFiles(destDir string) error
- func CompareVersions(v1, v2 string) int
- func ExtractArchive(archivePath, destDir string) (string, error)
- func FindBinaryInDirectory(dir string) (string, error)
- func GetCurrentVersion() string
- func GetFileHash(filePath, hashAlgorithm string) (string, error)
- func IsNewerVersion(currentVersion, newVersion string) bool
- func IsValidUpdateChannel(channel string) bool
- func VerifyChecksum(filePath, expectedChecksum, hashAlgorithm string) (bool, error)
- func VerifyFileSize(filePath string, expectedSize int64) (bool, error)
- type Config
- type DownloadProgress
- type Downloader
- type GitHubClient
- func (gc *GitHubClient) CreateIssue(ctx context.Context, title, body string, labels []string) (*GitHubIssue, error)
- func (gc *GitHubClient) GetAllReleases(ctx context.Context) ([]GitHubRelease, error)
- func (gc *GitHubClient) GetLatestRelease(ctx context.Context, channel string) (*GitHubRelease, error)
- func (gc *GitHubClient) GetNewestValidRelease(ctx context.Context, channel string) (*GitHubRelease, error)
- func (gc *GitHubClient) IssueExists(ctx context.Context, title string) (bool, error)
- func (gc *GitHubClient) ReportError(ctx context.Context, err error, nodeVersion, nodeOS, nodeArch string) error
- func (gc *GitHubClient) SetToken(token string)
- type GitHubIssue
- type GitHubRelease
- type RateLimiter
- type ReleaseVerifier
- type UpdateStatus
- type Updater
- func (u *Updater) CheckForUpdate()
- func (u *Updater) GetStatus() UpdateStatus
- func (u *Updater) InstallUpdate()
- func (u *Updater) RestartNode() error
- func (u *Updater) SetOnUpdateAvailable(callback func(version string))
- func (u *Updater) SetOnUpdateComplete(callback func(newVersion string, err error))
- func (u *Updater) SetOnUpdateProgress(callback func(progress float64))
- func (u *Updater) Start()
- func (u *Updater) Stop()
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CleanupExtractedFiles ¶
CleanupExtractedFiles removes the extracted files
func CompareVersions ¶
CompareVersions compares two version strings (simple semantic version comparison) Returns 1 if v1 > v2, -1 if v1 < v2, 0 if equal
func ExtractArchive ¶
ExtractArchive extracts a tar.gz or zip archive to a destination directory
func FindBinaryInDirectory ¶
FindBinaryInDirectory searches for an executable binary in a directory
func GetCurrentVersion ¶
func GetCurrentVersion() string
GetCurrentVersion returns the current version from the running binary
func GetFileHash ¶
GetFileHash calculates the hash of a file
func IsNewerVersion ¶
IsNewerVersion checks if newVersion is newer than currentVersion
func IsValidUpdateChannel ¶
IsValidUpdateChannel checks if the update channel is valid
func VerifyChecksum ¶
VerifyChecksum verifies a file against a expected checksum The hashAlgorithm can be "sha256" or "sha512"
Types ¶
type Config ¶
type Config struct {
// Enabled determines if auto-update is active
Enabled bool
// CheckInterval is how often to check for updates
CheckInterval time.Duration
// GitHubOwner is the GitHub repository owner (default: HoosatNetwork)
GitHubOwner string
// GitHubRepo is the GitHub repository name (default: HTND)
GitHubRepo string
// UpdateChannel determines which releases to consider:
// "stable" - only tagged releases (default)
// "beta" - include pre-releases
// "all" - include all releases including drafts
UpdateChannel string
// AutoDownload determines if updates should be downloaded automatically
// If false, only notifications will be logged
AutoDownload bool
// AutoInstall determines if updates should be installed automatically
// If false, downloads will be stored but not installed
// Requires AutoDownload to be true
AutoInstall bool
// NotifyOnly determines if the updater should only log notifications
// without performing any actions (overrides AutoDownload and AutoInstall)
NotifyOnly bool
// InstallDelayMin is the minimum random delay before auto-installing
InstallDelayMin time.Duration
// InstallDelayMax is the maximum random delay before auto-installing
InstallDelayMax time.Duration
// GitHubToken is a personal access token for auto-filing error reports
// Requires 'repo' scope. If empty, error reporting is disabled.
GitHubToken string
// AutoReportIssues determines if issues should be automatically reported to GitHub
// When enabled (default), panics and update errors will create GitHub issues
// Requires GitHubToken to be set for reporting to work
AutoReportIssues bool
// ReleasePublicKey is the hex-encoded ed25519 public key that release checksum lists are
// signed with. Empty falls back to the build's pinnedReleasePublicKey, which is itself empty
// unless a release captain set it - see verify.go.
ReleasePublicKey string
// AllowUnverifiedInstall permits installing an archive whose authenticity was never
// established. It exists only because no signing key ships in this repository; it must never
// be on by default. See ReleaseVerifier.
AllowUnverifiedInstall bool
}
Config holds the configuration for the auto-updater
func DefaultConfig ¶
func DefaultConfig() *Config
DefaultConfig returns the default auto-update configuration
type DownloadProgress ¶
type DownloadProgress struct {
TotalBytes int64
Downloaded int64
Percentage float64
SpeedBytesPS float64
}
DownloadProgress represents the progress of a download
type Downloader ¶
type Downloader struct {
// contains filtered or unexported fields
}
Downloader handles downloading and verifying update files
func (*Downloader) DownloadFile ¶
DownloadFile downloads a file from a URL to a destination path Returns the path to the downloaded file and any error
type GitHubClient ¶
type GitHubClient struct {
// contains filtered or unexported fields
}
GitHubClient handles communication with GitHub API
func NewGitHubClient ¶
func NewGitHubClient(owner, repo string) *GitHubClient
NewGitHubClient creates a new GitHub API client
func (*GitHubClient) CreateIssue ¶
func (gc *GitHubClient) CreateIssue(ctx context.Context, title, body string, labels []string) (*GitHubIssue, error)
CreateIssue creates a new GitHub issue (requires token)
func (*GitHubClient) GetAllReleases ¶
func (gc *GitHubClient) GetAllReleases(ctx context.Context) ([]GitHubRelease, error)
GetAllReleases fetches all releases from GitHub
func (*GitHubClient) GetLatestRelease ¶
func (gc *GitHubClient) GetLatestRelease(ctx context.Context, channel string) (*GitHubRelease, error)
GetLatestRelease fetches the latest release from GitHub
func (*GitHubClient) GetNewestValidRelease ¶
func (gc *GitHubClient) GetNewestValidRelease(ctx context.Context, channel string) (*GitHubRelease, error)
GetNewestValidRelease returns the newest release that matches the channel criteria
func (*GitHubClient) IssueExists ¶
IssueExists checks if an issue with the same title already exists
func (*GitHubClient) ReportError ¶
func (gc *GitHubClient) ReportError(ctx context.Context, err error, nodeVersion, nodeOS, nodeArch string) error
ReportError files a GitHub issue if it doesn't already exist on GitHub
func (*GitHubClient) SetToken ¶
func (gc *GitHubClient) SetToken(token string)
SetToken configures GitHub authentication for issue reporting
type GitHubIssue ¶
type GitHubIssue struct {
Title string `json:"title"`
Body string `json:"body"`
Labels []string `json:"labels"`
}
GitHubIssue represents a GitHub issue
type GitHubRelease ¶
type GitHubRelease struct {
TagName string `json:"tag_name"`
Name string `json:"name"`
PublishedAt time.Time `json:"published_at"`
Prerelease bool `json:"prerelease"`
Draft bool `json:"draft"`
Assets []struct {
Name string `json:"name"`
DownloadURL string `json:"browser_download_url"`
Size int64 `json:"size"`
} `json:"assets"`
}
GitHubRelease represents a GitHub release API response
func (*GitHubRelease) GetAssetForPlatform ¶
func (release *GitHubRelease) GetAssetForPlatform() (string, string, error)
GetAssetForPlatform returns the download URL for the asset matching the current platform
type RateLimiter ¶
type RateLimiter struct {
// contains filtered or unexported fields
}
RateLimiter implements a simple rate limiter for GitHub API
func NewRateLimiter ¶
func NewRateLimiter(minInterval time.Duration) *RateLimiter
NewRateLimiter creates a new rate limiter
type ReleaseVerifier ¶
type ReleaseVerifier struct {
// contains filtered or unexported fields
}
ReleaseVerifier decides whether a downloaded release archive may be installed.
The rule it enforces is HTN-162's: no unsigned archive installs. An archive is installable only when its SHA-256 appears in a checksum list that carries a valid ed25519 signature from the pinned key. Everything else - no key configured, no checksum asset, no signature asset, a bad signature, a checksum that does not match, an asset name absent from the list - is a refusal.
The single deliberate escape hatch is allowUnverified, which an operator must set explicitly. It exists because this repository ships no key (see pinnedReleasePublicKey), so without it the feature would be unusable for anyone running their own builds rather than the project's releases.
func NewReleaseVerifier ¶
func NewReleaseVerifier(publicKeyHex string, allowUnverified bool) (*ReleaseVerifier, error)
NewReleaseVerifier builds a verifier from a hex-encoded ed25519 public key. An empty publicKeyHex falls back to pinnedReleasePublicKey, which is itself empty unless a release captain has set it.
func (*ReleaseVerifier) HasPinnedKey ¶
func (v *ReleaseVerifier) HasPinnedKey() bool
HasPinnedKey reports whether a key is configured at all.
func (*ReleaseVerifier) VerifyArchive ¶
func (v *ReleaseVerifier) VerifyArchive(ctx context.Context, fetch assetFetcher, release *GitHubRelease, assetName, archivePath, workDir string) error
VerifyArchive returns nil only if archivePath may be installed.
workDir is where the checksum and signature assets are downloaded to; the caller owns it.
type UpdateStatus ¶
type UpdateStatus struct {
CurrentVersion string
LatestVersion string
AvailableVersion string
LastCheckTime time.Time
LastCheckError string
UpdateInProgress bool
DownloadProgress float64
DownloadCompleted bool
InstallPending bool
LastUpdateError string
}
UpdateStatus represents the current status of the updater
type Updater ¶
type Updater struct {
// contains filtered or unexported fields
}
Updater is the main auto-update manager
func NewUpdater ¶
NewUpdater creates a new auto-updater instance
func (*Updater) CheckForUpdate ¶
func (u *Updater) CheckForUpdate()
CheckForUpdate manually triggers an update check
func (*Updater) GetStatus ¶
func (u *Updater) GetStatus() UpdateStatus
GetStatus returns the current update status
func (*Updater) InstallUpdate ¶
func (u *Updater) InstallUpdate()
InstallUpdate manually triggers the installation of a downloaded update
func (*Updater) RestartNode ¶
RestartNode asks the node to shut down gracefully so that whatever supervises it can start the replacement binary, which installBinary has already put in place.
HTN-164: this used to exec a second htnd and then call os.Exit(0). Both halves were wrong. The new process started while this one still held the database lock, so the replacement raced the incumbent for a datadir that was still open; and os.Exit(0) skipped every deferred shutdown in app.main - componentManager.Stop and, critically, databaseContext.Close - so the database was left to whatever pebble could recover from its WAL rather than being closed cleanly. An update was therefore most likely to corrupt or lock out the datadir at exactly the moment the operator was least watching.
Requesting shutdown through signal.ShutdownRequestChannel is the same path the ShutDown RPC uses. The listener accepts repeated requests, so this cannot panic the way closing a channel directly did before HTN-141.
htnd deliberately does not start its own replacement. A process cannot hand its database lock to a child it spawns before exiting, and any attempt to sequence that is a race. The supervisor owns the new process: systemd's Restart=always, a docker restart policy, or an equivalent.
func (*Updater) SetOnUpdateAvailable ¶
SetOnUpdateAvailable sets the callback for when an update is available
func (*Updater) SetOnUpdateComplete ¶
SetOnUpdateComplete sets the callback for when update is complete
func (*Updater) SetOnUpdateProgress ¶
SetOnUpdateProgress sets the callback for update progress