mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-07 20:30:36 -05:00
parent
c98348416c
commit
45e1084ff2
13 changed files with 447 additions and 1192 deletions
|
@ -1,51 +1,114 @@
|
||||||
defaults: &defaults
|
parameters:
|
||||||
docker:
|
|
||||||
- image: bepsays/ci-goreleaser:1.21900.20000
|
|
||||||
environment:
|
|
||||||
CGO_ENABLED: "0"
|
|
||||||
|
|
||||||
|
# v2: 11m.
|
||||||
|
defaults: &defaults
|
||||||
|
resource_class: large
|
||||||
|
docker:
|
||||||
|
- image: bepsays/ci-hugoreleaser:1.21900.20000
|
||||||
|
environment: &buildenv
|
||||||
|
GOMODCACHE: /root/project/gomodcache
|
||||||
version: 2
|
version: 2
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
prepare_release:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
|
environment: &buildenv
|
||||||
|
GOMODCACHE: /root/project/gomodcache
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- &remote-docker
|
||||||
|
setup_remote_docker:
|
||||||
|
version: 20.10.14
|
||||||
|
- checkout:
|
||||||
path: hugo
|
path: hugo
|
||||||
|
- &git-config
|
||||||
|
run:
|
||||||
|
command: |
|
||||||
|
git config --global user.email "bjorn.erik.pedersen+hugoreleaser@gmail.com"
|
||||||
|
git config --global user.name "hugoreleaser"
|
||||||
- run:
|
- run:
|
||||||
command: |
|
command: |
|
||||||
git clone git@github.com:gohugoio/hugoDocs.git
|
cd hugo
|
||||||
cd hugo
|
go mod download
|
||||||
go mod download
|
go run -tags release main.go release --step 1
|
||||||
sleep 5
|
- save_cache:
|
||||||
go mod verify
|
key: git-sha-{{ .Revision }}
|
||||||
- persist_to_workspace:
|
paths:
|
||||||
root: .
|
- hugo
|
||||||
paths: .
|
- gomodcache
|
||||||
release:
|
build_container1:
|
||||||
<<: *defaults
|
<<: [*defaults]
|
||||||
|
environment:
|
||||||
|
<<: [*buildenv]
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- &restore-cache
|
||||||
at: /root/project
|
restore_cache:
|
||||||
|
key: git-sha-{{ .Revision }}
|
||||||
- run:
|
- run:
|
||||||
command: |
|
no_output_timeout: 20m
|
||||||
cd hugo
|
command: |
|
||||||
git config --global user.email "bjorn.erik.pedersen+hugoreleaser@gmail.com"
|
mkdir -p /tmp/files/dist1
|
||||||
git config --global user.name "hugoreleaser"
|
cd hugo
|
||||||
go run -tags release main.go release -r ${CIRCLE_BRANCH}
|
hugoreleaser build -paths "builds/container1/**" -workers 3 -dist /tmp/files/dist1 -chunks $CIRCLE_NODE_TOTAL -chunk-index $CIRCLE_NODE_INDEX
|
||||||
|
- &persist-workspace
|
||||||
|
persist_to_workspace:
|
||||||
|
root: /tmp/files
|
||||||
|
paths:
|
||||||
|
- dist1
|
||||||
|
- dist2
|
||||||
|
parallelism: 7
|
||||||
|
build_container2:
|
||||||
|
<<: [*defaults]
|
||||||
|
environment:
|
||||||
|
<<: [*buildenv]
|
||||||
|
docker:
|
||||||
|
- image: bepsays/ci-hugoreleaser-linux-arm64:1.21900.20000
|
||||||
|
steps:
|
||||||
|
- *restore-cache
|
||||||
|
- &attach-workspace
|
||||||
|
attach_workspace:
|
||||||
|
at: /tmp/workspace
|
||||||
|
- run:
|
||||||
|
command: |
|
||||||
|
mkdir -p /tmp/files/dist2
|
||||||
|
cd hugo
|
||||||
|
hugoreleaser build -paths "builds/container2/**" -workers 1 -dist /tmp/files/dist2
|
||||||
|
- *persist-workspace
|
||||||
|
archive_and_release:
|
||||||
|
<<: [*defaults]
|
||||||
|
environment:
|
||||||
|
<<: [*buildenv]
|
||||||
|
steps:
|
||||||
|
- *restore-cache
|
||||||
|
- *attach-workspace
|
||||||
|
- *git-config
|
||||||
|
- run:
|
||||||
|
command: |
|
||||||
|
cp -a /tmp/workspace/dist1/. ./hugo/dist
|
||||||
|
cp -a /tmp/workspace/dist2/. ./hugo/dist
|
||||||
|
- run:
|
||||||
|
command: |
|
||||||
|
cd hugo
|
||||||
|
hugoreleaser archive
|
||||||
|
hugoreleaser release
|
||||||
|
go run -tags release main.go release --step 2
|
||||||
workflows:
|
workflows:
|
||||||
version: 2
|
version: 2
|
||||||
release:
|
release:
|
||||||
jobs:
|
jobs:
|
||||||
- build:
|
- prepare_release:
|
||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
only: /release-.*/
|
only: /release-.*/
|
||||||
- hold:
|
- build_container1:
|
||||||
type: approval
|
|
||||||
requires:
|
requires:
|
||||||
- build
|
- prepare_release
|
||||||
- release:
|
- build_container2:
|
||||||
|
requires:
|
||||||
|
- prepare_release
|
||||||
|
- archive_and_release:
|
||||||
context: org-global
|
context: org-global
|
||||||
requires:
|
requires:
|
||||||
- hold
|
- build_container1
|
||||||
|
- build_container2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/config"
|
"github.com/gohugoio/hugo/config"
|
||||||
"github.com/gohugoio/hugo/releaser"
|
"github.com/gohugoio/hugo/releaser"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -29,10 +27,9 @@ var _ cmder = (*releaseCommandeer)(nil)
|
||||||
type releaseCommandeer struct {
|
type releaseCommandeer struct {
|
||||||
cmd *cobra.Command
|
cmd *cobra.Command
|
||||||
|
|
||||||
version string
|
step int
|
||||||
|
skipPush bool
|
||||||
skipPublish bool
|
try bool
|
||||||
try bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func createReleaser() cmder {
|
func createReleaser() cmder {
|
||||||
|
@ -50,9 +47,9 @@ func createReleaser() cmder {
|
||||||
return r.release()
|
return r.release()
|
||||||
}
|
}
|
||||||
|
|
||||||
r.cmd.PersistentFlags().StringVarP(&r.version, "rel", "r", "", "new release version, i.e. 0.25.1")
|
r.cmd.PersistentFlags().BoolVarP(&r.skipPush, "skip-push", "", false, "skip pushing to remote")
|
||||||
r.cmd.PersistentFlags().BoolVarP(&r.skipPublish, "skip-publish", "", false, "skip all publishing pipes of the release")
|
r.cmd.PersistentFlags().BoolVarP(&r.try, "try", "", false, "no changes")
|
||||||
r.cmd.PersistentFlags().BoolVarP(&r.try, "try", "", false, "simulate a release, i.e. no changes")
|
r.cmd.PersistentFlags().IntVarP(&r.step, "step", "", 0, "step to run (1: set new version 2: prepare next dev version)")
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
@ -65,8 +62,10 @@ func (c *releaseCommandeer) flagsToConfig(cfg config.Provider) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *releaseCommandeer) release() error {
|
func (r *releaseCommandeer) release() error {
|
||||||
if r.version == "" {
|
rel, err := releaser.New(r.skipPush, r.try, r.step)
|
||||||
return errors.New("must set the --rel flag to the relevant version number")
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
return releaser.New(r.version, r.skipPublish, r.try).Run()
|
|
||||||
|
return rel.Run()
|
||||||
}
|
}
|
||||||
|
|
214
goreleaser.yml
214
goreleaser.yml
|
@ -1,214 +0,0 @@
|
||||||
project_name: hugo
|
|
||||||
env:
|
|
||||||
- GO111MODULE=on
|
|
||||||
- GOPROXY=https://proxy.golang.org
|
|
||||||
before:
|
|
||||||
hooks:
|
|
||||||
- go mod download
|
|
||||||
builds:
|
|
||||||
-
|
|
||||||
binary: hugo
|
|
||||||
id: hugo
|
|
||||||
ldflags: -s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
|
|
||||||
env:
|
|
||||||
- CGO_ENABLED=0
|
|
||||||
flags:
|
|
||||||
- -buildmode
|
|
||||||
- exe
|
|
||||||
goos:
|
|
||||||
- darwin
|
|
||||||
- linux
|
|
||||||
- windows
|
|
||||||
goarch:
|
|
||||||
- amd64
|
|
||||||
- 386
|
|
||||||
- arm
|
|
||||||
- arm64
|
|
||||||
goarm:
|
|
||||||
- 7
|
|
||||||
ignore:
|
|
||||||
- goos: darwin
|
|
||||||
goarch: 386
|
|
||||||
-
|
|
||||||
binary: hugo
|
|
||||||
id: hugo_unix
|
|
||||||
ldflags: -s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
|
|
||||||
env:
|
|
||||||
- CGO_ENABLED=0
|
|
||||||
flags:
|
|
||||||
- -buildmode
|
|
||||||
- exe
|
|
||||||
goos:
|
|
||||||
- freebsd
|
|
||||||
- netbsd
|
|
||||||
- openbsd
|
|
||||||
- dragonfly
|
|
||||||
goarch:
|
|
||||||
- amd64
|
|
||||||
-
|
|
||||||
binary: hugo
|
|
||||||
id: hugo_extended_windows
|
|
||||||
ldflags:
|
|
||||||
- -s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
|
|
||||||
- "-extldflags '-static'"
|
|
||||||
env:
|
|
||||||
- CGO_ENABLED=1
|
|
||||||
- CC=x86_64-w64-mingw32-gcc
|
|
||||||
- CXX=x86_64-w64-mingw32-g++
|
|
||||||
flags:
|
|
||||||
- -buildmode
|
|
||||||
- exe
|
|
||||||
- -tags
|
|
||||||
- extended
|
|
||||||
goos:
|
|
||||||
- windows
|
|
||||||
goarch:
|
|
||||||
- amd64
|
|
||||||
- binary: hugo
|
|
||||||
id: hugo_extended_darwin
|
|
||||||
ldflags: -s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
|
|
||||||
env:
|
|
||||||
- CGO_ENABLED=1
|
|
||||||
- CC=o64-clang
|
|
||||||
- CXX=o64-clang++
|
|
||||||
flags:
|
|
||||||
- -buildmode
|
|
||||||
- exe
|
|
||||||
- -tags
|
|
||||||
- extended
|
|
||||||
goos:
|
|
||||||
- darwin
|
|
||||||
goarch:
|
|
||||||
- amd64
|
|
||||||
- arm64
|
|
||||||
- binary: hugo
|
|
||||||
id: hugo_extended_linux
|
|
||||||
ldflags: -s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
|
|
||||||
env:
|
|
||||||
- CGO_ENABLED=1
|
|
||||||
flags:
|
|
||||||
- -buildmode
|
|
||||||
- exe
|
|
||||||
- -tags
|
|
||||||
- extended
|
|
||||||
goos:
|
|
||||||
- linux
|
|
||||||
goarch:
|
|
||||||
- amd64
|
|
||||||
hooks:
|
|
||||||
post: ./goreleaser-hook-post-linux.sh
|
|
||||||
release:
|
|
||||||
draft: true
|
|
||||||
|
|
||||||
archives:
|
|
||||||
-
|
|
||||||
id: "hugo"
|
|
||||||
builds: ['hugo', 'hugo_unix', 'hugo_fat_darwin']
|
|
||||||
format: tar.gz
|
|
||||||
format_overrides:
|
|
||||||
- goos: windows
|
|
||||||
format: zip
|
|
||||||
name_template: "{{.ProjectName}}_{{.Version}}_{{.Os}}-{{.Arch}}"
|
|
||||||
replacements:
|
|
||||||
amd64: 64bit
|
|
||||||
386: 32bit
|
|
||||||
arm: ARM
|
|
||||||
arm64: ARM64
|
|
||||||
darwin: macOS
|
|
||||||
linux: Linux
|
|
||||||
windows: Windows
|
|
||||||
openbsd: OpenBSD
|
|
||||||
netbsd: NetBSD
|
|
||||||
freebsd: FreeBSD
|
|
||||||
dragonfly: DragonFlyBSD
|
|
||||||
files:
|
|
||||||
- README.md
|
|
||||||
- LICENSE
|
|
||||||
-
|
|
||||||
id: "hugo_extended"
|
|
||||||
builds: ['hugo_extended_windows', 'hugo_extended_linux', 'hugo_extended_fat_darwin']
|
|
||||||
format: tar.gz
|
|
||||||
format_overrides:
|
|
||||||
- goos: windows
|
|
||||||
format: zip
|
|
||||||
name_template: "{{.ProjectName}}_extended_{{.Version}}_{{.Os}}-{{.Arch}}"
|
|
||||||
replacements:
|
|
||||||
amd64: 64bit
|
|
||||||
386: 32bit
|
|
||||||
arm: ARM
|
|
||||||
arm64: ARM64
|
|
||||||
darwin: macOS
|
|
||||||
linux: Linux
|
|
||||||
windows: Windows
|
|
||||||
openbsd: OpenBSD
|
|
||||||
netbsd: NetBSD
|
|
||||||
freebsd: FreeBSD
|
|
||||||
dragonfly: DragonFlyBSD
|
|
||||||
files:
|
|
||||||
- README.md
|
|
||||||
- LICENSE
|
|
||||||
|
|
||||||
universal_binaries:
|
|
||||||
-
|
|
||||||
id: hugo_fat_darwin
|
|
||||||
|
|
||||||
ids:
|
|
||||||
- hugo
|
|
||||||
|
|
||||||
replace: true
|
|
||||||
|
|
||||||
-
|
|
||||||
id: hugo_extended_fat_darwin
|
|
||||||
|
|
||||||
ids:
|
|
||||||
- hugo_extended_darwin
|
|
||||||
|
|
||||||
replace: true
|
|
||||||
|
|
||||||
nfpms:
|
|
||||||
-
|
|
||||||
id: "hugo"
|
|
||||||
builds: ['hugo']
|
|
||||||
formats:
|
|
||||||
- deb
|
|
||||||
vendor: "gohugo.io"
|
|
||||||
homepage: "https://gohugo.io/"
|
|
||||||
maintainer: "Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>"
|
|
||||||
description: "A Fast and Flexible Static Site Generator built with love in GoLang."
|
|
||||||
license: "Apache-2.0"
|
|
||||||
file_name_template: "{{.ProjectName}}_{{.Version}}_{{.Os}}-{{.Arch}}"
|
|
||||||
replacements:
|
|
||||||
amd64: 64bit
|
|
||||||
386: 32bit
|
|
||||||
arm: ARM
|
|
||||||
arm64: ARM64
|
|
||||||
darwin: macOS
|
|
||||||
linux: Linux
|
|
||||||
windows: Windows
|
|
||||||
openbsd: OpenBSD
|
|
||||||
netbsd: NetBSD
|
|
||||||
freebsd: FreeBSD
|
|
||||||
dragonfly: DragonFlyBSD
|
|
||||||
-
|
|
||||||
id: "hugo_extended"
|
|
||||||
builds: ['hugo_extended_linux']
|
|
||||||
formats:
|
|
||||||
- deb
|
|
||||||
vendor: "gohugo.io"
|
|
||||||
homepage: "https://gohugo.io/"
|
|
||||||
maintainer: "Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>"
|
|
||||||
description: "A Fast and Flexible Static Site Generator built with love in GoLang."
|
|
||||||
license: "Apache-2.0"
|
|
||||||
file_name_template: "{{.ProjectName}}_extended_{{.Version}}_{{.Os}}-{{.Arch}}"
|
|
||||||
replacements:
|
|
||||||
amd64: 64bit
|
|
||||||
386: 32bit
|
|
||||||
arm: ARM
|
|
||||||
arm64: ARM64
|
|
||||||
darwin: macOS
|
|
||||||
linux: Linux
|
|
||||||
windows: Windows
|
|
||||||
openbsd: OpenBSD
|
|
||||||
netbsd: NetBSD
|
|
||||||
freebsd: FreeBSD
|
|
||||||
dragonfly: DragonFlyBSD
|
|
6
hugoreleaser.env
Normal file
6
hugoreleaser.env
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
HUGO_RELEASE_NAME=New release setup
|
||||||
|
|
||||||
|
# Release env.
|
||||||
|
# These will be replaced by script before release.
|
||||||
|
HUGORELEASER_TAG=xxx
|
||||||
|
HUGORELEASER_COMMITISH=xxx
|
232
hugoreleaser.toml
Normal file
232
hugoreleaser.toml
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
project = "hugo"
|
||||||
|
|
||||||
|
[go_settings]
|
||||||
|
go_proxy = "https://proxy.golang.org"
|
||||||
|
go_exe = "go"
|
||||||
|
|
||||||
|
[build_settings]
|
||||||
|
binary = "hugo"
|
||||||
|
flags = ["-buildmode", "exe"]
|
||||||
|
env = ["CGO_ENABLED=0"]
|
||||||
|
ldflags = "-s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio"
|
||||||
|
|
||||||
|
[archive_settings]
|
||||||
|
name_template = "{{ .Project }}_{{ .Tag | trimPrefix `v` }}_{{ .Goos }}-{{ .Goarch }}"
|
||||||
|
extra_files = [
|
||||||
|
{ source_path = "README.md", target_path = "README.md" },
|
||||||
|
{ source_path = "LICENSE", target_path = "LICENSE" },
|
||||||
|
]
|
||||||
|
[archive_settings.type]
|
||||||
|
format = "tar.gz"
|
||||||
|
extension = ".tar.gz"
|
||||||
|
[archive_settings.replacements]
|
||||||
|
amd64 = "64bit"
|
||||||
|
386 = "32bit"
|
||||||
|
arm = "ARM"
|
||||||
|
arm64 = "ARM64"
|
||||||
|
darwin = "macOS"
|
||||||
|
linux = "Linux"
|
||||||
|
windows = "Windows"
|
||||||
|
openbsd = "OpenBSD"
|
||||||
|
netbsd = "NetBSD"
|
||||||
|
freebsd = "FreeBSD"
|
||||||
|
dragonfly = "DragonFlyBSD"
|
||||||
|
|
||||||
|
[release_settings]
|
||||||
|
name = "${HUGO_RELEASE_NAME}"
|
||||||
|
type = "github"
|
||||||
|
repository = "hugo"
|
||||||
|
repository_owner = "gohugoio"
|
||||||
|
draft = true
|
||||||
|
prerelease = false
|
||||||
|
|
||||||
|
[release_settings.release_notes_settings]
|
||||||
|
# Use Hugoreleaser's autogenerated release notes.
|
||||||
|
generate = true
|
||||||
|
|
||||||
|
# Collapse relases with < 10 changes below one title.
|
||||||
|
short_threshold = 10
|
||||||
|
short_title = "What's Changed"
|
||||||
|
|
||||||
|
groups = [
|
||||||
|
# Group the changes in the release notes by title.
|
||||||
|
# You need at least one.
|
||||||
|
# The groups will be tested in order until a match is found.
|
||||||
|
# The titles will so be listed in the given order in the release note.
|
||||||
|
# Any match with ignore=true title will be dropped.
|
||||||
|
{ regexp = "Merge commit|Squashed", ignore = true },
|
||||||
|
{ title = "Bug fixes", regexp = "fix", ordinal = 10 },
|
||||||
|
{ title = "Dependency Updates", regexp = "deps", ordinal = 30 },
|
||||||
|
{ title = "Build Setup", regexp = "(snap|release|update to)", ordinal = 40 },
|
||||||
|
{ title = "Documentation", regexp = "(doc|readme)", ordinal = 40 },
|
||||||
|
{ title = "Improvements", regexp = ".*", ordinal = 20 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[builds]]
|
||||||
|
path = "container1/unix/regular"
|
||||||
|
|
||||||
|
[[builds.os]]
|
||||||
|
goos = "darwin"
|
||||||
|
[[builds.os.archs]]
|
||||||
|
goarch = "universal"
|
||||||
|
[[builds.os]]
|
||||||
|
goos = "linux"
|
||||||
|
[[builds.os.archs]]
|
||||||
|
goarch = "amd64"
|
||||||
|
[[builds.os.archs]]
|
||||||
|
goarch = "arm64"
|
||||||
|
[[builds.os.archs]]
|
||||||
|
goarch = "arm"
|
||||||
|
[builds.os.archs.build_settings]
|
||||||
|
env = ["CGO_ENABLED=0", "GOARM=7"]
|
||||||
|
|
||||||
|
# Unix BSD variants
|
||||||
|
[[builds.os]]
|
||||||
|
goos = "dragonfly"
|
||||||
|
[[builds.os.archs]]
|
||||||
|
goarch = "amd64"
|
||||||
|
[[builds.os]]
|
||||||
|
goos = "freebsd"
|
||||||
|
[[builds.os.archs]]
|
||||||
|
goarch = "amd64"
|
||||||
|
[[builds.os]]
|
||||||
|
goos = "netbsd"
|
||||||
|
[[builds.os.archs]]
|
||||||
|
goarch = "amd64"
|
||||||
|
[[builds.os]]
|
||||||
|
goos = "openbsd"
|
||||||
|
[[builds.os.archs]]
|
||||||
|
goarch = "amd64"
|
||||||
|
|
||||||
|
[[builds]]
|
||||||
|
path = "container1/unix/extended"
|
||||||
|
|
||||||
|
[builds.build_settings]
|
||||||
|
flags = ["-buildmode", "exe", "-tags", "extended"]
|
||||||
|
env = ["CGO_ENABLED=1"]
|
||||||
|
|
||||||
|
[[builds.os]]
|
||||||
|
goos = "darwin"
|
||||||
|
[builds.os.build_settings]
|
||||||
|
env = ["CGO_ENABLED=1", "CC=o64-clang", "CXX=o64-clang++"]
|
||||||
|
[[builds.os.archs]]
|
||||||
|
goarch = "universal"
|
||||||
|
[[builds.os]]
|
||||||
|
goos = "linux"
|
||||||
|
[[builds.os.archs]]
|
||||||
|
goarch = "amd64"
|
||||||
|
|
||||||
|
[[builds]]
|
||||||
|
path = "container2/linux/extended"
|
||||||
|
|
||||||
|
[builds.build_settings]
|
||||||
|
flags = ["-buildmode", "exe", "-tags", "extended"]
|
||||||
|
|
||||||
|
[[builds.os]]
|
||||||
|
goos = "linux"
|
||||||
|
[builds.os.build_settings]
|
||||||
|
env = [
|
||||||
|
"CGO_ENABLED=1",
|
||||||
|
"CC=aarch64-linux-gnu-gcc",
|
||||||
|
"CXX=aarch64-linux-gnu-g++",
|
||||||
|
]
|
||||||
|
[[builds.os.archs]]
|
||||||
|
goarch = "arm64"
|
||||||
|
|
||||||
|
[[builds]]
|
||||||
|
path = "container1/windows/regular"
|
||||||
|
|
||||||
|
[[builds.os]]
|
||||||
|
goos = "windows"
|
||||||
|
[builds.os.build_settings]
|
||||||
|
binary = "hugo.exe"
|
||||||
|
[[builds.os.archs]]
|
||||||
|
goarch = "amd64"
|
||||||
|
[[builds.os.archs]]
|
||||||
|
goarch = "arm64"
|
||||||
|
|
||||||
|
[[builds]]
|
||||||
|
path = "container1/windows/extended"
|
||||||
|
|
||||||
|
[builds.build_settings]
|
||||||
|
flags = ["-buildmode", "exe", "-tags", "extended"]
|
||||||
|
env = [
|
||||||
|
"CGO_ENABLED=1",
|
||||||
|
"CC=x86_64-w64-mingw32-gcc",
|
||||||
|
"CXX=x86_64-w64-mingw32-g++",
|
||||||
|
]
|
||||||
|
ldflags = "-s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio -extldflags '-static'"
|
||||||
|
|
||||||
|
[[builds.os]]
|
||||||
|
goos = "windows"
|
||||||
|
[builds.os.build_settings]
|
||||||
|
binary = "hugo.exe"
|
||||||
|
[[builds.os.archs]]
|
||||||
|
goarch = "amd64"
|
||||||
|
|
||||||
|
[[archives]]
|
||||||
|
paths = ["builds/container1/unix/regular/**"]
|
||||||
|
[[archives]]
|
||||||
|
paths = ["builds/container1/unix/extended/**"]
|
||||||
|
[archives.archive_settings]
|
||||||
|
name_template = "{{ .Project }}_extended_{{ .Tag | trimPrefix `v` }}_{{ .Goos }}-{{ .Goarch }}"
|
||||||
|
[[archives]]
|
||||||
|
# Only extended builds in container2.
|
||||||
|
paths = ["builds/container2/**"]
|
||||||
|
[archives.archive_settings]
|
||||||
|
name_template = "{{ .Project }}_extended_{{ .Tag | trimPrefix `v` }}_{{ .Goos }}-{{ .Goarch }}"
|
||||||
|
[[archives]]
|
||||||
|
paths = ["builds/**/windows/regular/**"]
|
||||||
|
[archives.archive_settings.type]
|
||||||
|
format = "zip"
|
||||||
|
extension = ".zip"
|
||||||
|
[[archives]]
|
||||||
|
paths = ["builds/**/windows/extended/**"]
|
||||||
|
[archives.archive_settings]
|
||||||
|
name_template = "{{ .Project }}_extended_{{ .Tag | trimPrefix `v` }}_{{ .Goos }}-{{ .Goarch }}"
|
||||||
|
[archives.archive_settings.type]
|
||||||
|
format = "zip"
|
||||||
|
extension = ".zip"
|
||||||
|
[[archives]]
|
||||||
|
paths = ["builds/**/regular/linux/{arm64,amd64}"]
|
||||||
|
[archives.archive_settings]
|
||||||
|
[archives.archive_settings.type]
|
||||||
|
format = "_plugin"
|
||||||
|
extension = ".deb"
|
||||||
|
[archives.archive_settings.plugin]
|
||||||
|
id = "deb"
|
||||||
|
type = "gorun"
|
||||||
|
command = "github.com/gohugoio/hugoreleaser-archive-plugins/deb@v0.5.0"
|
||||||
|
[archives.archive_settings.custom_settings]
|
||||||
|
vendor = "gohugo.io"
|
||||||
|
homepage = "https://github.com/gohugoio/hugoreleaser"
|
||||||
|
maintainer = "Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>"
|
||||||
|
description = "Build, archive and release Go programs."
|
||||||
|
license = "Apache-2.0"
|
||||||
|
[[archives]]
|
||||||
|
paths = ["builds/**/extended/linux/{arm64,amd64}"]
|
||||||
|
[archives.archive_settings]
|
||||||
|
name_template = "{{ .Project }}_extended_{{ .Tag | trimPrefix `v` }}_{{ .Goos }}-{{ .Goarch }}"
|
||||||
|
[archives.archive_settings.type]
|
||||||
|
format = "_plugin"
|
||||||
|
extension = ".deb"
|
||||||
|
[archives.archive_settings.plugin]
|
||||||
|
id = "deb"
|
||||||
|
type = "gorun"
|
||||||
|
command = "github.com/gohugoio/hugoreleaser-archive-plugins/deb@latest"
|
||||||
|
[archives.archive_settings.custom_settings]
|
||||||
|
vendor = "gohugo.io"
|
||||||
|
homepage = "https://github.com/gohugoio/hugoreleaser"
|
||||||
|
maintainer = "Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>"
|
||||||
|
description = "Build, archive and release Go programs."
|
||||||
|
license = "Apache-2.0"
|
||||||
|
|
||||||
|
[[releases]]
|
||||||
|
paths = ["archives/**"]
|
||||||
|
path = "r1"
|
||||||
|
|
||||||
|
# The above should allow the following build commands:
|
||||||
|
# hugoreleaser build -paths "builds/container1/**"
|
||||||
|
# hugoreleaser build -paths "builds/container2/**"
|
||||||
|
# hugoreleaser archive
|
||||||
|
# hugoreleaser release
|
253
releaser/git.go
253
releaser/git.go
|
@ -1,253 +0,0 @@
|
||||||
// Copyright 2017-present The Hugo Authors. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package releaser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"regexp"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/hexec"
|
|
||||||
)
|
|
||||||
|
|
||||||
var issueRe = regexp.MustCompile(`(?i)(?:Updates?|Closes?|Fix.*|See) #(\d+)`)
|
|
||||||
|
|
||||||
type changeLog struct {
|
|
||||||
Version string
|
|
||||||
Notes gitInfos
|
|
||||||
All gitInfos
|
|
||||||
Docs gitInfos
|
|
||||||
|
|
||||||
// Overall stats
|
|
||||||
Repo *gitHubRepo
|
|
||||||
ContributorCount int
|
|
||||||
ThemeCount int
|
|
||||||
}
|
|
||||||
|
|
||||||
func newChangeLog(infos, docInfos gitInfos) *changeLog {
|
|
||||||
log := &changeLog{
|
|
||||||
Docs: docInfos,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, info := range infos {
|
|
||||||
// TODO(bep) improve
|
|
||||||
if regexp.MustCompile("(?i)deprecate|note").MatchString(info.Subject) {
|
|
||||||
log.Notes = append(log.Notes, info)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.All = append(log.All, info)
|
|
||||||
info.Subject = strings.TrimSpace(info.Subject)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return log
|
|
||||||
}
|
|
||||||
|
|
||||||
type gitInfo struct {
|
|
||||||
Hash string
|
|
||||||
Author string
|
|
||||||
Subject string
|
|
||||||
Body string
|
|
||||||
|
|
||||||
GitHubCommit *gitHubCommit
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g gitInfo) Issues() []int {
|
|
||||||
return extractIssues(g.Body)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g gitInfo) AuthorID() string {
|
|
||||||
if g.GitHubCommit != nil {
|
|
||||||
return g.GitHubCommit.Author.Login
|
|
||||||
}
|
|
||||||
return g.Author
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractIssues(body string) []int {
|
|
||||||
var i []int
|
|
||||||
m := issueRe.FindAllStringSubmatch(body, -1)
|
|
||||||
for _, mm := range m {
|
|
||||||
issueID, err := strconv.Atoi(mm[1])
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
i = append(i, issueID)
|
|
||||||
}
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
|
|
||||||
type gitInfos []gitInfo
|
|
||||||
|
|
||||||
func git(args ...string) (string, error) {
|
|
||||||
cmd, _ := hexec.SafeCommand("git", args...)
|
|
||||||
out, err := cmd.CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("git failed: %q: %q (%q)", err, out, args)
|
|
||||||
}
|
|
||||||
return string(out), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getGitInfos(tag, repo, repoPath string, remote bool) (gitInfos, error) {
|
|
||||||
return getGitInfosBefore("HEAD", tag, repo, repoPath, remote)
|
|
||||||
}
|
|
||||||
|
|
||||||
type countribCount struct {
|
|
||||||
Author string
|
|
||||||
GitHubAuthor gitHubAuthor
|
|
||||||
Count int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c countribCount) AuthorLink() string {
|
|
||||||
if c.GitHubAuthor.HTMLURL != "" {
|
|
||||||
return fmt.Sprintf("[@%s](%s)", c.GitHubAuthor.Login, c.GitHubAuthor.HTMLURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strings.Contains(c.Author, "@") {
|
|
||||||
return c.Author
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.Author[:strings.Index(c.Author, "@")]
|
|
||||||
}
|
|
||||||
|
|
||||||
type contribCounts []countribCount
|
|
||||||
|
|
||||||
func (c contribCounts) Less(i, j int) bool { return c[i].Count > c[j].Count }
|
|
||||||
func (c contribCounts) Len() int { return len(c) }
|
|
||||||
func (c contribCounts) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
|
|
||||||
|
|
||||||
func (g gitInfos) ContribCountPerAuthor() contribCounts {
|
|
||||||
var c contribCounts
|
|
||||||
|
|
||||||
counters := make(map[string]countribCount)
|
|
||||||
|
|
||||||
for _, gi := range g {
|
|
||||||
authorID := gi.AuthorID()
|
|
||||||
if count, ok := counters[authorID]; ok {
|
|
||||||
count.Count = count.Count + 1
|
|
||||||
counters[authorID] = count
|
|
||||||
} else {
|
|
||||||
var ghA gitHubAuthor
|
|
||||||
if gi.GitHubCommit != nil {
|
|
||||||
ghA = gi.GitHubCommit.Author
|
|
||||||
}
|
|
||||||
authorCount := countribCount{Count: 1, Author: gi.Author, GitHubAuthor: ghA}
|
|
||||||
counters[authorID] = authorCount
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range counters {
|
|
||||||
c = append(c, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Sort(c)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func getGitInfosBefore(ref, tag, repo, repoPath string, remote bool) (gitInfos, error) {
|
|
||||||
client := newGitHubAPI(repo)
|
|
||||||
var g gitInfos
|
|
||||||
|
|
||||||
log, err := gitLogBefore(ref, tag, repoPath)
|
|
||||||
if err != nil {
|
|
||||||
return g, err
|
|
||||||
}
|
|
||||||
|
|
||||||
log = strings.Trim(log, "\n\x1e'")
|
|
||||||
entries := strings.Split(log, "\x1e")
|
|
||||||
|
|
||||||
for _, entry := range entries {
|
|
||||||
items := strings.Split(entry, "\x1f")
|
|
||||||
gi := gitInfo{}
|
|
||||||
|
|
||||||
if len(items) > 0 {
|
|
||||||
gi.Hash = items[0]
|
|
||||||
}
|
|
||||||
if len(items) > 1 {
|
|
||||||
gi.Author = items[1]
|
|
||||||
}
|
|
||||||
if len(items) > 2 {
|
|
||||||
gi.Subject = items[2]
|
|
||||||
}
|
|
||||||
if len(items) > 3 {
|
|
||||||
gi.Body = items[3]
|
|
||||||
}
|
|
||||||
|
|
||||||
if remote && gi.Hash != "" {
|
|
||||||
gc, err := client.fetchCommit(gi.Hash)
|
|
||||||
if err == nil {
|
|
||||||
gi.GitHubCommit = &gc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g = append(g, gi)
|
|
||||||
}
|
|
||||||
|
|
||||||
return g, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore autogenerated commits etc. in change log. This is a regexp.
|
|
||||||
const ignoredCommits = "snapcraft:|Merge commit|Squashed"
|
|
||||||
|
|
||||||
func gitLogBefore(ref, tag, repoPath string) (string, error) {
|
|
||||||
var prevTag string
|
|
||||||
var err error
|
|
||||||
if tag != "" {
|
|
||||||
prevTag = tag
|
|
||||||
} else {
|
|
||||||
prevTag, err = gitVersionTagBefore(ref)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultArgs := []string{"log", "-E", fmt.Sprintf("--grep=%s", ignoredCommits), "--invert-grep", "--pretty=format:%x1e%h%x1f%aE%x1f%s%x1f%b", "--abbrev-commit", prevTag + ".." + ref}
|
|
||||||
|
|
||||||
var args []string
|
|
||||||
|
|
||||||
if repoPath != "" {
|
|
||||||
args = append([]string{"-C", repoPath}, defaultArgs...)
|
|
||||||
} else {
|
|
||||||
args = defaultArgs
|
|
||||||
}
|
|
||||||
|
|
||||||
log, err := git(args...)
|
|
||||||
if err != nil {
|
|
||||||
return ",", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return log, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func gitVersionTagBefore(ref string) (string, error) {
|
|
||||||
return gitShort("describe", "--tags", "--abbrev=0", "--always", "--match", "v[0-9]*", ref+"^")
|
|
||||||
}
|
|
||||||
|
|
||||||
func gitShort(args ...string) (output string, err error) {
|
|
||||||
output, err = git(args...)
|
|
||||||
return strings.Replace(strings.Split(output, "\n")[0], "'", "", -1), err
|
|
||||||
}
|
|
||||||
|
|
||||||
func tagExists(tag string) (bool, error) {
|
|
||||||
out, err := git("tag", "-l", tag)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(out, tag) {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, nil
|
|
||||||
}
|
|
|
@ -1,86 +0,0 @@
|
||||||
// Copyright 2017-present The Hugo Authors. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package releaser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
qt "github.com/frankban/quicktest"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGitInfos(t *testing.T) {
|
|
||||||
c := qt.New(t)
|
|
||||||
skipIfCI(t)
|
|
||||||
infos, err := getGitInfos("v0.20", "hugo", "", false)
|
|
||||||
|
|
||||||
c.Assert(err, qt.IsNil)
|
|
||||||
c.Assert(len(infos) > 0, qt.Equals, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIssuesRe(t *testing.T) {
|
|
||||||
c := qt.New(t)
|
|
||||||
|
|
||||||
body := `
|
|
||||||
This is a commit message.
|
|
||||||
|
|
||||||
Updates #123
|
|
||||||
Fix #345
|
|
||||||
closes #543
|
|
||||||
See #456
|
|
||||||
`
|
|
||||||
|
|
||||||
issues := extractIssues(body)
|
|
||||||
|
|
||||||
c.Assert(len(issues), qt.Equals, 4)
|
|
||||||
c.Assert(issues[0], qt.Equals, 123)
|
|
||||||
c.Assert(issues[2], qt.Equals, 543)
|
|
||||||
|
|
||||||
bodyNoIssues := `
|
|
||||||
This is a commit message without issue refs.
|
|
||||||
|
|
||||||
But it has e #10 to make old regexp confused.
|
|
||||||
Streets #20.
|
|
||||||
`
|
|
||||||
|
|
||||||
emptyIssuesList := extractIssues(bodyNoIssues)
|
|
||||||
c.Assert(len(emptyIssuesList), qt.Equals, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGitVersionTagBefore(t *testing.T) {
|
|
||||||
skipIfCI(t)
|
|
||||||
c := qt.New(t)
|
|
||||||
v1, err := gitVersionTagBefore("v0.18")
|
|
||||||
c.Assert(err, qt.IsNil)
|
|
||||||
c.Assert(v1, qt.Equals, "v0.17")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTagExists(t *testing.T) {
|
|
||||||
skipIfCI(t)
|
|
||||||
c := qt.New(t)
|
|
||||||
b1, err := tagExists("v0.18")
|
|
||||||
c.Assert(err, qt.IsNil)
|
|
||||||
c.Assert(b1, qt.Equals, true)
|
|
||||||
|
|
||||||
b2, err := tagExists("adfagdsfg")
|
|
||||||
c.Assert(err, qt.IsNil)
|
|
||||||
c.Assert(b2, qt.Equals, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func skipIfCI(t *testing.T) {
|
|
||||||
if isCI() {
|
|
||||||
// Travis has an ancient git with no --invert-grep: https://github.com/travis-ci/travis-ci/issues/6328
|
|
||||||
// Also Travis clones very shallowly, making some of the tests above shaky.
|
|
||||||
t.Skip("Skip git test on Linux to make Travis happy.")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,143 +0,0 @@
|
||||||
package releaser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
gitHubCommitsAPI = "https://api.github.com/repos/gohugoio/REPO/commits/%s"
|
|
||||||
gitHubRepoAPI = "https://api.github.com/repos/gohugoio/REPO"
|
|
||||||
gitHubContributorsAPI = "https://api.github.com/repos/gohugoio/REPO/contributors"
|
|
||||||
)
|
|
||||||
|
|
||||||
type gitHubAPI struct {
|
|
||||||
commitsAPITemplate string
|
|
||||||
repoAPI string
|
|
||||||
contributorsAPITemplate string
|
|
||||||
}
|
|
||||||
|
|
||||||
func newGitHubAPI(repo string) *gitHubAPI {
|
|
||||||
return &gitHubAPI{
|
|
||||||
commitsAPITemplate: strings.Replace(gitHubCommitsAPI, "REPO", repo, -1),
|
|
||||||
repoAPI: strings.Replace(gitHubRepoAPI, "REPO", repo, -1),
|
|
||||||
contributorsAPITemplate: strings.Replace(gitHubContributorsAPI, "REPO", repo, -1),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type gitHubCommit struct {
|
|
||||||
Author gitHubAuthor `json:"author"`
|
|
||||||
HTMLURL string `json:"html_url"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type gitHubAuthor struct {
|
|
||||||
ID int `json:"id"`
|
|
||||||
Login string `json:"login"`
|
|
||||||
HTMLURL string `json:"html_url"`
|
|
||||||
AvatarURL string `json:"avatar_url"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type gitHubRepo struct {
|
|
||||||
ID int `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
HTMLURL string `json:"html_url"`
|
|
||||||
Stars int `json:"stargazers_count"`
|
|
||||||
Contributors []gitHubContributor
|
|
||||||
}
|
|
||||||
|
|
||||||
type gitHubContributor struct {
|
|
||||||
ID int `json:"id"`
|
|
||||||
Login string `json:"login"`
|
|
||||||
HTMLURL string `json:"html_url"`
|
|
||||||
Contributions int `json:"contributions"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *gitHubAPI) fetchCommit(ref string) (gitHubCommit, error) {
|
|
||||||
var commit gitHubCommit
|
|
||||||
|
|
||||||
u := fmt.Sprintf(g.commitsAPITemplate, ref)
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", u, nil)
|
|
||||||
if err != nil {
|
|
||||||
return commit, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = doGitHubRequest(req, &commit)
|
|
||||||
|
|
||||||
return commit, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *gitHubAPI) fetchRepo() (gitHubRepo, error) {
|
|
||||||
var repo gitHubRepo
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", g.repoAPI, nil)
|
|
||||||
if err != nil {
|
|
||||||
return repo, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = doGitHubRequest(req, &repo)
|
|
||||||
if err != nil {
|
|
||||||
return repo, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var contributors []gitHubContributor
|
|
||||||
page := 0
|
|
||||||
for {
|
|
||||||
page++
|
|
||||||
var currPage []gitHubContributor
|
|
||||||
url := fmt.Sprintf(g.contributorsAPITemplate+"?page=%d", page)
|
|
||||||
|
|
||||||
req, err = http.NewRequest("GET", url, nil)
|
|
||||||
if err != nil {
|
|
||||||
return repo, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = doGitHubRequest(req, &currPage)
|
|
||||||
if err != nil {
|
|
||||||
return repo, err
|
|
||||||
}
|
|
||||||
if len(currPage) == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
contributors = append(contributors, currPage...)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
repo.Contributors = contributors
|
|
||||||
|
|
||||||
return repo, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func doGitHubRequest(req *http.Request, v any) error {
|
|
||||||
addGitHubToken(req)
|
|
||||||
|
|
||||||
resp, err := http.DefaultClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if isError(resp) {
|
|
||||||
b, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
return fmt.Errorf("GitHub lookup failed: %s", string(b))
|
|
||||||
}
|
|
||||||
|
|
||||||
return json.NewDecoder(resp.Body).Decode(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func isError(resp *http.Response) bool {
|
|
||||||
return resp.StatusCode < 200 || resp.StatusCode > 299
|
|
||||||
}
|
|
||||||
|
|
||||||
func addGitHubToken(req *http.Request) {
|
|
||||||
gitHubToken := os.Getenv("GITHUB_TOKEN")
|
|
||||||
if gitHubToken != "" {
|
|
||||||
req.Header.Add("Authorization", "token "+gitHubToken)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
// Copyright 2017-present The Hugo Authors. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package releaser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
qt "github.com/frankban/quicktest"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGitHubLookupCommit(t *testing.T) {
|
|
||||||
skipIfNoToken(t)
|
|
||||||
c := qt.New(t)
|
|
||||||
client := newGitHubAPI("hugo")
|
|
||||||
commit, err := client.fetchCommit("793554108763c0984f1a1b1a6ee5744b560d78d0")
|
|
||||||
c.Assert(err, qt.IsNil)
|
|
||||||
fmt.Println(commit)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFetchRepo(t *testing.T) {
|
|
||||||
skipIfNoToken(t)
|
|
||||||
c := qt.New(t)
|
|
||||||
client := newGitHubAPI("hugo")
|
|
||||||
repo, err := client.fetchRepo()
|
|
||||||
c.Assert(err, qt.IsNil)
|
|
||||||
fmt.Println(">>", len(repo.Contributors))
|
|
||||||
}
|
|
||||||
|
|
||||||
func skipIfNoToken(t *testing.T) {
|
|
||||||
if os.Getenv("GITHUB_TOKEN") == "" {
|
|
||||||
t.Skip("Skip test against GitHub as no GITHUB_TOKEN set.")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,191 +0,0 @@
|
||||||
// Copyright 2017-present The Hugo Authors. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// Package releaser implements a set of utilities and a wrapper around Goreleaser
|
|
||||||
// to help automate the Hugo release process.
|
|
||||||
package releaser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
issueLinkTemplate = "#%d"
|
|
||||||
linkTemplate = "[%s](%s)"
|
|
||||||
releaseNotesMarkdownTemplatePatchRelease = `
|
|
||||||
{{ if eq (len .All) 1 }}
|
|
||||||
This is a bug-fix release with one important fix.
|
|
||||||
{{ else }}
|
|
||||||
This is a bug-fix release with a couple of important fixes.
|
|
||||||
{{ end }}
|
|
||||||
{{ range .All }}
|
|
||||||
{{- if .GitHubCommit -}}
|
|
||||||
* {{ .Subject }} {{ .Hash }} {{ . | author }} {{ range .Issues }}{{ . | issue }} {{ end }}
|
|
||||||
{{ else -}}
|
|
||||||
* {{ .Subject }} {{ range .Issues }}{{ . | issue }} {{ end }}
|
|
||||||
{{ end -}}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
|
|
||||||
`
|
|
||||||
releaseNotesMarkdownTemplate = `
|
|
||||||
{{- $contribsPerAuthor := .All.ContribCountPerAuthor -}}
|
|
||||||
{{- $docsContribsPerAuthor := .Docs.ContribCountPerAuthor -}}
|
|
||||||
|
|
||||||
This release represents **{{ len .All }} contributions by {{ len $contribsPerAuthor }} contributors** to the main Hugo code base.
|
|
||||||
|
|
||||||
{{- if gt (len $contribsPerAuthor) 3 -}}
|
|
||||||
{{- $u1 := index $contribsPerAuthor 0 -}}
|
|
||||||
{{- $u2 := index $contribsPerAuthor 1 -}}
|
|
||||||
{{- $u3 := index $contribsPerAuthor 2 -}}
|
|
||||||
{{- $u4 := index $contribsPerAuthor 3 -}}
|
|
||||||
{{- $u1.AuthorLink }} leads the Hugo development with a significant amount of contributions, but also a big shoutout to {{ $u2.AuthorLink }}, {{ $u3.AuthorLink }}, and {{ $u4.AuthorLink }} for their ongoing contributions.
|
|
||||||
And thanks to [@digitalcraftsman](https://github.com/digitalcraftsman) for his ongoing work on keeping the themes site in pristine condition.
|
|
||||||
{{ end }}
|
|
||||||
Many have also been busy writing and fixing the documentation in [hugoDocs](https://github.com/gohugoio/hugoDocs),
|
|
||||||
which has received **{{ len .Docs }} contributions by {{ len $docsContribsPerAuthor }} contributors**.
|
|
||||||
{{- if gt (len $docsContribsPerAuthor) 3 -}}
|
|
||||||
{{- $u1 := index $docsContribsPerAuthor 0 -}}
|
|
||||||
{{- $u2 := index $docsContribsPerAuthor 1 -}}
|
|
||||||
{{- $u3 := index $docsContribsPerAuthor 2 -}}
|
|
||||||
{{- $u4 := index $docsContribsPerAuthor 3 }} A special thanks to {{ $u1.AuthorLink }}, {{ $u2.AuthorLink }}, {{ $u3.AuthorLink }}, and {{ $u4.AuthorLink }} for their work on the documentation site.
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
Hugo now has:
|
|
||||||
|
|
||||||
{{ with .Repo -}}
|
|
||||||
* {{ .Stars }}+ [stars](https://github.com/gohugoio/hugo/stargazers)
|
|
||||||
* {{ len .Contributors }}+ [contributors](https://github.com/gohugoio/hugo/graphs/contributors)
|
|
||||||
{{- end -}}
|
|
||||||
{{ with .ThemeCount }}
|
|
||||||
* {{ . }}+ [themes](http://themes.gohugo.io/)
|
|
||||||
{{ end }}
|
|
||||||
{{ with .Notes }}
|
|
||||||
## Notes
|
|
||||||
{{ template "change-section" . }}
|
|
||||||
{{- end -}}
|
|
||||||
{{ with .All }}
|
|
||||||
## Changes
|
|
||||||
{{ template "change-section" . }}
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
{{ define "change-section" }}
|
|
||||||
{{ range . }}
|
|
||||||
{{- if .GitHubCommit -}}
|
|
||||||
* {{ .Subject }} {{ .Hash }} {{ . | author }} {{ range .Issues }}{{ . | issue }} {{ end }}
|
|
||||||
{{ else -}}
|
|
||||||
* {{ .Subject }} {{ range .Issues }}{{ . | issue }} {{ end }}
|
|
||||||
{{ end -}}
|
|
||||||
{{- end }}
|
|
||||||
{{ end }}
|
|
||||||
`
|
|
||||||
)
|
|
||||||
|
|
||||||
var templateFuncs = template.FuncMap{
|
|
||||||
"isPatch": func(c changeLog) bool {
|
|
||||||
return !strings.HasSuffix(c.Version, "0")
|
|
||||||
},
|
|
||||||
"issue": func(id int) string {
|
|
||||||
return fmt.Sprintf(issueLinkTemplate, id)
|
|
||||||
},
|
|
||||||
"commitURL": func(info gitInfo) string {
|
|
||||||
if info.GitHubCommit.HTMLURL == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return fmt.Sprintf(linkTemplate, info.Hash, info.GitHubCommit.HTMLURL)
|
|
||||||
},
|
|
||||||
"author": func(info gitInfo) string {
|
|
||||||
return "@" + info.GitHubCommit.Author.Login
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeReleaseNotes(version string, infosMain, infosDocs gitInfos, to io.Writer) error {
|
|
||||||
client := newGitHubAPI("hugo")
|
|
||||||
changes := newChangeLog(infosMain, infosDocs)
|
|
||||||
changes.Version = version
|
|
||||||
repo, err := client.fetchRepo()
|
|
||||||
if err == nil {
|
|
||||||
changes.Repo = &repo
|
|
||||||
}
|
|
||||||
themeCount, err := fetchThemeCount()
|
|
||||||
if err == nil {
|
|
||||||
changes.ThemeCount = themeCount
|
|
||||||
}
|
|
||||||
|
|
||||||
mtempl := releaseNotesMarkdownTemplate
|
|
||||||
|
|
||||||
if !strings.HasSuffix(version, "0") {
|
|
||||||
mtempl = releaseNotesMarkdownTemplatePatchRelease
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpl, err := template.New("").Funcs(templateFuncs).Parse(mtempl)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = tmpl.Execute(to, changes)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func fetchThemeCount() (int, error) {
|
|
||||||
resp, err := http.Get("https://raw.githubusercontent.com/gohugoio/hugoThemesSiteBuilder/main/themes.txt")
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
b, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
return bytes.Count(b, []byte("\n")) - bytes.Count(b, []byte("#")), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getReleaseNotesFilename(version string) string {
|
|
||||||
return filepath.FromSlash(fmt.Sprintf("temp/%s-relnotes-ready.md", version))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *ReleaseHandler) writeReleaseNotesToTemp(version string, isPatch bool, infosMain, infosDocs gitInfos) (string, error) {
|
|
||||||
filename := getReleaseNotesFilename(version)
|
|
||||||
|
|
||||||
var w io.WriteCloser
|
|
||||||
|
|
||||||
if !r.try {
|
|
||||||
f, err := os.Create(filename)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
w = f
|
|
||||||
|
|
||||||
} else {
|
|
||||||
w = os.Stdout
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := writeReleaseNotes(version, infosMain, infosDocs, w); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return filename, nil
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
// Copyright 2017-present The Hugo Authors. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// Package commands defines and implements command-line commands and flags
|
|
||||||
// used by Hugo. Commands and flags are implemented using Cobra.
|
|
||||||
|
|
||||||
package releaser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
qt "github.com/frankban/quicktest"
|
|
||||||
)
|
|
||||||
|
|
||||||
func _TestReleaseNotesWriter(t *testing.T) {
|
|
||||||
skipIfNoToken(t)
|
|
||||||
if os.Getenv("CI") != "" {
|
|
||||||
// Travis has an ancient git with no --invert-grep: https://github.com/travis-ci/travis-ci/issues/6328
|
|
||||||
t.Skip("Skip git test on CI to make Travis happy..")
|
|
||||||
}
|
|
||||||
|
|
||||||
c := qt.New(t)
|
|
||||||
|
|
||||||
var b bytes.Buffer
|
|
||||||
|
|
||||||
// TODO(bep) consider to query GitHub directly for the gitlog with author info, probably faster.
|
|
||||||
infos, err := getGitInfosBefore("HEAD", "v0.89.0", "hugo", "", false)
|
|
||||||
c.Assert(err, qt.IsNil)
|
|
||||||
|
|
||||||
c.Assert(writeReleaseNotes("0.89.0", infos, infos, &b), qt.IsNil)
|
|
||||||
|
|
||||||
fmt.Println(b.String())
|
|
||||||
}
|
|
|
@ -17,7 +17,6 @@ package releaser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -25,22 +24,56 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/hexec"
|
"github.com/gohugoio/hugo/common/hexec"
|
||||||
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/hugo"
|
"github.com/gohugoio/hugo/common/hugo"
|
||||||
)
|
)
|
||||||
|
|
||||||
const commitPrefix = "releaser:"
|
const commitPrefix = "releaser:"
|
||||||
|
|
||||||
|
// New initialises a ReleaseHandler.
|
||||||
|
func New(skipPush, try bool, step int) (*ReleaseHandler, error) {
|
||||||
|
if step < 1 || step > 2 {
|
||||||
|
return nil, fmt.Errorf("step must be 1 or 2")
|
||||||
|
}
|
||||||
|
|
||||||
|
prefix := "release-"
|
||||||
|
branch, err := git("rev-parse", "--abbrev-ref", "HEAD")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !strings.HasPrefix(branch, prefix) {
|
||||||
|
return nil, fmt.Errorf("branch %q is not a release branch", branch)
|
||||||
|
}
|
||||||
|
|
||||||
|
logf("Branch: %s\n", branch)
|
||||||
|
|
||||||
|
version := strings.TrimPrefix(branch, prefix)
|
||||||
|
version = strings.TrimPrefix(version, "v")
|
||||||
|
rh := &ReleaseHandler{branchVersion: version, skipPush: skipPush, try: try, step: step}
|
||||||
|
|
||||||
|
if try {
|
||||||
|
rh.git = func(args ...string) (string, error) {
|
||||||
|
logln("git", strings.Join(args, " "))
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rh.git = git
|
||||||
|
}
|
||||||
|
|
||||||
|
return rh, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ReleaseHandler provides functionality to release a new version of Hugo.
|
// ReleaseHandler provides functionality to release a new version of Hugo.
|
||||||
// Test this locally without doing an actual release:
|
// Test this locally without doing an actual release:
|
||||||
// go run -tags release main.go release --skip-publish --try -r 0.90.0
|
// go run -tags release main.go release --skip-publish --try -r 0.90.0
|
||||||
// Or a variation of the above -- the skip-publish flag makes sure that any changes are performed to the local Git only.
|
// Or a variation of the above -- the skip-publish flag makes sure that any changes are performed to the local Git only.
|
||||||
type ReleaseHandler struct {
|
type ReleaseHandler struct {
|
||||||
cliVersion string
|
branchVersion string
|
||||||
|
|
||||||
skipPublish bool
|
// 1 or 2.
|
||||||
|
step int
|
||||||
|
|
||||||
|
// No remote pushes.
|
||||||
|
skipPush bool
|
||||||
|
|
||||||
// Just simulate, no actual changes.
|
// Just simulate, no actual changes.
|
||||||
try bool
|
try bool
|
||||||
|
@ -48,144 +81,48 @@ type ReleaseHandler struct {
|
||||||
git func(args ...string) (string, error)
|
git func(args ...string) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r ReleaseHandler) calculateVersions() (hugo.Version, hugo.Version) {
|
|
||||||
newVersion := hugo.MustParseVersion(r.cliVersion)
|
|
||||||
finalVersion := newVersion.Next()
|
|
||||||
finalVersion.PatchLevel = 0
|
|
||||||
|
|
||||||
if newVersion.Suffix != "-test" {
|
|
||||||
newVersion.Suffix = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
finalVersion.Suffix = "-DEV"
|
|
||||||
|
|
||||||
return newVersion, finalVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
// New initialises a ReleaseHandler.
|
|
||||||
func New(version string, skipPublish, try bool) *ReleaseHandler {
|
|
||||||
// When triggered from CI release branch
|
|
||||||
version = strings.TrimPrefix(version, "release-")
|
|
||||||
version = strings.TrimPrefix(version, "v")
|
|
||||||
rh := &ReleaseHandler{cliVersion: version, skipPublish: skipPublish, try: try}
|
|
||||||
|
|
||||||
if try {
|
|
||||||
rh.git = func(args ...string) (string, error) {
|
|
||||||
fmt.Println("git", strings.Join(args, " "))
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rh.git = git
|
|
||||||
}
|
|
||||||
|
|
||||||
return rh
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run creates a new release.
|
// Run creates a new release.
|
||||||
func (r *ReleaseHandler) Run() error {
|
func (r *ReleaseHandler) Run() error {
|
||||||
if os.Getenv("GITHUB_TOKEN") == "" {
|
|
||||||
return errors.New("GITHUB_TOKEN not set, create one here with the repo scope selected: https://github.com/settings/tokens/new")
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Start release from %q\n", wd())
|
|
||||||
|
|
||||||
newVersion, finalVersion := r.calculateVersions()
|
newVersion, finalVersion := r.calculateVersions()
|
||||||
|
|
||||||
version := newVersion.String()
|
version := newVersion.String()
|
||||||
tag := "v" + version
|
tag := "v" + version
|
||||||
isPatch := newVersion.PatchLevel > 0
|
|
||||||
mainVersion := newVersion
|
mainVersion := newVersion
|
||||||
mainVersion.PatchLevel = 0
|
mainVersion.PatchLevel = 0
|
||||||
|
|
||||||
// Exit early if tag already exists
|
defer r.gitPush()
|
||||||
exists, err := tagExists(tag)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if exists {
|
if r.step == 1 {
|
||||||
return fmt.Errorf("tag %q already exists", tag)
|
if err := r.bumpVersions(newVersion); err != nil {
|
||||||
}
|
|
||||||
|
|
||||||
var changeLogFromTag string
|
|
||||||
|
|
||||||
if newVersion.PatchLevel == 0 {
|
|
||||||
// There may have been patch releases between, so set the tag explicitly.
|
|
||||||
changeLogFromTag = "v" + newVersion.Prev().String()
|
|
||||||
exists, _ := tagExists(changeLogFromTag)
|
|
||||||
if !exists {
|
|
||||||
// fall back to one that exists.
|
|
||||||
changeLogFromTag = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
gitCommits gitInfos
|
|
||||||
gitCommitsDocs gitInfos
|
|
||||||
)
|
|
||||||
|
|
||||||
defer r.gitPush() // TODO(bep)
|
|
||||||
|
|
||||||
gitCommits, err = getGitInfos(changeLogFromTag, "hugo", "", !r.try)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(bep) explicit tag?
|
|
||||||
gitCommitsDocs, err = getGitInfos("", "hugoDocs", "../hugoDocs", !r.try)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
releaseNotesFile, err := r.writeReleaseNotesToTemp(version, isPatch, gitCommits, gitCommitsDocs)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := r.git("add", releaseNotesFile); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
commitMsg := fmt.Sprintf("%s Add release notes for %s", commitPrefix, newVersion)
|
|
||||||
commitMsg += "\n[ci skip]"
|
|
||||||
|
|
||||||
if _, err := r.git("commit", "-m", commitMsg); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := r.bumpVersions(newVersion); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := r.git("commit", "-a", "-m", fmt.Sprintf("%s Bump versions for release of %s\n\n[ci skip]", commitPrefix, newVersion)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := r.git("tag", "-a", tag, "-m", fmt.Sprintf("%s %s\n\n[ci skip]", commitPrefix, newVersion)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !r.skipPublish {
|
|
||||||
if _, err := r.git("push", "origin", tag); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if err := r.release(releaseNotesFile); err != nil {
|
if _, err := r.git("commit", "-a", "-m", fmt.Sprintf("%s Bump versions for release of %s\n\n[ci skip]", commitPrefix, newVersion)); err != nil {
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// The above commit will be the target for this release, so print it to the console in a env friendly way.
|
||||||
|
sha, err := git("rev-parse", "HEAD")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hugoreleaser will do the actual release using these values.
|
||||||
|
if err := r.replaceInFile("hugoreleaser.env",
|
||||||
|
`HUGORELEASER_TAG=(\S*)`, "HUGORELEASER_TAG="+tag,
|
||||||
|
`HUGORELEASER_COMMITISH=(\S*)`, "HUGORELEASER_COMMITISH="+sha,
|
||||||
|
); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logf("HUGORELEASER_TAG=%s\n", tag)
|
||||||
|
logf("HUGORELEASER_COMMITISH=%s\n", sha)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.bumpVersions(finalVersion); err != nil {
|
if err := r.bumpVersions(finalVersion); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !r.try {
|
|
||||||
// No longer needed.
|
|
||||||
if err := os.Remove(releaseNotesFile); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := r.git("commit", "-a", "-m", fmt.Sprintf("%s Prepare repository for %s\n\n[ci skip]", commitPrefix, finalVersion)); err != nil {
|
if _, err := r.git("commit", "-a", "-m", fmt.Sprintf("%s Prepare repository for %s\n\n[ci skip]", commitPrefix, finalVersion)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -193,36 +130,6 @@ func (r *ReleaseHandler) Run() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReleaseHandler) gitPush() {
|
|
||||||
if r.skipPublish {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, err := r.git("push", "origin", "HEAD"); err != nil {
|
|
||||||
log.Fatal("push failed:", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *ReleaseHandler) release(releaseNotesFile string) error {
|
|
||||||
if r.try {
|
|
||||||
fmt.Println("Skip goreleaser...")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
args := []string{"--parallelism", "2", "--timeout", "120m", "--rm-dist", "--release-notes", releaseNotesFile}
|
|
||||||
if r.skipPublish {
|
|
||||||
args = append(args, "--skip-publish")
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd, _ := hexec.SafeCommand("goreleaser", args...)
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
err := cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("goreleaser failed: %w", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *ReleaseHandler) bumpVersions(ver hugo.Version) error {
|
func (r *ReleaseHandler) bumpVersions(ver hugo.Version) error {
|
||||||
toDev := ""
|
toDev := ""
|
||||||
|
|
||||||
|
@ -264,6 +171,29 @@ func (r *ReleaseHandler) bumpVersions(ver hugo.Version) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r ReleaseHandler) calculateVersions() (hugo.Version, hugo.Version) {
|
||||||
|
newVersion := hugo.MustParseVersion(r.branchVersion)
|
||||||
|
finalVersion := newVersion.Next()
|
||||||
|
finalVersion.PatchLevel = 0
|
||||||
|
|
||||||
|
if newVersion.Suffix != "-test" {
|
||||||
|
newVersion.Suffix = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
finalVersion.Suffix = "-DEV"
|
||||||
|
|
||||||
|
return newVersion, finalVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ReleaseHandler) gitPush() {
|
||||||
|
if r.skipPush {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err := r.git("push", "origin", "HEAD"); err != nil {
|
||||||
|
log.Fatal("push failed:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (r *ReleaseHandler) replaceInFile(filename string, oldNew ...string) error {
|
func (r *ReleaseHandler) replaceInFile(filename string, oldNew ...string) error {
|
||||||
filename = filepath.FromSlash(filename)
|
filename = filepath.FromSlash(filename)
|
||||||
fi, err := os.Stat(filename)
|
fi, err := os.Stat(filename)
|
||||||
|
@ -272,11 +202,11 @@ func (r *ReleaseHandler) replaceInFile(filename string, oldNew ...string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.try {
|
if r.try {
|
||||||
fmt.Printf("Replace in %q: %q\n", filename, oldNew)
|
logf("Replace in %q: %q\n", filename, oldNew)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := ioutil.ReadFile(filename)
|
b, err := os.ReadFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -287,18 +217,22 @@ func (r *ReleaseHandler) replaceInFile(filename string, oldNew ...string) error
|
||||||
newContent = re.ReplaceAllString(newContent, oldNew[i+1])
|
newContent = re.ReplaceAllString(newContent, oldNew[i+1])
|
||||||
}
|
}
|
||||||
|
|
||||||
return ioutil.WriteFile(filename, []byte(newContent), fi.Mode())
|
return os.WriteFile(filename, []byte(newContent), fi.Mode())
|
||||||
}
|
}
|
||||||
|
|
||||||
func isCI() bool {
|
func git(args ...string) (string, error) {
|
||||||
return os.Getenv("CI") != ""
|
cmd, _ := hexec.SafeCommand("git", args...)
|
||||||
}
|
out, err := cmd.CombinedOutput()
|
||||||
|
|
||||||
func wd() string {
|
|
||||||
p, err := os.Getwd()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
return "", fmt.Errorf("git failed: %q: %q (%q)", err, out, args)
|
||||||
}
|
}
|
||||||
return p
|
return string(out), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func logf(format string, args ...interface{}) {
|
||||||
|
fmt.Fprintf(os.Stderr, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func logln(args ...interface{}) {
|
||||||
|
fmt.Fprintln(os.Stderr, args...)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue