### Install detect-latest-release CLI Source: https://github.com/creativeprojects/go-selfupdate/blob/main/cmd/detect-latest-release/README.md Install the command-line tool using the go get command. ```bash $ go get -u github.com/creativeprojects/go-selfupdate/cmd/detect-latest-release ``` -------------------------------- ### Example: Install ghr Binary Source: https://github.com/creativeprojects/go-selfupdate/blob/main/cmd/get-release/README.md Demonstrates downloading and installing the latest release of the ghr binary from GitHub to your $GOPATH/bin directory. Verifies the installation by checking the version. ```bash $ get-release github.com/tcnksm/ghr Command was updated to the latest version 0.5.4: /Users/you/.go/bin/ghr $ ghr -version ghr version v0.5.4 (a12ff1c) ``` -------------------------------- ### Install get-release CLI Source: https://github.com/creativeprojects/go-selfupdate/blob/main/cmd/get-release/README.md Install the get-release command-line tool using go get. This command updates the tool to the latest version. ```bash $ go get -u github.com/creativeprojects/go-selfupdate/cmd/get-release ``` -------------------------------- ### Windows Binary Naming Convention Example (Shell) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Demonstrates the naming convention for Windows release assets, including the optional '.exe' extension before the archive extension. ```shell # foo-bar_windows_amd64.exe.zip ``` -------------------------------- ### Download and Install Latest Release Source: https://github.com/creativeprojects/go-selfupdate/blob/main/cmd/get-release/README.md Use the get-release command followed by the package name to download and install the latest release of a binary. Ensure the package follows Git tag and release naming rules. ```bash $ get-release {package} ``` -------------------------------- ### Get detect-latest-release Usage Source: https://github.com/creativeprojects/go-selfupdate/blob/main/cmd/detect-latest-release/README.md Run the command without any arguments to display its usage instructions. ```bash $ detect-latest-release ``` -------------------------------- ### Binary Naming Convention Example (Shell) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Illustrates the expected naming format for released binaries, including command name, OS, architecture, and optional compression extensions. Supports '-' as a separator. ```shell # {cmd}_{goos}_{goarch}{.ext} # foo-bar_linux_amd64 # foo-bar_linux_amd64.zip # foo-bar_linux_amd64.tar.gz # foo-bar_linux_amd64.xz # foo-bar-linux-amd64.tar.gz ``` -------------------------------- ### Update using HTTP Source in Go Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md This example demonstrates self-updating from an HTTP-based repository, suitable for private or non-open-source projects. It requires a checksums.txt file and allows custom headers for authentication. ```go func update() { ssource, err := selfupdate.NewHttpSource(selfupdate.HttpConfig{ BaseURL: "https://example.com/", }) if err != nil { log.Fatal(err) } updater, err := selfupdate.NewUpdater(selfupdate.Config{ Source: source, Validator: &selfupdate.ChecksumValidator{UniqueFilename: "checksums.txt"}, // checksum from goreleaser }) if err != nil { log.Fatal(err) } release, found, err := updater.DetectLatest(context.Background(), selfupdate.NewRepositorySlug("repo", "project")) if err != nil { log.Fatal(err) } if !found { log.Print("Release not found") return } fmt.Printf("found release %s\n", release.Version()) exe, err := selfupdate.ExecutablePath() if err != nil { return errors.New("could not locate executable path") } err = updater.UpdateTo(context.Background(), release, exe) if err != nil { log.Fatal(err) } } ``` -------------------------------- ### Archive Naming Convention Example (Shell) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Shows the naming convention for executables within compressed or archived release assets. The executable should be named after the command, potentially including OS and architecture. ```shell # foo-bar # foo-bar_linux_amd64 # foo-bar-linux-amd64 ``` -------------------------------- ### Get Default GitHub Updater Instance Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Use DefaultUpdater to retrieve a cached *Updater instance with default GitHub configuration. It automatically reads the $GITHUB_TOKEN environment variable for authentication. ```go up := selfupdate.DefaultUpdater() release, found, err := up.DetectLatest(context.Background(), selfupdate.ParseSlug("owner/repo")) ``` -------------------------------- ### Generate SHA256 Checksum File Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md To verify integrity using SHA256, generate a hash sum and save it in a file with the same name as the original file, suffixed with .sha256. This example uses the sha256sum command. ```shell sha256sum foo.zip > foo.zip.sha256 ``` -------------------------------- ### Generate ECDSA Signature File Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md To verify a signature using ECDSA, generate a signature and save it in a file with the same name as the original file, suffixed with .sig. This example uses openssl for generation. ```shell openssl dgst -sha256 -sign Test.pem -out foo.zip.sig foo.zip ``` -------------------------------- ### List Releases from Source with Context (Go) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Lists all available releases for a repository, accepting a context for cancellation. Requires a Repository object. ```go ListReleases(ctx context.Context, repository Repository) ([]SourceRelease, error) ``` -------------------------------- ### List Releases from Source (Go) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Lists all available releases for a given owner and repository. Returns a slice of SourceRelease and an error. ```go ListReleases(owner, repo string) ([]SourceRelease, error) ``` -------------------------------- ### Compare Release Versions with Semver Engine Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Use these helpers to compare the current version against a detected latest release. They wrap the internal semver engine, so no external semver package is needed. ```go const currentVersion = "1.1.0" release, found, err := updater.DetectLatest(ctx, selfupdate.ParseSlug("owner/app")) if err != nil || !found { return } fmt.Println(release.Version()) fmt.Println(release.GreaterThan(currentVersion)) fmt.Println(release.LessThan(currentVersion)) fmt.Println(release.Equal(currentVersion)) fmt.Println(release.LessOrEqual(currentVersion)) fmt.Println(release.GreaterOrEqual(currentVersion)) if release.LessOrEqual(currentVersion) { fmt.Println("already up to date") return } ``` -------------------------------- ### Download Release Asset with Context (Go) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Downloads a specific release asset, accepting a context for cancellation. Requires a Release object and asset ID. ```go DownloadReleaseAsset(ctx context.Context, rel *Release, assetID int64) (io.ReadCloser, error) ``` -------------------------------- ### Create Configured Updater Instance Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Use NewUpdater to create an *Updater instance from a Config struct. The Source defaults to GitHub if not specified. Configure validators, filters, and other update behaviors. ```go import ( "context" selfupdate "github.com/creativeprojects/go-selfupdate" ) updater, err := selfupdate.NewUpdater(selfupdate.Config{ // Source defaults to GitHub when omitted. Validator: &selfupdate.ChecksumValidator{UniqueFilename: "checksums.txt"}, Filters: []string{"myapp_"}, // only consider assets whose name contains "myapp_" Prerelease: false, // skip pre-releases Draft: false, // skip drafts OldSavePath: "/tmp/myapp.old", // keep old binary instead of deleting it UniversalArch: "all", // macOS universal binary fallback arch name }) if err != nil { log.Fatal(err) } ``` -------------------------------- ### NewGitLabSource Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Creates a GitLabSource. BaseURL is optional and defaults to gitlab.com. For private GitLab instances using the Generic Package Registry, no extra configuration is needed. The token is read from the GITLAB_TOKEN environment variable if not provided. ```APIDOC ## NewGitLabSource — create a GitLab release source `NewGitLabSource` creates a `*GitLabSource`. `BaseURL` is optional (defaults to `gitlab.com`). For private GitLab instances that use the Generic Package Registry, no extra configuration is needed — assets are accessed by URL. Token is read from `$GITLAB_TOKEN` if not set explicitly. ```go src, err := selfupdate.NewGitLabSource(selfupdate.GitLabConfig{ BaseURL: "https://gitlab.example.com/", APIToken: "glpat-yourtoken", }) if err != nil { log.Fatal(err) } updater, _ := selfupdate.NewUpdater(selfupdate.Config{ Source: src, Validator: &selfupdate.ChecksumValidator{UniqueFilename: "checksums.txt"}, }) release, found, err := updater.DetectLatest( context.Background(), selfupdate.NewRepositoryID(12345), // or NewRepositorySlug("owner", "repo") ) ``` ``` -------------------------------- ### Create RepositorySlug from Owner and Repo Strings Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Use NewRepositorySlug to construct a RepositorySlug from separate owner and repository name strings. ```go repo := selfupdate.NewRepositorySlug("creativeprojects", "resticprofile") owner, name, err := repo.GetSlug() // owner == "creativeprojects", name == "resticprofile", err == nil ``` -------------------------------- ### Create Gitea Release Source Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Use NewGiteaSource to create a Gitea release source. The BaseURL is mandatory, and the token is read from $GITEA_TOKEN if not provided. ```go src, err := selfupdate.NewGiteaSource(selfupdate.GiteaConfig{ BaseURL: "https://gitea.example.com", APIToken: "your-gitea-token", // or set $GITEA_TOKEN }) if err != nil { log.Fatal(err) } updater, _ := selfupdate.NewUpdater(selfupdate.Config{Source: src}) release, found, err := updater.DetectLatest( context.Background(), selfupdate.NewRepositorySlug("owner", "myapp"), ) ``` -------------------------------- ### Detect Specific Version Release with Context (Go) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Detects a specific version of a release for a repository, accepting a context for cancellation. Requires a Repository object and version string. ```go DetectVersion(ctx context.Context, repository Repository, version string) (*Release, bool, error) ``` -------------------------------- ### Update Command with Context (Go) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Determines the appropriate release to update to, accepting a context for cancellation. Requires command path, current version, and a Repository object. ```go UpdateCommand(ctx context.Context, cmdPath string, current string, repository Repository) (*Release, error) ``` -------------------------------- ### Update Binary to Specific Release with Context (Go) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Updates the current binary to a specific release, accepting a context for cancellation. Requires a Release object and command path. ```go UpdateTo(ctx context.Context, rel *Release, cmdPath string) error ``` -------------------------------- ### Download and Replace Binary with Updater.UpdateTo Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt This method downloads a release asset, optionally validates it, decompresses it, and atomically replaces the current binary. It includes rollback functionality on failure. ```go exe, err := selfupdate.ExecutablePath() if err != nil { return fmt.Errorf("could not find executable: %w", err) } release, found, err := updater.DetectLatest(ctx, selfupdate.ParseSlug("owner/myapp")) if err != nil || !found { return } if release.LessOrEqual("1.2.0") { fmt.Println("already up to date") return } if err := updater.UpdateTo(ctx, release, exe); err != nil { if rbErr := update.RollbackError(err); rbErr != nil { log.Fatalf("FATAL: update failed and rollback failed: %v / %v", err, rbErr) } return fmt.Errorf("update failed (rollback succeeded): %w", err) } fmt.Printf("Updated to %s\n", release.Version()) ``` -------------------------------- ### Detect Latest Release with Context (Go) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Detects the latest available release for a repository, accepting a context for cancellation. Requires a Repository object. ```go DetectLatest(ctx context.Context, repository Repository) (*Release, bool, error) ``` -------------------------------- ### Create GitLab Release Source Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt NewGitLabSource creates a GitLab release source. BaseURL is optional and defaults to gitlab.com. For private instances using the Generic Package Registry, no extra configuration is needed. Token is read from $GITLAB_TOKEN if not set. ```go src, err := selfupdate.NewGitLabSource(selfupdate.GitLabConfig{ BaseURL: "https://gitlab.example.com/", APIToken: "glpat-yourtoken", }) if err != nil { log.Fatal(err) } updater, _ := selfupdate.NewUpdater(selfupdate.Config{ Source: src, Validator: &selfupdate.ChecksumValidator{UniqueFilename: "checksums.txt"}, }) release, found, err := updater.DetectLatest( context.Background(), selfupdate.NewRepositoryID(12345), // or NewRepositorySlug("owner", "repo") ) ``` -------------------------------- ### Configure Universal Binary Fallback for macOS Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Enable fallback to a macOS universal binary if the native architecture is not found. Set the UniversalArch field in the Config struct to 'all' to enable this behavior. ```go updater, _ := NewUpdater(Config{UniversalArch: "all"}) ``` -------------------------------- ### Create Repository Slug (Go) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Constructs a RepositorySlug object from separate owner and repository name strings. Ensures proper formatting for repository identification. ```go func NewRepositorySlug(owner, repo string) RepositorySlug ``` -------------------------------- ### Update Binary with Context (Go) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Updates the current binary to the latest release, accepting a context for operation cancellation. Use this for long-running update operations. ```go UpdateTo(ctx context.Context, assetURL, assetFileName, cmdPath string) error ``` -------------------------------- ### Update Binary to Latest Release (Go) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Updates the current binary to the latest release from a given asset URL and file name. Requires the command path for the binary. ```go UpdateTo(assetURL, assetFileName, cmdPath string) error ``` -------------------------------- ### Methods on Source interface (v1 API) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Interface methods for listing releases and downloading release assets with context support. ```APIDOC ## Methods on Source interface (v1 API) ### Description These methods interact with release sources to list available releases and download assets, supporting context for operations. ### ListReleases Lists all available releases for a given repository. #### Signature ```go func ListReleases(ctx context.Context, repository Repository) ([]SourceRelease, error) ``` ### DownloadReleaseAsset Downloads a specific asset from a release. #### Signature ```go func DownloadReleaseAsset(ctx context.Context, rel *Release, assetID int64) (io.ReadCloser, error) ``` ``` -------------------------------- ### Parse Repository Slug (Go) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Parses a string representing an owner and repository name into a structured format. Use this to standardize repository identification. ```go func ParseSlug(slug string) RepositorySlug ``` -------------------------------- ### NewGiteaSource Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Creates a GiteaSource for self-hosted Gitea instances. The BaseURL is mandatory, and the token is read from the GITEA_TOKEN environment variable if not provided. ```APIDOC ## NewGiteaSource — create a Gitea release source `NewGiteaSource` creates a `*GiteaSource` pointing at a self-hosted Gitea instance. The `BaseURL` field is mandatory; the token is read from `$GITEA_TOKEN` if not set explicitly. ```go src, err := selfupdate.NewGiteaSource(selfupdate.GiteaConfig{ BaseURL: "https://gitea.example.com", APIToken: "your-gitea-token", // or set $GITEA_TOKEN }) if err != nil { log.Fatal(err) } updater, _ := selfupdate.NewUpdater(selfupdate.Config{Source: src}) release, found, err := updater.DetectLatest( context.Background(), selfupdate.NewRepositorySlug("owner", "myapp"), ) ``` ``` -------------------------------- ### Update Command with Current Version (Go) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Determines the appropriate release to update to based on the current command path and repository slug. Returns the target release and an error. ```go UpdateCommand(cmdPath string, current string, slug string) (*Release, error) ``` -------------------------------- ### NewHttpSource Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Creates an HttpSource that fetches a manifest.yaml from a custom HTTP server compatible with goreleaser-http-repo-builder. Custom headers can be used for authentication. ```APIDOC ## NewHttpSource — create an HTTP-based release source `NewHttpSource` creates a `*HttpSource` that fetches a `manifest.yaml` from a custom HTTP server compatible with [goreleaser-http-repo-builder](https://github.com/GRMrGecko/goreleaser-http-repo-builder). Custom headers enable authentication. ```go headers := http.Header{} headers.Set("Authorization", "Bearer secrettoken") src, err := selfupdate.NewHttpSource(selfupdate.HttpConfig{ BaseURL: "https://updates.example.com/", Headers: headers, }) if err != nil { log.Fatal(err) } updater, _ := selfupdate.NewUpdater(selfupdate.Config{Source: src}) // fetches https://updates.example.com/owner/myapp/manifest.yaml release, found, err := updater.DetectLatest( context.Background(), selfupdate.NewRepositorySlug("owner", "myapp"), ) ``` ``` -------------------------------- ### Package-level DetectVersion Shortcut Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Package-level DetectVersion uses the DefaultUpdater for concise one-liner usage when no custom configuration is needed, allowing detection of a specific version. ```go specificRelease, found, err := selfupdate.DetectVersion( context.Background(), selfupdate.ParseSlug("creativeprojects/resticprofile"), "v0.27.0", ) ``` -------------------------------- ### Detect Specific Version Release (Go) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Detects a specific version of a release for a given repository slug and version string. Returns the release information, a boolean indicating if found, and an error. ```go DetectVersion(slug string, version string) (*Release, bool, error) ``` -------------------------------- ### Update Self with Current Version (Go) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Initiates a self-update process based on the current version and repository slug. Returns the target release and an error. ```go UpdateSelf(current string, slug string) (*Release, error) ``` -------------------------------- ### Download Release Asset (Go) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Downloads a specific release asset identified by its ID for a given owner and repository. Returns an io.ReadCloser and an error. ```go DownloadReleaseAsset(owner, repo string, releaseID, id int64) (io.ReadCloser, error) ``` -------------------------------- ### Update Self with Context (Go) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Initiates a self-update process, accepting a context for cancellation. Requires current version and a Repository object. ```go UpdateSelf(ctx context.Context, current string, repository Repository) (*Release, error) ``` -------------------------------- ### ExecutablePath Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt ExecutablePath resolves and returns the absolute path of the running binary, handling symbolic links. ```APIDOC ## ExecutablePath ### Description `ExecutablePath` returns the absolute path of the current executable, resolving symlinks. It is used internally by `UpdateSelf` and is exported for use in custom update flows. ### Usage Example ```go exe, err := selfupdate.ExecutablePath() if err != nil { return fmt.Errorf("cannot find executable path: %w", err) } fmt.Println("Running from:", exe) // pass to UpdateTo or UpdateCommand: err = updater.UpdateTo(ctx, release, exe) ``` ``` -------------------------------- ### Update using GitLab Source in Go Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Use this snippet to configure and perform self-updates from a GitLab repository. Ensure you have a checksums.txt file generated by goreleaser. ```go func update() { ssource, err := selfupdate.NewGitLabSource(selfupdate.GitLabConfig{ BaseURL: "https://private.instance.on.gitlab.com/", }) if err != nil { log.Fatal(err) } updater, err := selfupdate.NewUpdater(selfupdate.Config{ Source: source, Validator: &selfupdate.ChecksumValidator{UniqueFilename: "checksums.txt"}, // checksum from goreleaser }) if err != nil { log.Fatal(err) } release, found, err := updater.DetectLatest(context.Background(), selfupdate.NewRepositorySlug("owner", "cli-tool")) if err != nil { log.Fatal(err) } if !found { log.Print("Release not found") return } fmt.Printf("found release %s\n", release.Version()) exe, err := selfupdate.ExecutablePath() if err != nil { return errors.New("could not locate executable path") } err = updater.UpdateTo(context.Background(), release, exe) if err != nil { log.Fatal(err) } } ``` -------------------------------- ### Detect Latest and Update with Updater.UpdateCommand Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt This function combines detecting the latest release and updating the binary. It checks if the current version is older than the latest and updates only if necessary. It returns the latest release information. ```go rel, err := updater.UpdateCommand( context.Background(), "/usr/local/bin/myapp", "1.1.0", selfupdate.ParseSlug("owner/myapp"), ) if err != nil { log.Fatalf("update failed: %v", err) } fmt.Printf("Now running version %s\n", rel.Version()) ``` -------------------------------- ### Creating an Updater Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Methods for creating and configuring an Updater instance to manage application updates. ```APIDOC ## NewUpdater — create a configured Updater instance ### Description `NewUpdater` returns an `*Updater` built from a `Config` struct. When `Config.Source` is nil it defaults to GitHub. All detection and update calls are methods on `*Updater`. ### Usage ```go import ( "context" selfupdate "github.com/creativeprojects/go-selfupdate" ) updater, err := selfupdate.NewUpdater(selfupdate.Config{ // Source defaults to GitHub when omitted. Validator: &selfupdate.ChecksumValidator{UniqueFilename: "checksums.txt"}, Filters: []string{"myapp_"}, // only consider assets whose name contains "myapp_" Prerelease: false, // skip pre-releases Draft: false, // skip drafts OldSavePath: "/tmp/myapp.old", // keep old binary instead of deleting it UniversalArch: "all", // macOS universal binary fallback arch name }) if err != nil { log.Fatal(err) } ``` ## DefaultUpdater — singleton updater with default GitHub configuration ### Description `DefaultUpdater` returns a cached `*Updater` using the default GitHub source. It reads `$GITHUB_TOKEN` from the environment. Useful for the simplest GitHub-hosted use cases. ### Usage ```go up := selfupdate.DefaultUpdater() release, found, err := up.DetectLatest(context.Background(), selfupdate.ParseSlug("owner/repo")) ``` ``` -------------------------------- ### Low-Level Package UpdateTo from Direct URL Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt This package-level function allows downloading an update directly from a specified URL without using a source provider. It's suitable for public releases and does not support authentication. ```go exe, _ := selfupdate.ExecutablePath() err := selfupdate.UpdateTo( context.Background(), "https://github.com/owner/repo/releases/download/v1.2.3/myapp_linux_amd64.tar.gz", "myapp_linux_amd64.tar.gz", exe, ) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Package-level DetectLatest Shortcut Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Package-level DetectLatest uses the DefaultUpdater for concise one-liner usage when no custom configuration is needed. ```go release, found, err := selfupdate.DetectLatest( context.Background(), selfupdate.ParseSlug("creativeprojects/resticprofile"), ) if err != nil { return fmt.Errorf("detect: %w", err) } ``` -------------------------------- ### Source Providers Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Configuration options for different release source providers. ```APIDOC ## NewGitHubSource — create a GitHub release source ### Description `NewGitHubSource` creates a `*GitHubSource` that reads releases from GitHub's API. It supports public GitHub, private repos (via `$GITHUB_TOKEN` or `APIToken`), and GitHub Enterprise. ### Usage ```go // Public GitHub with token from environment ($GITHUB_TOKEN) src, err := selfupdate.NewGitHubSource(selfupdate.GitHubConfig{}) // Explicit token src, err = selfupdate.NewGitHubSource(selfupdate.GitHubConfig{ APIToken: "ghp_yourtoken", }) // GitHub Enterprise src, err = selfupdate.NewGitHubSource(selfupdate.GitHubConfig{ EnterpriseBaseURL: "https://github.example.com/api/v3/", EnterpriseUploadURL: "https://github.example.com/api/v3/", APIToken: "ghp_yourtoken", }) if err != nil { log.Fatal(err) } updater, _ := selfupdate.NewUpdater(selfupdate.Config{Source: src}) ``` ``` -------------------------------- ### Update Binary to Specific Release (Go) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Updates the current binary to a specific release identified by a Release object. Requires the command path for the binary. ```go UpdateTo(rel *Release, cmdPath string) error ``` -------------------------------- ### Create GitHub Release Source Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Use NewGitHubSource to create a GitHubSource for reading releases from GitHub's API. Supports public/private repos and GitHub Enterprise. Authentication can be via environment variable ($GITHUB_TOKEN) or an explicit APIToken. ```go // Public GitHub with token from environment ($GITHUB_TOKEN) src, err := selfupdate.NewGitHubSource(selfupdate.GitHubConfig{}) // Explicit token src, err = selfupdate.NewGitHubSource(selfupdate.GitHubConfig{ APIToken: "ghp_yourtoken", }) // GitHub Enterprise src, err = selfupdate.NewGitHubSource(selfupdate.GitHubConfig{ EnterpriseBaseURL: "https://github.example.com/api/v3/", EnterpriseUploadURL: "https://github.example.com/api/v3/", APIToken: "ghp_yourtoken", }) if err != nil { log.Fatal(err) } updater, _ := selfupdate.NewUpdater(selfupdate.Config{Source: src}) ``` -------------------------------- ### Detect Latest Release (Go) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Detects the latest available release for a given repository slug. Returns the release information, a boolean indicating if found, and an error. ```go DetectLatest(slug string) (*Release, bool, error) ``` -------------------------------- ### Create HTTP Release Source Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt NewHttpSource creates an HTTP-based release source for a manifest.yaml from a custom HTTP server. Custom headers can be used for authentication. ```go headers := http.Header{} headers.Set("Authorization", "Bearer secrettoken") src, err := selfupdate.NewHttpSource(selfupdate.HttpConfig{ BaseURL: "https://updates.example.com/", Headers: headers, }) if err != nil { log.Fatal(err) } updater, _ := selfupdate.NewUpdater(selfupdate.Config{Source: src}) // fetches https://updates.example.com/owner/myapp/manifest.yaml release, found, err := updater.DetectLatest( context.Background(), selfupdate.NewRepositorySlug("owner", "myapp"), ) ``` -------------------------------- ### Version Tagging Convention (Text) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Explains the convention for Git tag names, which should correspond to semantic versioning (e.g., '1.2.3' or 'v1.2.3'). Prefixes before the version number are automatically omitted. ```text # 1.2.3 # v1.2.3 # ver1.2.3 # release-1.2.3 ``` -------------------------------- ### Single-File Multi-Asset Checksum Validation (Goreleaser-style) Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt This validator reads a single file (e.g., `checksums.txt`) that lists SHA256 hashes for all assets. Goreleaser produces `checksums.txt` automatically. Errors can include ErrChecksumValidationFailed or ErrHashNotFound. ```go // goreleaser produces checksums.txt automatically updater, _ := selfupdate.NewUpdater(selfupdate.Config{ Validator: &selfupdate.ChecksumValidator{UniqueFilename: "checksums.txt"}, }) release, found, err := updater.DetectLatest(ctx, selfupdate.ParseSlug("owner/myapp")) if err != nil { // could be ErrChecksumValidationFailed or ErrHashNotFound log.Fatal(err) } ``` -------------------------------- ### SetLogger for Redirecting Internal Logs Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Redirect internal logs by providing a compatible Logger interface implementation to SetLogger. The standard library's *log.Logger is compatible. Custom loggers must implement Print and Printf methods. ```go // Use the standard library logger selfupdate.SetLogger(log.Default()) // Or a custom logger type myLogger struct{} func (l *myLogger) Print(v ...any) { fmt.Print(v...) } func (l *myLogger) Printf(f string, v ...any) { fmt.Printf(f, v...) } selfupdate.SetLogger(&myLogger{}) ``` -------------------------------- ### NewRepositorySlug Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Creates a new RepositorySlug object from separate owner and repository name strings. ```APIDOC ## NewRepositorySlug ### Description Creates a repository slug object from both owner and repository name strings. ### Function Signature ```go func NewRepositorySlug(owner, repo string) RepositorySlug ``` ### Parameters #### Path Parameters - **owner** (string) - Required - The owner of the repository. - **repo** (string) - Required - The name of the repository. ``` -------------------------------- ### Package functions (v1 API) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Provides functions for updating software, detecting releases, and managing versions with context support. ```APIDOC ## Package functions (v1 API) ### Description These functions facilitate software updates and release detection, incorporating context for cancellation. ### UpdateTo Updates the application to a new version from a specified asset URL. #### Signature ```go func UpdateTo(ctx context.Context, assetURL, assetFileName, cmdPath string) error ``` ### DetectLatest Detects the latest available release for a given repository. #### Signature ```go func DetectLatest(ctx context.Context, repository Repository) (*Release, bool, error) ``` ### DetectVersion Detects a specific release version for a given repository. #### Signature ```go func DetectVersion(ctx context.Context, repository Repository, version string) (*Release, bool, error) ``` ### UpdateCommand Initiates an update using a command path, current version, and repository information. #### Signature ```go func UpdateCommand(ctx context.Context, cmdPath string, current string, repository Repository) (*Release, error) ``` ### UpdateSelf Updates the application itself based on the current version and repository information. #### Signature ```go func UpdateSelf(ctx context.Context, current string, repository Repository) (*Release, error) ``` ``` -------------------------------- ### DecompressCommand for Extracting Executables Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Use DecompressCommand to extract a raw executable binary from an archive reader. It detects the format from the filename and requires the executable name, OS, and architecture. Ensure the file is properly opened and closed. ```go f, _ := os.Open("myapp_linux_amd64.tar.gz") defer f.Close() execReader, err := selfupdate.DecompressCommand( f, "myapp_linux_amd64.tar.gz", // used to detect format "myapp", // executable name to look for inside archive "linux", "amd64", ) if err != nil { // errors.Is(err, selfupdate.ErrCannotDecompressFile) // errors.Is(err, selfupdate.ErrExecutableNotFoundInArchive) log.Fatal(err) } data, _ := io.ReadAll(execReader) ``` -------------------------------- ### Detect Latest Version and Update Binary Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Use this function to detect the latest available version from a GitHub repository and update the current executable if a newer version is found. Ensure the 'creativeprojects/resticprofile' slug is correct for your repository. ```go func update(version string) error { latest, found, err := selfupdate.DetectLatest(context.Background(), selfupdate.ParseSlug("creativeprojects/resticprofile")) if err != nil { return fmt.Errorf("error occurred while detecting version: %w", err) } if !found { return fmt.Errorf("latest version for %s/%s could not be found from github repository", runtime.GOOS, runtime.GOARCH) } if latest.LessOrEqual(version) { log.Printf("Current version (%s) is the latest", version) return nil } exe, err := selfupdate.ExecutablePath() if err != nil { return errors.New("could not locate executable path") } if err := selfupdate.UpdateTo(context.Background(), latest.AssetURL, latest.AssetName, exe); err != nil { return fmt.Errorf("error occurred while updating binary: %w", err) } log.Printf("Successfully updated to version %s", latest.Version()) return nil } ``` -------------------------------- ### Detect Latest Release for a Repository Source: https://github.com/creativeprojects/go-selfupdate/blob/main/cmd/detect-latest-release/README.md Specify a GitHub repository to find its latest release version. ```bash $ detect-latest-release creativeprojects/resticprofile ``` -------------------------------- ### Implement Release Validator Interface Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Implement the Validator interface to add custom validation logic for downloaded releases. The Validate method checks the release bytes against an additional asset, and GetValidationAssetName specifies the name of the asset containing the checksum or signature. ```go type Validator interface { // Validate validates release bytes against an additional asset bytes. // See SHAValidator or ECDSAValidator for more information. Validate(filename string, release, asset []byte) error // GetValidationAssetName returns the additional asset name containing the validation checksum. // The asset containing the checksum can be based on the release asset name // Please note if the validation file cannot be found, the DetectLatest and DetectVersion methods // will fail with a wrapped ErrValidationAssetNotFound error GetValidationAssetName(releaseFilename string) string } ``` -------------------------------- ### Update Running Executable with Updater.UpdateSelf Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt A convenience wrapper for UpdateCommand that automatically finds the running executable's path. It updates the application if a newer version is available. ```go func selfUpdate(currentVersion string) error { updater, err := selfupdate.NewUpdater(selfupdate.Config{ Validator: &selfupdate.ChecksumValidator{UniqueFilename: "checksums.txt"}, }) if err != nil { return err } rel, err := updater.UpdateSelf( context.Background(), currentVersion, selfupdate.ParseSlug("owner/myapp"), ) if err != nil { return fmt.Errorf("self-update: %w", err) } if rel.Equal(currentVersion) { fmt.Println("already up to date") } else { fmt.Printf("updated from %s to %s\n", currentVersion, rel.Version()) } return nil } ``` -------------------------------- ### Per-File SHA256 Validation Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt This validator requires a companion asset named `.sha256` containing the hex-encoded SHA256 sum of the release asset. DetectLatest will fail if the .sha256 file is absent. ```go // Generate: sha256sum myapp_linux_amd64.tar.gz > myapp_linux_amd64.tar.gz.sha256 updater, _ := selfupdate.NewUpdater(selfupdate.Config{ Validator: &selfupdate.SHAValidator{}, }) // DetectLatest will fail with ErrValidationAssetNotFound if the .sha256 file is absent release, found, err := updater.DetectLatest(ctx, selfupdate.ParseSlug("owner/myapp")) ``` -------------------------------- ### Updater.UpdateTo Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt `UpdateTo` downloads the asset identified by `rel`, optionally validates it, decompresses it, and atomically replaces `cmdPath` with the new binary, with rollback on failure. ```APIDOC ## Applying Updates ### Updater.UpdateTo — download and replace a binary from a Release `UpdateTo` downloads the asset identified by `rel`, optionally validates it, decompresses it, and atomically replaces `cmdPath` with the new binary, with rollback on failure. ```go exe, err := selfupdate.ExecutablePath() if err != nil { return fmt.Errorf("could not find executable: %w", err) } release, found, err := updater.DetectLatest(ctx, selfupdate.ParseSlug("owner/myapp")) if err != nil || !found { return } if release.LessOrEqual("1.2.0") { fmt.Println("already up to date") return } if err := updater.UpdateTo(ctx, release, exe); err != nil { // Check whether a rollback also failed if rbErr := update.RollbackError(err); rbErr != nil { log.Fatalf("FATAL: update failed and rollback failed: %v / %v", err, rbErr) } return fmt.Errorf("update failed (rollback succeeded): %w", err) } fmt.Printf("Updated to %s\n", release.Version()) ``` ``` -------------------------------- ### Detect Latest Release Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Updater.DetectLatest finds the highest semver-tagged release for the current platform, skipping drafts and pre-releases. It returns (nil, false, nil) if no suitable release is found. ```go ctx := context.Background() updater, _ := selfupdate.NewUpdater(selfupdate.Config{}) release, found, err := updater.DetectLatest(ctx, selfupdate.ParseSlug("owner/myapp")) if err != nil { log.Fatalf("detection error: %v", err) } if !found { log.Println("no release found for this platform") return } fmt.Printf("Latest version : %s\n", release.Version()) fmt.Printf("Asset URL : %s\n", release.AssetURL) fmt.Printf("Asset name : %s\n", release.AssetName) fmt.Printf("Release notes : %s\n", release.ReleaseNotes) fmt.Printf("Published at : %s\n", release.PublishedAt) ``` -------------------------------- ### Detect Specific Release Version Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Updater.DetectVersion finds a specific release by tag name, useful for downgrades or reproducible deployments. It returns an error or !found if the version is not available for the platform. ```go release, found, err := updater.DetectVersion( context.Background(), selfupdate.ParseSlug("owner/myapp"), "v1.2.3", ) if err != nil || !found { log.Printf("version v1.2.3 not found: found=%v err=%v", found, err) return } fmt.Println("Found:", release.Version()) // "1.2.3" ``` -------------------------------- ### Release Version Comparison Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt The Release type provides methods to compare the current version with a target version. These methods wrap the internal semver engine, simplifying version comparisons without external dependencies. ```APIDOC ## Release Version Comparison Methods The `Release` type exposes version comparison helpers that wrap the internal semver engine, avoiding the need to import a semver package in calling code. ```go const currentVersion = "1.1.0" release, found, err := updater.DetectLatest(ctx, selfupdate.ParseSlug("owner/app")) if err != nil || !found { return } fmt.Println(release.Version()) // "1.2.0" fmt.Println(release.GreaterThan(currentVersion)) // true fmt.Println(release.LessThan(currentVersion)) // false fmt.Println(release.Equal(currentVersion)) // false fmt.Println(release.LessOrEqual(currentVersion)) // false fmt.Println(release.GreaterOrEqual(currentVersion)) // true if release.LessOrEqual(currentVersion) { fmt.Println("already up to date") return } ``` ``` -------------------------------- ### Updater.DetectLatest Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Queries the source provider to find the latest stable release for the current platform. It filters releases by OS/arch, skips drafts and pre-releases, and returns the highest semver-tagged release with a matching asset. Returns (nil, false, nil) if no suitable release is found. ```APIDOC ## Updater.DetectLatest — find the latest stable release for this platform `DetectLatest` queries the source provider, filters releases by OS/arch, skips drafts and pre-releases, and returns the highest semver-tagged release that has a matching asset. Returns `(nil, false, nil)` when no suitable release exists. ```go ctx := context.Background() updater, _ := selfupdate.NewUpdater(selfupdate.Config{}) release, found, err := updater.DetectLatest(ctx, selfupdate.ParseSlug("owner/myapp")) if err != nil { log.Fatalf("detection error: %v", err) } if !found { log.Println("no release found for this platform") return } fmt.Printf("Latest version : %s\n", release.Version()) fmt.Printf("Asset URL : %s\n", release.AssetURL) fmt.Printf("Asset name : %s\n", release.AssetName) fmt.Printf("Release notes : %s\n", release.ReleaseNotes) fmt.Printf("Published at : %s\n", release.PublishedAt) ``` ``` -------------------------------- ### Updater.DetectVersion Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Similar to DetectLatest, but specifically finds a release matching an exact tag name. This is useful for downgrades or reproducible deployments. ```APIDOC ## Updater.DetectVersion — find a specific release version for this platform `DetectVersion` works like `DetectLatest` but pins to an exact tag name (e.g., `"v1.2.3"`). Useful for downgrade or reproducible-deploy scenarios. ```go release, found, err := updater.DetectVersion( context.Background(), selfupdate.ParseSlug("owner/myapp"), "v1.2.3", ) if err != nil || !found { log.Printf("version v1.2.3 not found: found=%v err=%v", found, err) return } fmt.Println("Found:", release.Version()) // "1.2.3" ``` ``` -------------------------------- ### Updater.UpdateSelf Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt `UpdateSelf` is a convenience wrapper around `UpdateCommand` that automatically resolves the path of the running process via `os.Executable` (following symlinks). ```APIDOC ### Updater.UpdateSelf — update the currently running executable `UpdateSelf` is a convenience wrapper around `UpdateCommand` that automatically resolves the path of the running process via `os.Executable` (following symlinks). ```go func selfUpdate(currentVersion string) error { updater, err := selfupdate.NewUpdater(selfupdate.Config{ Validator: &selfupdate.ChecksumValidator{UniqueFilename: "checksums.txt"}, }) if err != nil { return err } rel, err := updater.UpdateSelf( context.Background(), currentVersion, selfupdate.ParseSlug("owner/myapp"), ) if err != nil { return fmt.Errorf("self-update: %w", err) } if rel.Equal(currentVersion) { fmt.Println("already up to date") } else { fmt.Printf("updated from %s to %s\n", currentVersion, rel.Version()) } return nil } ``` ``` -------------------------------- ### Check for Sentinel Errors with errors.Is Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Use errors.Is to check for specific sentinel errors returned by the updater. This allows for granular error inspection and handling of different update failure scenarios. ```go release, found, err := updater.DetectLatest(ctx, selfupdate.ParseSlug("owner/myapp")) if err != nil { switch { case errors.Is(err, selfupdate.ErrValidationAssetNotFound): log.Printf("checksum/signature file missing from release: %v", err) case errors.Is(err, selfupdate.ErrChecksumValidationFailed): log.Printf("sha256 mismatch: %v", err) case errors.Is(err, selfupdate.ErrECDSAValidationFailed): log.Printf("ECDSA signature invalid: %v", err) case errors.Is(err, selfupdate.ErrInvalidPGPSignature): log.Printf("PGP signature invalid: %v", err) case errors.Is(err, selfupdate.ErrInvalidSlug): log.Printf("bad repository slug: %v", err) default: log.Printf("update error: %v", err) } } ``` ```go if applyErr := updater.UpdateTo(ctx, release, exe); applyErr != nil { if rbErr := update.RollbackError(applyErr); rbErr != nil { log.Fatalf("update AND rollback failed: update=%v rollback=%v", applyErr, rbErr) } log.Printf("update failed but rollback succeeded: %v", applyErr) } ``` -------------------------------- ### Package-level DetectLatest / DetectVersion Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Convenience functions that use the DefaultUpdater for one-liner usage when custom configuration is not needed. ```APIDOC ### Package-level DetectLatest / DetectVersion — shortcuts using DefaultUpdater These package-level functions call the methods on `DefaultUpdater()` for concise one-liner usage when no custom configuration is required. ```go release, found, err := selfupdate.DetectLatest( context.Background(), selfupdate.ParseSlug("creativeprojects/resticprofile"), ) if err != nil { return fmt.Errorf("detect: %w", err) } specificRelease, found, err := selfupdate.DetectVersion( context.Background(), selfupdate.ParseSlug("creativeprojects/resticprofile"), "v0.27.0", ) ``` ``` -------------------------------- ### Package-level UpdateTo Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt `UpdateTo` at the package level downloads directly from an arbitrary URL without using a source provider. Suitable for public releases only (no authentication). ```APIDOC ### Package-level UpdateTo — low-level update from a direct URL `UpdateTo` at the package level downloads directly from an arbitrary URL without using a source provider. Suitable for public releases only (no authentication). ```go exe, _ := selfupdate.ExecutablePath() err := selfupdate.UpdateTo( context.Background(), "https://github.com/owner/repo/releases/download/v1.2.3/myapp_linux_amd64.tar.gz", "myapp_linux_amd64.tar.gz", exe, ) if err != nil { log.Fatal(err) } ``` ``` -------------------------------- ### ExecutablePath for Resolving Running Binary Path Source: https://context7.com/creativeprojects/go-selfupdate/llms.txt Obtain the absolute path of the current executable, resolving symlinks, using ExecutablePath. This function is used internally by UpdateSelf and can be used in custom update flows. Handle potential errors during path resolution. ```go exe, err := selfupdate.ExecutablePath() if err != nil { return fmt.Errorf("cannot find executable path: %w", err) } fmt.Println("Running from:", exe) // pass to UpdateTo or UpdateCommand: err = updater.UpdateTo(ctx, release, exe) ``` -------------------------------- ### NewRepositoryID (GitLab only) Source: https://github.com/creativeprojects/go-selfupdate/blob/main/README.md Creates a RepositoryID object for GitLab using a numeric repository ID. ```APIDOC ## NewRepositoryID (GitLab only) ### Description Creates a repository identifier using a numeric repository ID, specifically for GitLab. ### Function Signature ```go func NewRepositoryID(id int) RepositoryID ``` ### Parameters #### Path Parameters - **id** (int) - Required - The numeric ID of the repository on GitLab. ```