First commit
This commit is contained in:
		
						commit
						886da1fce3
					
				
							
								
								
									
										29
									
								
								.github/workflows/release.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								.github/workflows/release.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					on:
 | 
				
			||||||
 | 
					  release:
 | 
				
			||||||
 | 
					    types: [created]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					permissions:
 | 
				
			||||||
 | 
					    contents: write
 | 
				
			||||||
 | 
					    packages: write
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					  goreleaser:
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      -
 | 
				
			||||||
 | 
					        name: Checkout
 | 
				
			||||||
 | 
					        uses: actions/checkout@v4
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          fetch-depth: 0
 | 
				
			||||||
 | 
					      -
 | 
				
			||||||
 | 
					        name: Set up Go
 | 
				
			||||||
 | 
					        uses: actions/setup-go@v4
 | 
				
			||||||
 | 
					      -
 | 
				
			||||||
 | 
					        name: Run GoReleaser
 | 
				
			||||||
 | 
					        uses: goreleaser/goreleaser-action@v6
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          distribution: goreleaser
 | 
				
			||||||
 | 
					          version: latest
 | 
				
			||||||
 | 
					          args: release --clean
 | 
				
			||||||
 | 
					        env:
 | 
				
			||||||
 | 
					          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
				
			||||||
							
								
								
									
										21
									
								
								.github/workflows/test_golang.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								.github/workflows/test_golang.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					name: Go package
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					on: [push]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					  build:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - uses: actions/checkout@v3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: Set up Go
 | 
				
			||||||
 | 
					        uses: actions/setup-go@v4
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          go-version: '1.21'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: Build
 | 
				
			||||||
 | 
					        run: go build -v ./...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: Test
 | 
				
			||||||
 | 
					        run: go test -v ./...
 | 
				
			||||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					goreleaser-http-repo-builder
 | 
				
			||||||
							
								
								
									
										26
									
								
								.goreleaser.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								.goreleaser.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					# This is an example .goreleaser.yml file with some sensible defaults.
 | 
				
			||||||
 | 
					# Make sure to check the documentation at https://goreleaser.com
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The lines below are called `modelines`. See `:help modeline`
 | 
				
			||||||
 | 
					# Feel free to remove those if you don't want/need to use them.
 | 
				
			||||||
 | 
					# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
 | 
				
			||||||
 | 
					# vim: set ts=2 sw=2 tw=0 fo=cnqoj
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					version: 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					before:
 | 
				
			||||||
 | 
					  hooks:
 | 
				
			||||||
 | 
					    - go mod tidy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					builds:
 | 
				
			||||||
 | 
					  - env:
 | 
				
			||||||
 | 
					      - CGO_ENABLED=0
 | 
				
			||||||
 | 
					    goos:
 | 
				
			||||||
 | 
					      - linux
 | 
				
			||||||
 | 
					      - darwin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					archives:
 | 
				
			||||||
 | 
					  - format: tar.gz
 | 
				
			||||||
 | 
					    # this name template makes the OS and Arch compatible with the results of `uname`.
 | 
				
			||||||
 | 
					    name_template: "{{ .ProjectName }}-{{ .Version }}.{{ .Os }}-{{ .Arch }}"
 | 
				
			||||||
 | 
					    wrap_in_directory: true
 | 
				
			||||||
							
								
								
									
										19
									
								
								LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					Copyright (c) 2024 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The above copyright notice and this permission notice shall be included in all
 | 
				
			||||||
 | 
					copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					SOFTWARE.
 | 
				
			||||||
							
								
								
									
										63
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,63 @@
 | 
				
			|||||||
 | 
					# goreleaser-http-repo-builder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tool was written out of the need to build a release repository compatible with [go-selfupdate](https://github.com/creativeprojects/go-selfupdate) with releases built by [goreleaser](https://goreleaser.com/).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Example Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The command has extensive help available, the following is an example of building a release and adding it to a new repo.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					goreleaser release --snapshot --skip=publish
 | 
				
			||||||
 | 
					mkdir repo
 | 
				
			||||||
 | 
					goreleaser-http-repo-builder add-release --repo=repo/ --release=dist/
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					After adding a release, you can copy the repo to your web server for update distrobution.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Example Goreleaser Config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					While there is good [documentation available](https://goreleaser.com/customization/) that I'd recommend reading, the following provides some examples that may be helpful in generating a release that is compatible with go-selfupdate.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- The checksums file name defaults to preappend the project name, which is not compatible if you wish to use the checksums to verify an update.
 | 
				
			||||||
 | 
					- If you're signing releases with an ECDSA key, this is what I found works best.
 | 
				
			||||||
 | 
					- If you need to specify the version manually, you can edit the version template. By default, goreleaser will use the git tag to determine the version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```yaml
 | 
				
			||||||
 | 
					version: 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					before:
 | 
				
			||||||
 | 
					  hooks:
 | 
				
			||||||
 | 
					    - go mod tidy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					builds:
 | 
				
			||||||
 | 
					  - env:
 | 
				
			||||||
 | 
					      - CGO_ENABLED=0
 | 
				
			||||||
 | 
					    goos:
 | 
				
			||||||
 | 
					      - linux
 | 
				
			||||||
 | 
					    goarch:
 | 
				
			||||||
 | 
					      - amd64
 | 
				
			||||||
 | 
					      - arm64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					archives:
 | 
				
			||||||
 | 
					  - format: tar.gz
 | 
				
			||||||
 | 
					    name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}"
 | 
				
			||||||
 | 
					    wrap_in_directory: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					checksum:
 | 
				
			||||||
 | 
					    name_template: "checksums.txt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					signs:
 | 
				
			||||||
 | 
					  - artifacts: all
 | 
				
			||||||
 | 
					    cmd: openssl
 | 
				
			||||||
 | 
					    args:
 | 
				
			||||||
 | 
					        - dgst
 | 
				
			||||||
 | 
					        - -sha256
 | 
				
			||||||
 | 
					        - -sign
 | 
				
			||||||
 | 
					        - "signing.key"
 | 
				
			||||||
 | 
					        - -out
 | 
				
			||||||
 | 
					        - ${signature}
 | 
				
			||||||
 | 
					        - ${artifact}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					snapshot:
 | 
				
			||||||
 | 
					    version_template: "v0.1.2"
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
							
								
								
									
										187
									
								
								add_release_cmd.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								add_release_cmd.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,187 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AddReleaseCmd struct {
 | 
				
			||||||
 | 
						Release        string    `help:"Path to goreleaser dist folder." required:"" type:"existingdir"`
 | 
				
			||||||
 | 
						Notes          string    `help:"Notes about this release."`
 | 
				
			||||||
 | 
						Draft          bool      `help:"Is this release a draft?"`
 | 
				
			||||||
 | 
						Prerelease     bool      `help:"Is this a prelease?"`
 | 
				
			||||||
 | 
						IncludeBinary  bool      `help:"Include binary artifacts."`
 | 
				
			||||||
 | 
						Force          bool      `help:"Force add, removing existing if needed."`
 | 
				
			||||||
 | 
						PublishedAt    time.Time `help:"Specify exact time for release."`
 | 
				
			||||||
 | 
						PublishedAtNow bool      `help:"Use the current time for published at instead of the metadata date."`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Adds a release to a repo.
 | 
				
			||||||
 | 
					func (a *AddReleaseCmd) Run() error {
 | 
				
			||||||
 | 
						// Read existing manifest for repo.
 | 
				
			||||||
 | 
						manifestFile := filepath.Join(app.flags.Repo, "manifest.yaml")
 | 
				
			||||||
 | 
						manifest, err := readManifestFile(manifestFile)
 | 
				
			||||||
 | 
						if os.IsNotExist(err) {
 | 
				
			||||||
 | 
							err = os.MkdirAll(app.flags.Repo, 0755)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Read metadata from goreleaser.
 | 
				
			||||||
 | 
						metadata, err := readMetadataFile(filepath.Join(a.Release, "metadata.json"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						versionPath := filepath.Join(app.flags.Repo, metadata.Version)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Read the artifcats to ensure we have a valid release.
 | 
				
			||||||
 | 
						artifacts, err := readArtifactFile(filepath.Join(a.Release, "artifacts.json"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(artifacts) == 0 {
 | 
				
			||||||
 | 
							return errors.New("no artifacts in release")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Validate the base dir for artifacts. It could be one dir up, or 2 dirs up.
 | 
				
			||||||
 | 
						artifcatBase := a.Release
 | 
				
			||||||
 | 
						artifactLayers := 0
 | 
				
			||||||
 | 
						if _, serr := os.Stat(filepath.Join(artifcatBase, artifacts[0].Path)); serr != nil {
 | 
				
			||||||
 | 
							artifcatBase = filepath.Dir(artifcatBase)
 | 
				
			||||||
 | 
							artifactLayers = 1
 | 
				
			||||||
 | 
							if _, serr := os.Stat(filepath.Join(artifcatBase, artifacts[0].Path)); serr != nil {
 | 
				
			||||||
 | 
								artifcatBase = filepath.Dir(artifcatBase)
 | 
				
			||||||
 | 
								artifactLayers = 2
 | 
				
			||||||
 | 
								if _, serr := os.Stat(filepath.Join(artifcatBase, artifacts[0].Path)); serr != nil {
 | 
				
			||||||
 | 
									return errors.New("unable to determine artificate base path")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check if the version already exists.
 | 
				
			||||||
 | 
						existingIndex := -1
 | 
				
			||||||
 | 
						for i, release := range manifest.Releases {
 | 
				
			||||||
 | 
							if release.TagName == metadata.Version {
 | 
				
			||||||
 | 
								existingIndex = i
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If the version already exists, ask about replacing.
 | 
				
			||||||
 | 
						if existingIndex != -1 {
 | 
				
			||||||
 | 
							if !a.Force {
 | 
				
			||||||
 | 
								ans := askForConfirmation("This release already exists, should we replace?")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// If we don't want to replace, we should stop here.
 | 
				
			||||||
 | 
								if !ans {
 | 
				
			||||||
 | 
									return errors.New("version already exists")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// We need to replace the release, so remove it.
 | 
				
			||||||
 | 
							manifest.Releases = append(manifest.Releases[:existingIndex], manifest.Releases[existingIndex+1:]...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Remove the version directory.
 | 
				
			||||||
 | 
							os.RemoveAll(versionPath)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Make the release.
 | 
				
			||||||
 | 
						manifest.LastReleaseID++
 | 
				
			||||||
 | 
						release := &HttpRelease{
 | 
				
			||||||
 | 
							ReleaseID:    manifest.LastReleaseID,
 | 
				
			||||||
 | 
							Name:         metadata.Name,
 | 
				
			||||||
 | 
							TagName:      metadata.Version,
 | 
				
			||||||
 | 
							URL:          metadata.Version,
 | 
				
			||||||
 | 
							Draft:        a.Draft,
 | 
				
			||||||
 | 
							Prerelease:   a.Prerelease,
 | 
				
			||||||
 | 
							PublishedAt:  metadata.Date,
 | 
				
			||||||
 | 
							ReleaseNotes: a.Notes,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If the publish date provided is valid, override.
 | 
				
			||||||
 | 
						if !a.PublishedAt.IsZero() {
 | 
				
			||||||
 | 
							release.PublishedAt = a.PublishedAt
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If published at is requested to be now, override.
 | 
				
			||||||
 | 
						if a.PublishedAtNow {
 | 
				
			||||||
 | 
							release.PublishedAt = app.now
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Make the directory for the release.
 | 
				
			||||||
 | 
						err = os.Mkdir(versionPath, 0755)
 | 
				
			||||||
 | 
						if err != nil && !os.IsExist(err) {
 | 
				
			||||||
 | 
							return fmt.Errorf("Error making release directory: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add artifacts.
 | 
				
			||||||
 | 
						for _, artifact := range artifacts {
 | 
				
			||||||
 | 
							// Skip binaries if not included.
 | 
				
			||||||
 | 
							if artifact.Type == "Binary" && !a.IncludeBinary {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Get the file path and confirm it exists and get its stat for file size.
 | 
				
			||||||
 | 
							path := filepath.Join(artifcatBase, artifact.Path)
 | 
				
			||||||
 | 
							stat, serr := os.Stat(path)
 | 
				
			||||||
 | 
							if serr != nil {
 | 
				
			||||||
 | 
								log.Println("Ignoring artifact", artifact.Name, "as its file does not exist.")
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Determine relative path.
 | 
				
			||||||
 | 
							s := strings.Split(artifact.Path, "/")
 | 
				
			||||||
 | 
							relativePath := filepath.Join(s[artifactLayers:]...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Determine if artifact is in its own sub dir, make sure it exists.
 | 
				
			||||||
 | 
							dir := filepath.Dir(relativePath)
 | 
				
			||||||
 | 
							if dir != "." {
 | 
				
			||||||
 | 
								os.MkdirAll(filepath.Join(versionPath, dir), 0755)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Copy artifact to repo.
 | 
				
			||||||
 | 
							err = copyFile(path, filepath.Join(versionPath, relativePath))
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Printf("Failed to copy artifact, skipping it: %s", err)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Make asset.
 | 
				
			||||||
 | 
							manifest.LastAssetID++
 | 
				
			||||||
 | 
							asset := &HttpAsset{
 | 
				
			||||||
 | 
								ID:   manifest.LastAssetID,
 | 
				
			||||||
 | 
								Name: artifact.Name,
 | 
				
			||||||
 | 
								Size: int(stat.Size()),
 | 
				
			||||||
 | 
								URL:  filepath.Join(metadata.Version, relativePath),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Add to the release.
 | 
				
			||||||
 | 
							release.Assets = append(release.Assets, asset)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add release to manifest.
 | 
				
			||||||
 | 
						manifest.Releases = append(manifest.Releases, release)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Write the manifest.
 | 
				
			||||||
 | 
						err = writeManifestFile(manifestFile, manifest)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If not a draft or prerelease, link latest to this release.
 | 
				
			||||||
 | 
						if !a.Draft && !a.Prerelease {
 | 
				
			||||||
 | 
							latestPath := filepath.Join(app.flags.Repo, "latest")
 | 
				
			||||||
 | 
							os.Remove(latestPath)
 | 
				
			||||||
 | 
							os.Symlink(metadata.Version, latestPath)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Println("Added release", metadata.Version, "for", metadata.Name, "to the repo", app.flags.Repo)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										39
									
								
								flags.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								flags.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/alecthomas/kong"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type VersionFlag bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (v VersionFlag) Decode(ctx *kong.DecodeContext) error { return nil }
 | 
				
			||||||
 | 
					func (v VersionFlag) IsBool() bool                         { return true }
 | 
				
			||||||
 | 
					func (v VersionFlag) BeforeApply(app *kong.Kong, vars kong.Vars) error {
 | 
				
			||||||
 | 
						fmt.Println(appName + ": " + appVersion)
 | 
				
			||||||
 | 
						app.Exit(0)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Flags supplied to cli.
 | 
				
			||||||
 | 
					type Flags struct {
 | 
				
			||||||
 | 
						Version    VersionFlag   `name:"version" help:"Print version information and quit"`
 | 
				
			||||||
 | 
						Repo       string        `help:"The path to a repo" required:"" type:"existingdir"`
 | 
				
			||||||
 | 
						AddRelease AddReleaseCmd `cmd:"" help:"Add an release to the repo"`
 | 
				
			||||||
 | 
						Prune      PruneCmd      `cmd:"" help:"Prune releases from repo."`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Parse the supplied flags.
 | 
				
			||||||
 | 
					func (a *App) ParseFlags() *kong.Context {
 | 
				
			||||||
 | 
						app.flags = &Flags{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx := kong.Parse(app.flags,
 | 
				
			||||||
 | 
							kong.Name(appName),
 | 
				
			||||||
 | 
							kong.Description(appDescription),
 | 
				
			||||||
 | 
							kong.UsageOnError(),
 | 
				
			||||||
 | 
							kong.ConfigureHelp(kong.HelpOptions{
 | 
				
			||||||
 | 
								Compact: true,
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						return ctx
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					module github.com/grmrgecko/goreleaser-http-repo-builder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					go 1.23
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require (
 | 
				
			||||||
 | 
						github.com/alecthomas/kong v1.2.1
 | 
				
			||||||
 | 
						gopkg.in/yaml.v3 v3.0.1
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										12
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					github.com/alecthomas/assert/v2 v2.10.0 h1:jjRCHsj6hBJhkmhznrCzoNpbA3zqy0fYiUcYZP/GkPY=
 | 
				
			||||||
 | 
					github.com/alecthomas/assert/v2 v2.10.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
 | 
				
			||||||
 | 
					github.com/alecthomas/kong v1.2.1 h1:E8jH4Tsgv6wCRX2nGrdPyHDUCSG83WH2qE4XLACD33Q=
 | 
				
			||||||
 | 
					github.com/alecthomas/kong v1.2.1/go.mod h1:rKTSFhbdp3Ryefn8x5MOEprnRFQ7nlmMC01GKhehhBM=
 | 
				
			||||||
 | 
					github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
 | 
				
			||||||
 | 
					github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
 | 
				
			||||||
 | 
					github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
 | 
				
			||||||
 | 
					github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
 | 
				
			||||||
 | 
					gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 | 
				
			||||||
 | 
					gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
				
			||||||
 | 
					gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 | 
				
			||||||
 | 
					gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
				
			||||||
							
								
								
									
										57
									
								
								goreleaser.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								goreleaser.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The metadata needed from goreleaser.
 | 
				
			||||||
 | 
					type Metadata struct {
 | 
				
			||||||
 | 
						Name    string    `json:"project_name"`
 | 
				
			||||||
 | 
						Version string    `json:"version"`
 | 
				
			||||||
 | 
						Date    time.Time `json:"date"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Read and parse metadata file
 | 
				
			||||||
 | 
					func readMetadataFile(metadataFile string) (*Metadata, error) {
 | 
				
			||||||
 | 
						// Read file, if error return the error.
 | 
				
			||||||
 | 
						jsonFile, err := os.Open(metadataFile)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Attempt to decode the file.
 | 
				
			||||||
 | 
						metadata := new(Metadata)
 | 
				
			||||||
 | 
						decoder := json.NewDecoder(jsonFile)
 | 
				
			||||||
 | 
						err = decoder.Decode(metadata)
 | 
				
			||||||
 | 
						jsonFile.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Return the metadata and if any error occurred.
 | 
				
			||||||
 | 
						return metadata, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Artifcat map.
 | 
				
			||||||
 | 
					type Artifact struct {
 | 
				
			||||||
 | 
						Name string `json:"name"`
 | 
				
			||||||
 | 
						Path string `json:"path"`
 | 
				
			||||||
 | 
						Type string `json:"type"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Read and parse metadata file
 | 
				
			||||||
 | 
					func readArtifactFile(artifactFile string) ([]*Artifact, error) {
 | 
				
			||||||
 | 
						// Read file, if error return the error.
 | 
				
			||||||
 | 
						jsonFile, err := os.Open(artifactFile)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Attempt to decode the file.
 | 
				
			||||||
 | 
						var artifacts []*Artifact
 | 
				
			||||||
 | 
						decoder := json.NewDecoder(jsonFile)
 | 
				
			||||||
 | 
						err = decoder.Decode(&artifacts)
 | 
				
			||||||
 | 
						jsonFile.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Return the metadata and if any error occurred.
 | 
				
			||||||
 | 
						return artifacts, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										28
									
								
								main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								main.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						appName        = "goreleaser-http-repo-builder"
 | 
				
			||||||
 | 
						appDescription = "Builds a repo for use with go-selfupdate"
 | 
				
			||||||
 | 
						appVersion     = "0.1.0"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// App is the global application structure for communicating between servers and storing information.
 | 
				
			||||||
 | 
					type App struct {
 | 
				
			||||||
 | 
						flags *Flags
 | 
				
			||||||
 | 
						now   time.Time
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var app *App
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						app = new(App)
 | 
				
			||||||
 | 
						app.now = time.Now()
 | 
				
			||||||
 | 
						ctx := app.ParseFlags()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := ctx.Run()
 | 
				
			||||||
 | 
						ctx.FatalIfErrorf(err)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										224
									
								
								main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								main_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,224 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"crypto/md5"
 | 
				
			||||||
 | 
						"encoding/hex"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Test the add release option.
 | 
				
			||||||
 | 
					func TestAppFunctionality(t *testing.T) {
 | 
				
			||||||
 | 
						// Make temp directory to build repo.
 | 
				
			||||||
 | 
						dname, err := os.MkdirTemp("", "goreleaser-http-repo-builder")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("error making tempdir: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get the tests dir with test files.
 | 
				
			||||||
 | 
						testsDir, err := filepath.Abs("tests")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("error finding tests dir: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Now date for app defines.
 | 
				
			||||||
 | 
						now, _ := time.Parse(time.DateOnly, "2024-10-08")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Test adding a release of v0.1.
 | 
				
			||||||
 | 
						os.Args = []string{"test", "--repo", dname, "add-release", "--notes", "This is a test.", "--release", filepath.Join(testsDir, "v0.1")}
 | 
				
			||||||
 | 
						app = new(App)
 | 
				
			||||||
 | 
						app.now = now
 | 
				
			||||||
 | 
						ctx := app.ParseFlags()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Run the command.
 | 
				
			||||||
 | 
						err = ctx.Run()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("error running the app: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Test adding a release of v0.1.1.
 | 
				
			||||||
 | 
						os.Args = []string{"test", "--repo", dname, "add-release", "--draft", "--release", filepath.Join(testsDir, "v0.1.1")}
 | 
				
			||||||
 | 
						app = new(App)
 | 
				
			||||||
 | 
						app.now = now
 | 
				
			||||||
 | 
						ctx = app.ParseFlags()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Run the command.
 | 
				
			||||||
 | 
						err = ctx.Run()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("error running the app: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Test adding a release of v0.1.2.
 | 
				
			||||||
 | 
						os.Args = []string{"test", "--repo", dname, "add-release", "--prerelease", "--published-at", "2024-10-05T22:15:21.731224367-05:00", "--release", filepath.Join(testsDir, "v0.1.2")}
 | 
				
			||||||
 | 
						app = new(App)
 | 
				
			||||||
 | 
						app.now = now
 | 
				
			||||||
 | 
						ctx = app.ParseFlags()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Run the command.
 | 
				
			||||||
 | 
						err = ctx.Run()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("error running the app: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Confirm the latest release is v0.1.0.
 | 
				
			||||||
 | 
						latestPath, err := os.Readlink(filepath.Join(dname, "latest"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("error reading link to latest: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if latestPath != "v0.1.0" {
 | 
				
			||||||
 | 
							t.Error("the latest link isn't correctly linked")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Hash the manifest file without the published_at dates.
 | 
				
			||||||
 | 
						hfun := md5.New()
 | 
				
			||||||
 | 
						d, err := os.ReadFile(filepath.Join(dname, "manifest.yaml"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("error reading manifest file: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Hash the result and confirm.
 | 
				
			||||||
 | 
						hfun.Write(d)
 | 
				
			||||||
 | 
						sum := hfun.Sum(nil)
 | 
				
			||||||
 | 
						hash := hex.EncodeToString(sum)
 | 
				
			||||||
 | 
						if hash != "01240af1d189ea540418903e15eb3068" {
 | 
				
			||||||
 | 
							t.Errorf("hash isn't valid for manifest file: %s", hash)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Binaries are not included.
 | 
				
			||||||
 | 
						if _, serr := os.Stat(filepath.Join(dname, "v0.1.0/example_linux_amd64/example")); !os.IsNotExist(serr) {
 | 
				
			||||||
 | 
							t.Error("v0.1.0 binary exists, when it shouldn't exist.")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Confirm the asset was copied correctly.
 | 
				
			||||||
 | 
						d, err = os.ReadFile(filepath.Join(dname, "v0.1.0/example_linux_amd64.tar.gz"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("error reading test file: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						hfun.Reset()
 | 
				
			||||||
 | 
						hfun.Write(d)
 | 
				
			||||||
 | 
						sum = hfun.Sum(nil)
 | 
				
			||||||
 | 
						hash = hex.EncodeToString(sum)
 | 
				
			||||||
 | 
						if hash != "9cffcbe826ae684db1c8a08ff9216f34" {
 | 
				
			||||||
 | 
							t.Errorf("hash isn't valid for test file: %s", hash)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Confirm pruning of max releases works.
 | 
				
			||||||
 | 
						os.Args = []string{"test", "--repo", dname, "prune", "--max-age=216h"}
 | 
				
			||||||
 | 
						app = new(App)
 | 
				
			||||||
 | 
						app.now = now
 | 
				
			||||||
 | 
						ctx = app.ParseFlags()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Run the command.
 | 
				
			||||||
 | 
						err = ctx.Run()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("error running the app: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Confirm pruned state.
 | 
				
			||||||
 | 
						if _, serr := os.Stat(filepath.Join(dname, "v0.1.0/example_linux_amd64.tar.gz")); !os.IsNotExist(serr) {
 | 
				
			||||||
 | 
							t.Error("v0.1.0 exists, when it shouldn't exist.")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if _, serr := os.Stat(filepath.Join(dname, "v0.1.1/example_linux_amd64.tar.gz")); os.IsNotExist(serr) {
 | 
				
			||||||
 | 
							t.Error("v0.1.1 does not exists, when it should.")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if _, serr := os.Stat(filepath.Join(dname, "v0.1.2/example_linux_amd64.tar.gz")); os.IsNotExist(serr) {
 | 
				
			||||||
 | 
							t.Error("v0.1.2 does not exists, when it should.")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Delete all files, and reset.
 | 
				
			||||||
 | 
						os.RemoveAll(dname)
 | 
				
			||||||
 | 
						os.Mkdir(dname, 0755)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Test adding a release of v0.1.
 | 
				
			||||||
 | 
						os.Args = []string{"test", "--repo", dname, "add-release", "--include-binary", "--release", filepath.Join(testsDir, "v0.1")}
 | 
				
			||||||
 | 
						app = new(App)
 | 
				
			||||||
 | 
						app.now = now
 | 
				
			||||||
 | 
						ctx = app.ParseFlags()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Run the command.
 | 
				
			||||||
 | 
						err = ctx.Run()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("error running the app: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Test adding a release of v0.1.1.
 | 
				
			||||||
 | 
						os.Args = []string{"test", "--repo", dname, "add-release", "--release", filepath.Join(testsDir, "v0.1.1")}
 | 
				
			||||||
 | 
						app = new(App)
 | 
				
			||||||
 | 
						app.now = now
 | 
				
			||||||
 | 
						ctx = app.ParseFlags()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Run the command.
 | 
				
			||||||
 | 
						err = ctx.Run()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("error running the app: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Test adding a release of v0.1.2.
 | 
				
			||||||
 | 
						os.Args = []string{"test", "--repo", dname, "add-release", "--published-at-now", "--release", filepath.Join(testsDir, "v0.1.2")}
 | 
				
			||||||
 | 
						app = new(App)
 | 
				
			||||||
 | 
						app.now = now
 | 
				
			||||||
 | 
						ctx = app.ParseFlags()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Run the command.
 | 
				
			||||||
 | 
						err = ctx.Run()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("error running the app: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Confirm the latest release is v0.1.2.
 | 
				
			||||||
 | 
						latestPath, err = os.Readlink(filepath.Join(dname, "latest"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("error reading link to latest: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if latestPath != "v0.1.2" {
 | 
				
			||||||
 | 
							t.Error("the latest link isn't correctly linked")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Hash the manifest file without the published_at dates.
 | 
				
			||||||
 | 
						hfun.Reset()
 | 
				
			||||||
 | 
						d, err = os.ReadFile(filepath.Join(dname, "manifest.yaml"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("error reading manifest file: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Hash the result and confirm.
 | 
				
			||||||
 | 
						hfun.Write(d)
 | 
				
			||||||
 | 
						sum = hfun.Sum(nil)
 | 
				
			||||||
 | 
						hash = hex.EncodeToString(sum)
 | 
				
			||||||
 | 
						if hash != "dfac4ec2fc35bb04c8f5f79e057dfbe9" {
 | 
				
			||||||
 | 
							t.Errorf("hash isn't valid for manifest file: %s", hash)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Binaries are not included.
 | 
				
			||||||
 | 
						if _, serr := os.Stat(filepath.Join(dname, "v0.1.0/example_linux_amd64/example")); os.IsNotExist(serr) {
 | 
				
			||||||
 | 
							t.Error("v0.1.0 binary does not exists, when it shouldn.")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Confirm pruning of max releases works.
 | 
				
			||||||
 | 
						os.Args = []string{"test", "--repo", dname, "prune", "--max-releases=1"}
 | 
				
			||||||
 | 
						app = new(App)
 | 
				
			||||||
 | 
						app.now = now
 | 
				
			||||||
 | 
						ctx = app.ParseFlags()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Run the command.
 | 
				
			||||||
 | 
						err = ctx.Run()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("error running the app: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Confirm pruned state.
 | 
				
			||||||
 | 
						if _, serr := os.Stat(filepath.Join(dname, "v0.1.0/example_linux_amd64.tar.gz")); !os.IsNotExist(serr) {
 | 
				
			||||||
 | 
							t.Error("v0.1.0 exists, when it shouldn't exist.")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if _, serr := os.Stat(filepath.Join(dname, "v0.1.1/example_linux_amd64.tar.gz")); !os.IsNotExist(serr) {
 | 
				
			||||||
 | 
							t.Error("v0.1.1 exists, when it shouldn't exist.")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if _, serr := os.Stat(filepath.Join(dname, "v0.1.2/example_linux_amd64.tar.gz")); os.IsNotExist(serr) {
 | 
				
			||||||
 | 
							t.Error("v0.1.2 does not exists, when it should.")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Cleanup.
 | 
				
			||||||
 | 
						os.RemoveAll(dname)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										71
									
								
								manifest.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								manifest.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,71 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"gopkg.in/yaml.v3"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// An individual asset.
 | 
				
			||||||
 | 
					type HttpAsset struct {
 | 
				
			||||||
 | 
						ID   int64  `yaml:"id"`
 | 
				
			||||||
 | 
						Name string `yaml:"name"`
 | 
				
			||||||
 | 
						Size int    `yaml:"size"`
 | 
				
			||||||
 | 
						URL  string `yaml:"url"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// An individual release.
 | 
				
			||||||
 | 
					type HttpRelease struct {
 | 
				
			||||||
 | 
						ReleaseID    int64        `yaml:"release_id"`
 | 
				
			||||||
 | 
						Name         string       `yaml:"name"`
 | 
				
			||||||
 | 
						TagName      string       `yaml:"tag_name"`
 | 
				
			||||||
 | 
						URL          string       `yaml:"url"`
 | 
				
			||||||
 | 
						Draft        bool         `yaml:"draft"`
 | 
				
			||||||
 | 
						Prerelease   bool         `yaml:"prerelease"`
 | 
				
			||||||
 | 
						PublishedAt  time.Time    `yaml:"published_at"`
 | 
				
			||||||
 | 
						ReleaseNotes string       `yaml:"release_notes"`
 | 
				
			||||||
 | 
						Assets       []*HttpAsset `yaml:"assets"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The manifest file structure.
 | 
				
			||||||
 | 
					type HttpManifest struct {
 | 
				
			||||||
 | 
						LastReleaseID int64          `yaml:"last_release_id"`
 | 
				
			||||||
 | 
						LastAssetID   int64          `yaml:"last_asset_id"`
 | 
				
			||||||
 | 
						Releases      []*HttpRelease `yaml:"releases"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Read and parse manifest file.
 | 
				
			||||||
 | 
					func readManifestFile(manifestFile string) (*HttpManifest, error) {
 | 
				
			||||||
 | 
						// We always want a manifest incase repo just needs to start from scratch.
 | 
				
			||||||
 | 
						manifest := new(HttpManifest)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Read file, if error return the error.
 | 
				
			||||||
 | 
						yamlFile, err := os.Open(manifestFile)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return manifest, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Attempt to decode the file.
 | 
				
			||||||
 | 
						decoder := yaml.NewDecoder(yamlFile)
 | 
				
			||||||
 | 
						err = decoder.Decode(manifest)
 | 
				
			||||||
 | 
						yamlFile.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Return the manifest and if any error occurred.
 | 
				
			||||||
 | 
						return manifest, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Write manifest file.
 | 
				
			||||||
 | 
					func writeManifestFile(manifestFile string, manifest *HttpManifest) error {
 | 
				
			||||||
 | 
						// Open the file for write.
 | 
				
			||||||
 | 
						yamlFile, err := os.OpenFile(manifestFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer yamlFile.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Encode data.
 | 
				
			||||||
 | 
						encoder := yaml.NewEncoder(yamlFile)
 | 
				
			||||||
 | 
						err = encoder.Encode(manifest)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										125
									
								
								prune_cmd.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								prune_cmd.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,125 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PruneCmd struct {
 | 
				
			||||||
 | 
						MaxAge      time.Duration `help:"Delete releases older than."`
 | 
				
			||||||
 | 
						MaxReleases int           `help:"Maximum number of releases to keep."`
 | 
				
			||||||
 | 
						DryRun      bool          `help:"Just log the result without actually pruning."`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Extra help to explain you can't set 2 prune stratages.
 | 
				
			||||||
 | 
					func (a *PruneCmd) Help() string {
 | 
				
			||||||
 | 
						return "You cannot use both max-age and max-releases, only set one."
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Verify the options provided to the command.
 | 
				
			||||||
 | 
					func (a *PruneCmd) AfterApply() error {
 | 
				
			||||||
 | 
						// If both stratages are defined, we don't allow that.
 | 
				
			||||||
 | 
						if a.MaxAge > time.Duration(0) && a.MaxReleases > 0 {
 | 
				
			||||||
 | 
							return errors.New("must only provide one prune argument")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// If no stratages are defined, we don't allow that.
 | 
				
			||||||
 | 
						if a.MaxAge <= time.Duration(0) && a.MaxReleases <= 0 {
 | 
				
			||||||
 | 
							return errors.New("must provide one prune argument")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Adds a release to a repo.
 | 
				
			||||||
 | 
					func (a *PruneCmd) Run() error {
 | 
				
			||||||
 | 
						// Read existing manifest for repo.
 | 
				
			||||||
 | 
						manifestFile := filepath.Join(app.flags.Repo, "manifest.yaml")
 | 
				
			||||||
 | 
						manifest, err := readManifestFile(manifestFile)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Keep reference of number of pruned releases.
 | 
				
			||||||
 | 
						releasesPruned := 0
 | 
				
			||||||
 | 
						n := len(manifest.Releases)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If max releases defined and is less than number of releases, look for items to prune.
 | 
				
			||||||
 | 
						if a.MaxReleases > 0 && n > a.MaxReleases {
 | 
				
			||||||
 | 
							// Loop starting at max releases.
 | 
				
			||||||
 | 
							for i := a.MaxReleases; i < n; i++ {
 | 
				
			||||||
 | 
								// Get the current release.
 | 
				
			||||||
 | 
								// We want pull from the top of the stack downward to keep newer releases.
 | 
				
			||||||
 | 
								version := manifest.Releases[n-(i+1)].TagName
 | 
				
			||||||
 | 
								log.Println("Removing release:", version)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// If this isn't a dry run, remove the version directory.
 | 
				
			||||||
 | 
								if !a.DryRun {
 | 
				
			||||||
 | 
									err = os.RemoveAll(filepath.Join(app.flags.Repo, version))
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										return fmt.Errorf("untable to remove release files: %s", err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Count the number pruned.
 | 
				
			||||||
 | 
								releasesPruned++
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Remove releases from the slice.
 | 
				
			||||||
 | 
							manifest.Releases = manifest.Releases[n-a.MaxReleases:]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If we are pruning based on duration, do so.
 | 
				
			||||||
 | 
						if a.MaxAge > time.Duration(0) {
 | 
				
			||||||
 | 
							// Loop through the releases, and find old releases.
 | 
				
			||||||
 | 
							for i := 0; i < n; i++ {
 | 
				
			||||||
 | 
								// If n is 1, we removed too many entries and need to stop.
 | 
				
			||||||
 | 
								if n == 1 {
 | 
				
			||||||
 | 
									log.Println("The repo has only 1 release remaining, ending the prune here to keep 1 release.")
 | 
				
			||||||
 | 
									break
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Get the current release, and confirm its age.
 | 
				
			||||||
 | 
								release := manifest.Releases[i]
 | 
				
			||||||
 | 
								if app.now.Sub(release.PublishedAt) >= a.MaxAge {
 | 
				
			||||||
 | 
									// This release is too old, so we need to remove it.
 | 
				
			||||||
 | 
									version := release.TagName
 | 
				
			||||||
 | 
									log.Println("Removing release:", version)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// If this isn't a dry run, remove the version files.
 | 
				
			||||||
 | 
									if !a.DryRun {
 | 
				
			||||||
 | 
										err = os.RemoveAll(filepath.Join(app.flags.Repo, version))
 | 
				
			||||||
 | 
										if err != nil {
 | 
				
			||||||
 | 
											return fmt.Errorf("untable to remove release files: %s", err)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Remove the release from the slice.
 | 
				
			||||||
 | 
									manifest.Releases = append(manifest.Releases[:i], manifest.Releases[i+1:]...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Back up one on the index and number of releases as one release was deleted.
 | 
				
			||||||
 | 
									i--
 | 
				
			||||||
 | 
									n--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Count number of releases pruned.
 | 
				
			||||||
 | 
									releasesPruned++
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Write the manifest if this isn't a dry run.
 | 
				
			||||||
 | 
						if !a.DryRun {
 | 
				
			||||||
 | 
							err = writeManifestFile(manifestFile, manifest)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Provide details on what's been pruned.
 | 
				
			||||||
 | 
						log.Println("Pruned", releasesPruned, "release from the repo.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										34
									
								
								tests/v0.1.1/artifacts.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								tests/v0.1.1/artifacts.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					[
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        "name": "metadata.json",
 | 
				
			||||||
 | 
					        "path": "v0.1.1/metadata.json",
 | 
				
			||||||
 | 
					        "internal_type": 30,
 | 
				
			||||||
 | 
					        "type": "Metadata"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        "name": "example_linux_amd64.tar.gz",
 | 
				
			||||||
 | 
					        "path": "v0.1.1/example_linux_amd64.tar.gz",
 | 
				
			||||||
 | 
					        "goos": "linux",
 | 
				
			||||||
 | 
					        "goarch": "amd64",
 | 
				
			||||||
 | 
					        "goamd64": "v1",
 | 
				
			||||||
 | 
					        "internal_type": 1,
 | 
				
			||||||
 | 
					        "type": "Archive",
 | 
				
			||||||
 | 
					        "extra": {
 | 
				
			||||||
 | 
					            "Binaries": [
 | 
				
			||||||
 | 
					                "example"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "Checksum": "sha256:9208c58af1265438c6894499847355bd5e77f93d04b201393baf41297d4680a3",
 | 
				
			||||||
 | 
					            "Format": "tar.gz",
 | 
				
			||||||
 | 
					            "ID": "default",
 | 
				
			||||||
 | 
					            "Replaces": null,
 | 
				
			||||||
 | 
					            "WrappedIn": "example_linux_amd64"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        "name": "checksums.txt",
 | 
				
			||||||
 | 
					        "path": "v0.1.1/checksums.txt",
 | 
				
			||||||
 | 
					        "internal_type": 12,
 | 
				
			||||||
 | 
					        "type": "Checksum",
 | 
				
			||||||
 | 
					        "extra": {}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
							
								
								
									
										1
									
								
								tests/v0.1.1/checksums.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/v0.1.1/checksums.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					9208c58af1265438c6894499847355bd5e77f93d04b201393baf41297d4680a3  example_linux_amd64.tar.gz
 | 
				
			||||||
							
								
								
									
										113
									
								
								tests/v0.1.1/config.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								tests/v0.1.1/config.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,113 @@
 | 
				
			|||||||
 | 
					version: 2
 | 
				
			||||||
 | 
					project_name: example
 | 
				
			||||||
 | 
					release:
 | 
				
			||||||
 | 
					  github:
 | 
				
			||||||
 | 
					    owner: GRMrGecko
 | 
				
			||||||
 | 
					    name: goreleaser-http-repo-builder
 | 
				
			||||||
 | 
					  name_template: '{{.Tag}}'
 | 
				
			||||||
 | 
					builds:
 | 
				
			||||||
 | 
					  - id: example
 | 
				
			||||||
 | 
					    goos:
 | 
				
			||||||
 | 
					      - linux
 | 
				
			||||||
 | 
					    goarch:
 | 
				
			||||||
 | 
					      - amd64
 | 
				
			||||||
 | 
					      - arm64
 | 
				
			||||||
 | 
					    goarm:
 | 
				
			||||||
 | 
					      - "6"
 | 
				
			||||||
 | 
					    gomips:
 | 
				
			||||||
 | 
					      - hardfloat
 | 
				
			||||||
 | 
					    goamd64:
 | 
				
			||||||
 | 
					      - v1
 | 
				
			||||||
 | 
					    targets:
 | 
				
			||||||
 | 
					      - linux_amd64_v1
 | 
				
			||||||
 | 
					      - linux_arm64
 | 
				
			||||||
 | 
					    dir: .
 | 
				
			||||||
 | 
					    main: .
 | 
				
			||||||
 | 
					    binary: example
 | 
				
			||||||
 | 
					    builder: go
 | 
				
			||||||
 | 
					    gobinary: go
 | 
				
			||||||
 | 
					    command: build
 | 
				
			||||||
 | 
					    ldflags:
 | 
				
			||||||
 | 
					      - -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}} -X main.builtBy=goreleaser
 | 
				
			||||||
 | 
					    env:
 | 
				
			||||||
 | 
					      - CGO_ENABLED=0
 | 
				
			||||||
 | 
					archives:
 | 
				
			||||||
 | 
					  - id: default
 | 
				
			||||||
 | 
					    name_template: '{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}'
 | 
				
			||||||
 | 
					    format: tar.gz
 | 
				
			||||||
 | 
					    wrap_in_directory: "true"
 | 
				
			||||||
 | 
					    files:
 | 
				
			||||||
 | 
					      - src: license*
 | 
				
			||||||
 | 
					      - src: LICENSE*
 | 
				
			||||||
 | 
					      - src: readme*
 | 
				
			||||||
 | 
					      - src: README*
 | 
				
			||||||
 | 
					      - src: changelog*
 | 
				
			||||||
 | 
					      - src: CHANGELOG*
 | 
				
			||||||
 | 
					snapshot:
 | 
				
			||||||
 | 
					  version_template: v0.1.0
 | 
				
			||||||
 | 
					checksum:
 | 
				
			||||||
 | 
					  name_template: checksums.txt
 | 
				
			||||||
 | 
					  algorithm: sha256
 | 
				
			||||||
 | 
					changelog:
 | 
				
			||||||
 | 
					  format: '{{ .SHA }}: {{ .Message }} ({{ with .AuthorUsername }}@{{ . }}{{ else }}{{ .AuthorName }} <{{ .AuthorEmail }}>{{ end }})'
 | 
				
			||||||
 | 
					dist: dist
 | 
				
			||||||
 | 
					env_files:
 | 
				
			||||||
 | 
					  github_token: ~/.config/goreleaser/github_token
 | 
				
			||||||
 | 
					  gitlab_token: ~/.config/goreleaser/gitlab_token
 | 
				
			||||||
 | 
					  gitea_token: ~/.config/goreleaser/gitea_token
 | 
				
			||||||
 | 
					before:
 | 
				
			||||||
 | 
					  hooks:
 | 
				
			||||||
 | 
					    - go mod tidy
 | 
				
			||||||
 | 
					source:
 | 
				
			||||||
 | 
					  name_template: '{{ .ProjectName }}-{{ .Version }}'
 | 
				
			||||||
 | 
					  format: tar.gz
 | 
				
			||||||
 | 
					gomod:
 | 
				
			||||||
 | 
					  gobinary: go
 | 
				
			||||||
 | 
					announce:
 | 
				
			||||||
 | 
					  twitter:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					  mastodon:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					    server: ""
 | 
				
			||||||
 | 
					  reddit:
 | 
				
			||||||
 | 
					    title_template: '{{ .ProjectName }} {{ .Tag }} is out!'
 | 
				
			||||||
 | 
					    url_template: '{{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					  slack:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					    username: GoReleaser
 | 
				
			||||||
 | 
					  discord:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					    author: GoReleaser
 | 
				
			||||||
 | 
					    color: "3888754"
 | 
				
			||||||
 | 
					    icon_url: https://goreleaser.com/static/avatar.png
 | 
				
			||||||
 | 
					  teams:
 | 
				
			||||||
 | 
					    title_template: '{{ .ProjectName }} {{ .Tag }} is out!'
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					    color: '#2D313E'
 | 
				
			||||||
 | 
					    icon_url: https://goreleaser.com/static/avatar.png
 | 
				
			||||||
 | 
					  smtp:
 | 
				
			||||||
 | 
					    subject_template: '{{ .ProjectName }} {{ .Tag }} is out!'
 | 
				
			||||||
 | 
					    body_template: 'You can view details from: {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					  mattermost:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					    title_template: '{{ .ProjectName }} {{ .Tag }} is out!'
 | 
				
			||||||
 | 
					    username: GoReleaser
 | 
				
			||||||
 | 
					  linkedin:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					  telegram:
 | 
				
			||||||
 | 
					    message_template: '{{ mdv2escape .ProjectName }} {{ mdv2escape .Tag }} is out{{ mdv2escape "!" }} Check it out at {{ mdv2escape .ReleaseURL }}'
 | 
				
			||||||
 | 
					    parse_mode: MarkdownV2
 | 
				
			||||||
 | 
					  webhook:
 | 
				
			||||||
 | 
					    message_template: '{ "message": "{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}"}'
 | 
				
			||||||
 | 
					    content_type: application/json; charset=utf-8
 | 
				
			||||||
 | 
					  opencollective:
 | 
				
			||||||
 | 
					    title_template: '{{ .Tag }}'
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out!<br/>Check it out at <a href="{{ .ReleaseURL }}">{{ .ReleaseURL }}</a>'
 | 
				
			||||||
 | 
					  bluesky:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					git:
 | 
				
			||||||
 | 
					  tag_sort: -version:refname
 | 
				
			||||||
 | 
					github_urls:
 | 
				
			||||||
 | 
					  download: https://github.com
 | 
				
			||||||
 | 
					gitlab_urls:
 | 
				
			||||||
 | 
					  download: https://gitlab.com
 | 
				
			||||||
							
								
								
									
										2
									
								
								tests/v0.1.1/example_linux_amd64.tar.gz
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								tests/v0.1.1/example_linux_amd64.tar.gz
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					ŽíõÞ}k© Î<>Iƒ`É<>cú|ÀGéNÙãðFñttV—hÉtÍËËõ€ÕØÙŸ¥øF
 | 
				
			||||||
							
								
								
									
										12
									
								
								tests/v0.1.1/metadata.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								tests/v0.1.1/metadata.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "project_name": "example",
 | 
				
			||||||
 | 
					    "tag": "v0.0.0",
 | 
				
			||||||
 | 
					    "previous_tag": "",
 | 
				
			||||||
 | 
					    "version": "v0.1.1",
 | 
				
			||||||
 | 
					    "commit": "521be63afb85d785ce36b4bd0d7412664593ac1d",
 | 
				
			||||||
 | 
					    "date": "2024-09-30T09:26:01.612178185-05:00",
 | 
				
			||||||
 | 
					    "runtime": {
 | 
				
			||||||
 | 
					        "goos": "linux",
 | 
				
			||||||
 | 
					        "goarch": "amd64"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										34
									
								
								tests/v0.1.2/artifacts.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								tests/v0.1.2/artifacts.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					[
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        "name": "metadata.json",
 | 
				
			||||||
 | 
					        "path": "v0.1.2/metadata.json",
 | 
				
			||||||
 | 
					        "internal_type": 30,
 | 
				
			||||||
 | 
					        "type": "Metadata"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        "name": "example_linux_amd64.tar.gz",
 | 
				
			||||||
 | 
					        "path": "v0.1.2/example_linux_amd64.tar.gz",
 | 
				
			||||||
 | 
					        "goos": "linux",
 | 
				
			||||||
 | 
					        "goarch": "amd64",
 | 
				
			||||||
 | 
					        "goamd64": "v1",
 | 
				
			||||||
 | 
					        "internal_type": 1,
 | 
				
			||||||
 | 
					        "type": "Archive",
 | 
				
			||||||
 | 
					        "extra": {
 | 
				
			||||||
 | 
					            "Binaries": [
 | 
				
			||||||
 | 
					                "example"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "Checksum": "sha256:9208c58af1265438c6894499847355bd5e77f93d04b201393baf41297d4680a3",
 | 
				
			||||||
 | 
					            "Format": "tar.gz",
 | 
				
			||||||
 | 
					            "ID": "default",
 | 
				
			||||||
 | 
					            "Replaces": null,
 | 
				
			||||||
 | 
					            "WrappedIn": "example_linux_amd64"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        "name": "checksums.txt",
 | 
				
			||||||
 | 
					        "path": "v0.1.2/checksums.txt",
 | 
				
			||||||
 | 
					        "internal_type": 12,
 | 
				
			||||||
 | 
					        "type": "Checksum",
 | 
				
			||||||
 | 
					        "extra": {}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
							
								
								
									
										1
									
								
								tests/v0.1.2/checksums.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/v0.1.2/checksums.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					9208c58af1265438c6894499847355bd5e77f93d04b201393baf41297d4680a3  example_linux_amd64.tar.gz
 | 
				
			||||||
							
								
								
									
										113
									
								
								tests/v0.1.2/config.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								tests/v0.1.2/config.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,113 @@
 | 
				
			|||||||
 | 
					version: 2
 | 
				
			||||||
 | 
					project_name: example
 | 
				
			||||||
 | 
					release:
 | 
				
			||||||
 | 
					  github:
 | 
				
			||||||
 | 
					    owner: GRMrGecko
 | 
				
			||||||
 | 
					    name: goreleaser-http-repo-builder
 | 
				
			||||||
 | 
					  name_template: '{{.Tag}}'
 | 
				
			||||||
 | 
					builds:
 | 
				
			||||||
 | 
					  - id: example
 | 
				
			||||||
 | 
					    goos:
 | 
				
			||||||
 | 
					      - linux
 | 
				
			||||||
 | 
					    goarch:
 | 
				
			||||||
 | 
					      - amd64
 | 
				
			||||||
 | 
					      - arm64
 | 
				
			||||||
 | 
					    goarm:
 | 
				
			||||||
 | 
					      - "6"
 | 
				
			||||||
 | 
					    gomips:
 | 
				
			||||||
 | 
					      - hardfloat
 | 
				
			||||||
 | 
					    goamd64:
 | 
				
			||||||
 | 
					      - v1
 | 
				
			||||||
 | 
					    targets:
 | 
				
			||||||
 | 
					      - linux_amd64_v1
 | 
				
			||||||
 | 
					      - linux_arm64
 | 
				
			||||||
 | 
					    dir: .
 | 
				
			||||||
 | 
					    main: .
 | 
				
			||||||
 | 
					    binary: example
 | 
				
			||||||
 | 
					    builder: go
 | 
				
			||||||
 | 
					    gobinary: go
 | 
				
			||||||
 | 
					    command: build
 | 
				
			||||||
 | 
					    ldflags:
 | 
				
			||||||
 | 
					      - -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}} -X main.builtBy=goreleaser
 | 
				
			||||||
 | 
					    env:
 | 
				
			||||||
 | 
					      - CGO_ENABLED=0
 | 
				
			||||||
 | 
					archives:
 | 
				
			||||||
 | 
					  - id: default
 | 
				
			||||||
 | 
					    name_template: '{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}'
 | 
				
			||||||
 | 
					    format: tar.gz
 | 
				
			||||||
 | 
					    wrap_in_directory: "true"
 | 
				
			||||||
 | 
					    files:
 | 
				
			||||||
 | 
					      - src: license*
 | 
				
			||||||
 | 
					      - src: LICENSE*
 | 
				
			||||||
 | 
					      - src: readme*
 | 
				
			||||||
 | 
					      - src: README*
 | 
				
			||||||
 | 
					      - src: changelog*
 | 
				
			||||||
 | 
					      - src: CHANGELOG*
 | 
				
			||||||
 | 
					snapshot:
 | 
				
			||||||
 | 
					  version_template: v0.1.0
 | 
				
			||||||
 | 
					checksum:
 | 
				
			||||||
 | 
					  name_template: checksums.txt
 | 
				
			||||||
 | 
					  algorithm: sha256
 | 
				
			||||||
 | 
					changelog:
 | 
				
			||||||
 | 
					  format: '{{ .SHA }}: {{ .Message }} ({{ with .AuthorUsername }}@{{ . }}{{ else }}{{ .AuthorName }} <{{ .AuthorEmail }}>{{ end }})'
 | 
				
			||||||
 | 
					dist: dist
 | 
				
			||||||
 | 
					env_files:
 | 
				
			||||||
 | 
					  github_token: ~/.config/goreleaser/github_token
 | 
				
			||||||
 | 
					  gitlab_token: ~/.config/goreleaser/gitlab_token
 | 
				
			||||||
 | 
					  gitea_token: ~/.config/goreleaser/gitea_token
 | 
				
			||||||
 | 
					before:
 | 
				
			||||||
 | 
					  hooks:
 | 
				
			||||||
 | 
					    - go mod tidy
 | 
				
			||||||
 | 
					source:
 | 
				
			||||||
 | 
					  name_template: '{{ .ProjectName }}-{{ .Version }}'
 | 
				
			||||||
 | 
					  format: tar.gz
 | 
				
			||||||
 | 
					gomod:
 | 
				
			||||||
 | 
					  gobinary: go
 | 
				
			||||||
 | 
					announce:
 | 
				
			||||||
 | 
					  twitter:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					  mastodon:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					    server: ""
 | 
				
			||||||
 | 
					  reddit:
 | 
				
			||||||
 | 
					    title_template: '{{ .ProjectName }} {{ .Tag }} is out!'
 | 
				
			||||||
 | 
					    url_template: '{{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					  slack:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					    username: GoReleaser
 | 
				
			||||||
 | 
					  discord:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					    author: GoReleaser
 | 
				
			||||||
 | 
					    color: "3888754"
 | 
				
			||||||
 | 
					    icon_url: https://goreleaser.com/static/avatar.png
 | 
				
			||||||
 | 
					  teams:
 | 
				
			||||||
 | 
					    title_template: '{{ .ProjectName }} {{ .Tag }} is out!'
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					    color: '#2D313E'
 | 
				
			||||||
 | 
					    icon_url: https://goreleaser.com/static/avatar.png
 | 
				
			||||||
 | 
					  smtp:
 | 
				
			||||||
 | 
					    subject_template: '{{ .ProjectName }} {{ .Tag }} is out!'
 | 
				
			||||||
 | 
					    body_template: 'You can view details from: {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					  mattermost:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					    title_template: '{{ .ProjectName }} {{ .Tag }} is out!'
 | 
				
			||||||
 | 
					    username: GoReleaser
 | 
				
			||||||
 | 
					  linkedin:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					  telegram:
 | 
				
			||||||
 | 
					    message_template: '{{ mdv2escape .ProjectName }} {{ mdv2escape .Tag }} is out{{ mdv2escape "!" }} Check it out at {{ mdv2escape .ReleaseURL }}'
 | 
				
			||||||
 | 
					    parse_mode: MarkdownV2
 | 
				
			||||||
 | 
					  webhook:
 | 
				
			||||||
 | 
					    message_template: '{ "message": "{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}"}'
 | 
				
			||||||
 | 
					    content_type: application/json; charset=utf-8
 | 
				
			||||||
 | 
					  opencollective:
 | 
				
			||||||
 | 
					    title_template: '{{ .Tag }}'
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out!<br/>Check it out at <a href="{{ .ReleaseURL }}">{{ .ReleaseURL }}</a>'
 | 
				
			||||||
 | 
					  bluesky:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					git:
 | 
				
			||||||
 | 
					  tag_sort: -version:refname
 | 
				
			||||||
 | 
					github_urls:
 | 
				
			||||||
 | 
					  download: https://github.com
 | 
				
			||||||
 | 
					gitlab_urls:
 | 
				
			||||||
 | 
					  download: https://gitlab.com
 | 
				
			||||||
							
								
								
									
										2
									
								
								tests/v0.1.2/example_linux_amd64.tar.gz
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								tests/v0.1.2/example_linux_amd64.tar.gz
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					ŽíõÞ}k© Î<>Iƒ`É<>cú|ÀGéNÙãðFñttV—hÉtÍËËõ€ÕØÙŸ¥øF
 | 
				
			||||||
							
								
								
									
										12
									
								
								tests/v0.1.2/metadata.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								tests/v0.1.2/metadata.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "project_name": "example",
 | 
				
			||||||
 | 
					    "tag": "v0.0.0",
 | 
				
			||||||
 | 
					    "previous_tag": "",
 | 
				
			||||||
 | 
					    "version": "v0.1.2",
 | 
				
			||||||
 | 
					    "commit": "94bb85eb32ea07f33d627ce0dee905e29d8d1c96",
 | 
				
			||||||
 | 
					    "date": "2024-10-07T22:15:21.731224367-05:00",
 | 
				
			||||||
 | 
					    "runtime": {
 | 
				
			||||||
 | 
					        "goos": "linux",
 | 
				
			||||||
 | 
					        "goarch": "amd64"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										47
									
								
								tests/v0.1/artifacts.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								tests/v0.1/artifacts.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					[
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        "name": "metadata.json",
 | 
				
			||||||
 | 
					        "path": "v0.1/metadata.json",
 | 
				
			||||||
 | 
					        "internal_type": 30,
 | 
				
			||||||
 | 
					        "type": "Metadata"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        "name": "example",
 | 
				
			||||||
 | 
					        "path": "v0.1/example_linux_amd64/example",
 | 
				
			||||||
 | 
					        "goos": "linux",
 | 
				
			||||||
 | 
					        "goarch": "amd64",
 | 
				
			||||||
 | 
					        "internal_type": 4,
 | 
				
			||||||
 | 
					        "type": "Binary",
 | 
				
			||||||
 | 
					        "extra": {
 | 
				
			||||||
 | 
					            "Binary": "example",
 | 
				
			||||||
 | 
					            "Ext": "",
 | 
				
			||||||
 | 
					            "ID": "example"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        "name": "example_linux_amd64.tar.gz",
 | 
				
			||||||
 | 
					        "path": "v0.1/example_linux_amd64.tar.gz",
 | 
				
			||||||
 | 
					        "goos": "linux",
 | 
				
			||||||
 | 
					        "goarch": "amd64",
 | 
				
			||||||
 | 
					        "goamd64": "v1",
 | 
				
			||||||
 | 
					        "internal_type": 1,
 | 
				
			||||||
 | 
					        "type": "Archive",
 | 
				
			||||||
 | 
					        "extra": {
 | 
				
			||||||
 | 
					            "Binaries": [
 | 
				
			||||||
 | 
					                "example"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "Checksum": "sha256:9208c58af1265438c6894499847355bd5e77f93d04b201393baf41297d4680a3",
 | 
				
			||||||
 | 
					            "Format": "tar.gz",
 | 
				
			||||||
 | 
					            "ID": "default",
 | 
				
			||||||
 | 
					            "Replaces": null,
 | 
				
			||||||
 | 
					            "WrappedIn": "example_linux_amd64"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        "name": "checksums.txt",
 | 
				
			||||||
 | 
					        "path": "v0.1/checksums.txt",
 | 
				
			||||||
 | 
					        "internal_type": 12,
 | 
				
			||||||
 | 
					        "type": "Checksum",
 | 
				
			||||||
 | 
					        "extra": {}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
							
								
								
									
										1
									
								
								tests/v0.1/checksums.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/v0.1/checksums.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					9208c58af1265438c6894499847355bd5e77f93d04b201393baf41297d4680a3  example_linux_amd64.tar.gz
 | 
				
			||||||
							
								
								
									
										113
									
								
								tests/v0.1/config.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								tests/v0.1/config.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,113 @@
 | 
				
			|||||||
 | 
					version: 2
 | 
				
			||||||
 | 
					project_name: example
 | 
				
			||||||
 | 
					release:
 | 
				
			||||||
 | 
					  github:
 | 
				
			||||||
 | 
					    owner: GRMrGecko
 | 
				
			||||||
 | 
					    name: goreleaser-http-repo-builder
 | 
				
			||||||
 | 
					  name_template: '{{.Tag}}'
 | 
				
			||||||
 | 
					builds:
 | 
				
			||||||
 | 
					  - id: example
 | 
				
			||||||
 | 
					    goos:
 | 
				
			||||||
 | 
					      - linux
 | 
				
			||||||
 | 
					    goarch:
 | 
				
			||||||
 | 
					      - amd64
 | 
				
			||||||
 | 
					      - arm64
 | 
				
			||||||
 | 
					    goarm:
 | 
				
			||||||
 | 
					      - "6"
 | 
				
			||||||
 | 
					    gomips:
 | 
				
			||||||
 | 
					      - hardfloat
 | 
				
			||||||
 | 
					    goamd64:
 | 
				
			||||||
 | 
					      - v1
 | 
				
			||||||
 | 
					    targets:
 | 
				
			||||||
 | 
					      - linux_amd64_v1
 | 
				
			||||||
 | 
					      - linux_arm64
 | 
				
			||||||
 | 
					    dir: .
 | 
				
			||||||
 | 
					    main: .
 | 
				
			||||||
 | 
					    binary: example
 | 
				
			||||||
 | 
					    builder: go
 | 
				
			||||||
 | 
					    gobinary: go
 | 
				
			||||||
 | 
					    command: build
 | 
				
			||||||
 | 
					    ldflags:
 | 
				
			||||||
 | 
					      - -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}} -X main.builtBy=goreleaser
 | 
				
			||||||
 | 
					    env:
 | 
				
			||||||
 | 
					      - CGO_ENABLED=0
 | 
				
			||||||
 | 
					archives:
 | 
				
			||||||
 | 
					  - id: default
 | 
				
			||||||
 | 
					    name_template: '{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}'
 | 
				
			||||||
 | 
					    format: tar.gz
 | 
				
			||||||
 | 
					    wrap_in_directory: "true"
 | 
				
			||||||
 | 
					    files:
 | 
				
			||||||
 | 
					      - src: license*
 | 
				
			||||||
 | 
					      - src: LICENSE*
 | 
				
			||||||
 | 
					      - src: readme*
 | 
				
			||||||
 | 
					      - src: README*
 | 
				
			||||||
 | 
					      - src: changelog*
 | 
				
			||||||
 | 
					      - src: CHANGELOG*
 | 
				
			||||||
 | 
					snapshot:
 | 
				
			||||||
 | 
					  version_template: v0.1.0
 | 
				
			||||||
 | 
					checksum:
 | 
				
			||||||
 | 
					  name_template: checksums.txt
 | 
				
			||||||
 | 
					  algorithm: sha256
 | 
				
			||||||
 | 
					changelog:
 | 
				
			||||||
 | 
					  format: '{{ .SHA }}: {{ .Message }} ({{ with .AuthorUsername }}@{{ . }}{{ else }}{{ .AuthorName }} <{{ .AuthorEmail }}>{{ end }})'
 | 
				
			||||||
 | 
					dist: dist
 | 
				
			||||||
 | 
					env_files:
 | 
				
			||||||
 | 
					  github_token: ~/.config/goreleaser/github_token
 | 
				
			||||||
 | 
					  gitlab_token: ~/.config/goreleaser/gitlab_token
 | 
				
			||||||
 | 
					  gitea_token: ~/.config/goreleaser/gitea_token
 | 
				
			||||||
 | 
					before:
 | 
				
			||||||
 | 
					  hooks:
 | 
				
			||||||
 | 
					    - go mod tidy
 | 
				
			||||||
 | 
					source:
 | 
				
			||||||
 | 
					  name_template: '{{ .ProjectName }}-{{ .Version }}'
 | 
				
			||||||
 | 
					  format: tar.gz
 | 
				
			||||||
 | 
					gomod:
 | 
				
			||||||
 | 
					  gobinary: go
 | 
				
			||||||
 | 
					announce:
 | 
				
			||||||
 | 
					  twitter:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					  mastodon:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					    server: ""
 | 
				
			||||||
 | 
					  reddit:
 | 
				
			||||||
 | 
					    title_template: '{{ .ProjectName }} {{ .Tag }} is out!'
 | 
				
			||||||
 | 
					    url_template: '{{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					  slack:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					    username: GoReleaser
 | 
				
			||||||
 | 
					  discord:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					    author: GoReleaser
 | 
				
			||||||
 | 
					    color: "3888754"
 | 
				
			||||||
 | 
					    icon_url: https://goreleaser.com/static/avatar.png
 | 
				
			||||||
 | 
					  teams:
 | 
				
			||||||
 | 
					    title_template: '{{ .ProjectName }} {{ .Tag }} is out!'
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					    color: '#2D313E'
 | 
				
			||||||
 | 
					    icon_url: https://goreleaser.com/static/avatar.png
 | 
				
			||||||
 | 
					  smtp:
 | 
				
			||||||
 | 
					    subject_template: '{{ .ProjectName }} {{ .Tag }} is out!'
 | 
				
			||||||
 | 
					    body_template: 'You can view details from: {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					  mattermost:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					    title_template: '{{ .ProjectName }} {{ .Tag }} is out!'
 | 
				
			||||||
 | 
					    username: GoReleaser
 | 
				
			||||||
 | 
					  linkedin:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					  telegram:
 | 
				
			||||||
 | 
					    message_template: '{{ mdv2escape .ProjectName }} {{ mdv2escape .Tag }} is out{{ mdv2escape "!" }} Check it out at {{ mdv2escape .ReleaseURL }}'
 | 
				
			||||||
 | 
					    parse_mode: MarkdownV2
 | 
				
			||||||
 | 
					  webhook:
 | 
				
			||||||
 | 
					    message_template: '{ "message": "{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}"}'
 | 
				
			||||||
 | 
					    content_type: application/json; charset=utf-8
 | 
				
			||||||
 | 
					  opencollective:
 | 
				
			||||||
 | 
					    title_template: '{{ .Tag }}'
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out!<br/>Check it out at <a href="{{ .ReleaseURL }}">{{ .ReleaseURL }}</a>'
 | 
				
			||||||
 | 
					  bluesky:
 | 
				
			||||||
 | 
					    message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
 | 
				
			||||||
 | 
					git:
 | 
				
			||||||
 | 
					  tag_sort: -version:refname
 | 
				
			||||||
 | 
					github_urls:
 | 
				
			||||||
 | 
					  download: https://github.com
 | 
				
			||||||
 | 
					gitlab_urls:
 | 
				
			||||||
 | 
					  download: https://gitlab.com
 | 
				
			||||||
							
								
								
									
										2
									
								
								tests/v0.1/example_linux_amd64.tar.gz
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								tests/v0.1/example_linux_amd64.tar.gz
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					ŽíõÞ}k© Î<>Iƒ`É<>cú|ÀGéNÙãðFñttV—hÉtÍËËõ€ÕØÙŸ¥øF
 | 
				
			||||||
							
								
								
									
										2
									
								
								tests/v0.1/example_linux_amd64/example
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								tests/v0.1/example_linux_amd64/example
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					ŽíõÞ}k© Î<>Iƒ`É<>cú|ÀGéNÙãðFñttV—hÉtÍËËõ€ÕØÙŸ¥øF
 | 
				
			||||||
							
								
								
									
										12
									
								
								tests/v0.1/metadata.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								tests/v0.1/metadata.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "project_name": "example",
 | 
				
			||||||
 | 
					    "tag": "v0.0.0",
 | 
				
			||||||
 | 
					    "previous_tag": "",
 | 
				
			||||||
 | 
					    "version": "v0.1.0",
 | 
				
			||||||
 | 
					    "commit": "1869b4455d572d3e3c7e00114586b47f184a2e35",
 | 
				
			||||||
 | 
					    "date": "2024-09-27T12:10:11.314135185-05:00",
 | 
				
			||||||
 | 
					    "runtime": {
 | 
				
			||||||
 | 
					        "goos": "linux",
 | 
				
			||||||
 | 
					        "goarch": "amd64"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										61
									
								
								util.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								util.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bufio"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Helper for CLI to ask for confirmation.
 | 
				
			||||||
 | 
					func askForConfirmation(message string) bool {
 | 
				
			||||||
 | 
						// Read stdanrd input for each new line.
 | 
				
			||||||
 | 
						scanner := bufio.NewScanner(os.Stdin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Loop the question until answered.
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							fmt.Printf("%s [y/n]: ", message)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Get next line.
 | 
				
			||||||
 | 
							scanner.Scan()
 | 
				
			||||||
 | 
							resp := strings.ToLower(strings.TrimSpace(scanner.Text()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Check if yes or no.
 | 
				
			||||||
 | 
							switch resp {
 | 
				
			||||||
 | 
							case "y", "yes":
 | 
				
			||||||
 | 
								return true
 | 
				
			||||||
 | 
							case "n", "no":
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								fmt.Println("Invalid answer.")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Helper for copying files.
 | 
				
			||||||
 | 
					func copyFile(srcFile, dstFile string) (err error) {
 | 
				
			||||||
 | 
						// Open the source file.
 | 
				
			||||||
 | 
						f, err := os.Open(srcFile)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer f.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Open the destination file.
 | 
				
			||||||
 | 
						d, err := os.Create(dstFile)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer d.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Copy the data to the new file.
 | 
				
			||||||
 | 
						_, err = io.Copy(d, f)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Ensure new file is fully written.
 | 
				
			||||||
 | 
						err = d.Sync()
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user