diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2629cfd..edf7304 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,21 +14,36 @@ jobs: runs-on: ubuntu-latest steps: - - name: Set up Go 1.21 + - name: Set up latest stable Go uses: actions/setup-go@v5 with: - go-version: 1.21 + go-version: stable + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-tags: 1 + fetch-depth: 1 + + # Set environment variables required by GoReleaser + - name: Set build environment variables + run: | + echo "GIT_STATE=$(if git diff-index --quiet HEAD --; then echo 'clean'; else echo 'dirty'; fi)" >> $GITHUB_ENV + echo "BUILD_HOST=$(hostname)" >> $GITHUB_ENV + echo "GO_VERSION=$(go version | awk '{print $3}')" >> $GITHUB_ENV + echo "BUILD_USER=$(whoami)" >> $GITHUB_ENV + echo "CGO_ENABLED=1" >> $GITHUB_ENV + - name: Docker Login uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-tags: 1 - fetch-depth: 0 + - name: Release with goreleaser uses: goreleaser/goreleaser-action@v6 env: diff --git a/.github/workflows/prbuild.yml b/.github/workflows/prbuild.yml new file mode 100644 index 0000000..476ba60 --- /dev/null +++ b/.github/workflows/prbuild.yml @@ -0,0 +1,44 @@ +name: Build PR with goreleaser + +on: + pull_request: + branches: + - main + types: [opened, synchronize, reopened, edited] + workflow_dispatch: + +jobs: + prbuild: + runs-on: ubuntu-latest + steps: + + - name: Set up latest stable Go + uses: actions/setup-go@v5 + with: + go-version: stable + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-tags: 1 + fetch-depth: 1 + + # Set environment variables required by GoReleaser + - name: Set build environment variables + run: | + echo "GIT_STATE=$(if git diff-index --quiet HEAD --; then echo 'clean'; else echo 'dirty'; fi)" >> $GITHUB_ENV + echo "BUILD_HOST=$(hostname)" >> $GITHUB_ENV + echo "GO_VERSION=$(go version | awk '{print $3}')" >> $GITHUB_ENV + echo "BUILD_USER=$(whoami)" >> $GITHUB_ENV + echo "CGO_ENABLED=1" >> $GITHUB_ENV + + - name: Build with goreleaser + uses: goreleaser/goreleaser-action@v6 + + with: + version: '~> v2' + args: release --snapshot + id: goreleaser \ No newline at end of file diff --git a/.gitignore b/.gitignore index 45e95ea..aeafd79 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ emulator/rf-emulator **.part dist/* **coverage.out** +magellan.1 \ No newline at end of file diff --git a/.goreleaser.yaml b/.goreleaser.yaml index b202123..d8552b6 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -7,12 +7,36 @@ before: - go-md2man -in README.md -out magellan.1 builds: - - env: - - CGO_ENABLED=1 + - binary: magellan + main: ./main.go + # export GIT_STATE=$(if git diff-index --quiet HEAD --; then echo 'clean'; else echo 'dirty'; fi) + # export BUILD_HOST=$(hostname) + # export GO_VERSION=$(go version | awk '{print $3}') + # export BUILD_USER=$(whoami) + ldflags: + - "-X github.com/OpenCHAMI/magellan/internal/version.GitCommit={{ .Commit }} \ + -X github.com/OpenCHAMI/magellan/internal/version.BuildTime={{ .Timestamp }} \ + -X github.com/OpenCHAMI/magellan/internal/version.Version={{ .Version }} \ + -X github.com/OpenCHAMI/magellan/internal/version.GitBranch={{ .Branch }} \ + -X github.com/OpenCHAMI/magellan/internal/version.GitTag={{ .Tag }} \ + -X github.com/OpenCHAMI/magellan/internal/version.GitState={{ .Env.GIT_STATE }} \ + -X github.com/OpenCHAMI/magellan/internal/version.BuildHost={{ .Env.BUILD_HOST }} \ + -X github.com/OpenCHAMI/magellan/internal/version.GoVersion={{ .Env.GO_VERSION }} \ + -X github.com/OpenCHAMI/magellan/internal/version.BuildUser={{ .Env.BUILD_USER }} " + tags: + - version goos: - linux + - darwin + - windows goarch: - amd64 + - arm64 + goamd64: + - v3 + env: + - CGO_ENABLED=0 + archives: - format: tar.gz # this name template makes the OS and Arch compatible with the results of uname. @@ -27,26 +51,89 @@ archives: - LICENSE - CHANGELOG.md - README.md - - bin/magellan.sh - magellan.1 + +nfpms: + - id: magellan + formats: + - deb + - rpm + - apk + - archlinux + maintainer: "David J. Allen " + description: "Magellan is a discovery tool for BMCs." + homepage: "https://www.openchami.org" + license: MIT + section: utils + priority: optional + contents: + - src: dist/magellan_{{ .Os }}_{{ if eq .Arch "amd64" }}{{ .Arch }}_{{ .Amd64 }}{{ else }}{{ .Arch }}{{ end }}/magellan + dst: /usr/local/bin/magellan + - src: magellan.1 + dst: /usr/share/man/man1/ + + dockers: - - - image_templates: - - ghcr.io/openchami/{{.ProjectName}}:latest - - ghcr.io/openchami/{{.ProjectName}}:{{ .Tag }} - - ghcr.io/openchami/{{.ProjectName}}:v{{ .Major }} - - ghcr.io/openchami/{{.ProjectName}}:v{{ .Major }}.{{ .Minor }} + - image_templates: + - &amd64_linux_image ghcr.io/openchami/{{.ProjectName}}:{{ .Tag }}-amd64 + - ghcr.io/openchami/{{.ProjectName}}:{{ .Major }}-amd64 + - ghcr.io/openchami/{{.ProjectName}}:{{ .Major }}.{{ .Minor }}-amd64 + use: buildx build_flag_templates: - "--pull" + - "--platform=linux/amd64" - "--label=org.opencontainers.image.created={{.Date}}" - "--label=org.opencontainers.image.title={{.ProjectName}}" - "--label=org.opencontainers.image.revision={{.FullCommit}}" - "--label=org.opencontainers.image.version={{.Version}}" + goarch: amd64 + goamd64: v3 extra_files: - LICENSE - CHANGELOG.md - README.md - - bin/magellan.sh + - image_templates: + - &arm64v8_linux_image ghcr.io/openchami/{{.ProjectName}}:{{ .Tag }}-arm64 + - ghcr.io/openchami/{{.ProjectName}}:{{ .Major }}-arm64 + - ghcr.io/openchami/{{.ProjectName}}:{{ .Major }}.{{ .Minor }}-arm64 + use: buildx + build_flag_templates: + - "--pull" + - "--platform=linux/arm64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + extra_files: + - LICENSE + - CHANGELOG.md + - README.md + goarch: arm64 + +docker_manifests: + - name_template: "ghcr.io/openchami/{{.ProjectName}}:latest" + image_templates: + - *amd64_linux_image + - *arm64v8_linux_image + + - name_template: "ghcr.io/openchami/{{.ProjectName}}:{{ .Tag }}" + image_templates: + - *amd64_linux_image + - *arm64v8_linux_image + + - name_template: "ghcr.io/openchami/{{.ProjectName}}:{{ .Major }}" + image_templates: + - *amd64_linux_image + - *arm64v8_linux_image + + - name_template: "ghcr.io/openchami/{{.ProjectName}}:{{ .Major }}.{{ .Minor }}" + image_templates: + - *amd64_linux_image + - *arm64v8_linux_image + + + + checksum: name_template: 'checksums.txt' snapshot: @@ -57,8 +144,3 @@ changelog: exclude: - '^docs:' - '^test:' -release: - github: - name_template: "{{.Version}}" - prerelease: auto - mode: append diff --git a/Dockerfile b/Dockerfile index 510a291..d9632fe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,17 @@ -FROM cgr.dev/chainguard/wolfi-base +FROM chainguard/wolfi-base:latest -RUN apk add --no-cache tini bash +# Include curl in the final image for manual checks of the Redfish urls +RUN set -ex \ + && apk update \ + && apk add --no-cache curl tini \ + && rm -rf /var/cache/apk/* \ + && rm -rf /tmp/* # nobody 65534:65534 USER 65534:65534 COPY magellan /magellan -COPY /bin/magellan.sh /magellan.sh CMD [ "/magellan" ] diff --git a/bin/magellan.sh b/bin/magellan.sh deleted file mode 100755 index c91d922..0000000 --- a/bin/magellan.sh +++ /dev/null @@ -1,122 +0,0 @@ -#!/bin/bash - -EXE=./magellan -SUBNETS="" -PORTS="" -USER="" -PASS="" -SMD_HOST="" -SMD_PORT="" -THREADS="1" -TIMEOUT="30" -ARGS="" -FORCE_UPDATE=false -SCAN_PARAMS="" -COLLECT_PARAMS="" - - -function scan() { - # ./magellan scan --subnet 172.16.0.0 --port 443 - ${EXE} scan ${SCAN_PARAMS} - # --subnet ${SUBNETS} \ - # --port ${PORTS} \ - # --timeout ${TIMEOUT} \ - # --threads ${THREADS} -} - -function list(){ - # ./magellan list - ${EXE} list -} - -function collect() { - # ./magellan collect --user admin --pass password - ${EXE} collect ${COLLECT_PARAMS} - # --user ${USER} \ - # --pass ${PASS} \ - # --timeout ${TIMEOUT} \ - # --threads ${THREADS} \ - # --host ${SMD_HOST} \ - # --port ${SMD_PORT} \ - # --force-update ${FORCE_UPDATE} -} - - -# parse incoming arguments to set variables -while [[ $# -gt 0 ]]; do - case $1 in - --scan) - SCAN_PARAMS="$2" - shift - shift - ;; - --collect) - COLLECT_PARAMS="$2" - shift - shift - ;; - --subnet) - SUBNETS="$2" - shift # past argument - shift # past value - ;; - -p|--port) - PORTS="$2" - shift # past argument - shift # past value - ;; - --user) - USER="$2" - shift # past argument - shift # past value - ;; - --pass|--password) - PASS="$2" - shift - shift - ;; - --smd-host) - SMD_HOST="$2" - shift - shift - ;; - --smd-port) - SMD_PORT="$2" - shift - shift - ;; - --timeout) - TIMEOUT="$2" - shift - shift - ;; - --threads) - THREADS="$2" - shift - shift - ;; - -*|--*) - echo "Unknown option $1" - exit 1 - ;; - *) - ARGS+=("$1") # save positional arg - shift # past argument - ;; - esac -done - -set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters - -if [[ -n $1 ]]; then - echo "Last line of file specified as non-opt/last argument:" - tail -1 "$1" -fi - -scan -collect - -# run with docker -# docker run magellan:latest magellan.sh \ -# --scan "--subnet 127.16.0.0 --port 443" \ -# --collect "--user admin --pass password --timeout 300 --threads 1 --smd-host host --smd-port port" \ No newline at end of file diff --git a/cmd/version.go b/cmd/version.go index b9cfd82..87b7596 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -1,41 +1,18 @@ package cmd import ( - "fmt" - + "github.com/OpenCHAMI/magellan/internal/version" "github.com/spf13/cobra" ) -var ( - version string - commit string - date string - output string -) - var versionCmd = &cobra.Command{ Use: "version", Short: "Print version info and exit", Run: func(cmd *cobra.Command, args []string) { - if cmd.Flag("commit").Value.String() == "true" { - output = commit - if date != "" { - output += " built on " + date - } - fmt.Println(output) - } else { - fmt.Printf("%s-%s\n", version, commit) - } + version.PrintVersionInfo() }, } func init() { - versionCmd.Flags().Bool("commit", false, "show the version commit") rootCmd.AddCommand(versionCmd) } - -func SetVersionInfo(buildVersion string, buildCommit string, buildDate string) { - version = buildVersion - commit = buildCommit - date = buildDate -} diff --git a/dist/archlinux/PKGBUILD b/dist/archlinux/PKGBUILD deleted file mode 100644 index 23e69b7..0000000 --- a/dist/archlinux/PKGBUILD +++ /dev/null @@ -1,29 +0,0 @@ -# Maintainer: David J. Allen -pkgname=magellan -pkgver=v0.1.5 -pkgrel=1 -pkgdesc="Redfish-based BMC discovery tool written in Go" -arch=("x86_64") -url="https://github.com/OpenCHAMI/magellan" -license=('MIT') -groups=("openchami") -provides=('magellan') -conflicts=('magellan') -source_x86_64=("${url}/releases/download/${pkgver}/${pkgname}_Linux_x86_64.tar.gz") -sha256sums_x86_64=('1bb028d592d5389b519362e6aa7021f27443f0b36471e09ee7f47ab5cb6d4d7f') - -# Please refer to the 'USING VCS SOURCES' section of the PKGBUILD man page for -# a description of each element in the source array. - -pkgver() { - cd "$srcdir" || exit - printf "%s" "$(git describe --tags --abbrev=0)" -} - -package() { - cd "$srcdir/" || exit - - # install the binary to /usr/bin - mkdir -p "${pkgdir}/usr/bin" - install -m755 magellan "${pkgdir}/usr/bin/magellan" -} diff --git a/internal/version/version.go b/internal/version/version.go new file mode 100644 index 0000000..7d9d231 --- /dev/null +++ b/internal/version/version.go @@ -0,0 +1,60 @@ +package version + +import ( + "fmt" +) + +// GitCommit stores the latest Git commit hash. +// Set via -ldflags "-X github.com/OpenCHAMI/magellan/internal/version.GitCommit=$(git rev-parse HEAD)" +var GitCommit string + +// BuildTime stores the build timestamp in UTC. +// Set via -ldflags "-X github.com/OpenCHAMI/magellan/internal/version.BuildTime=$(date -u +%Y-%m-%dT%H:%M:%SZ)" +var BuildTime string + +// Version indicates the version of the binary, such as a release number or semantic version. +// Set via -ldflags "-X github.com/OpenCHAMI/magellan/internal/version.Version=v1.0.0" +var Version string + +// GitBranch holds the name of the Git branch from which the build was created. +// Set via -ldflags "-X github.com/OpenCHAMI/magellan/internal/version.GitBranch=$(git rev-parse --abbrev-ref HEAD)" +var GitBranch string + +// GitTag represents the most recent Git tag at build time, if any. +// Set via -ldflags "-X github.com/OpenCHAMI/magellan/internal/version.GitTag=$(git describe --tags --abbrev=0)" +var GitTag string + +// GitState indicates whether the working directory was "clean" or "dirty" (i.e., with uncommitted changes). +// Set via -ldflags "-X github.com/OpenCHAMI/magellan/internal/version.GitState=$(if git diff-index --quiet HEAD --; then echo 'clean'; else echo 'dirty'; fi)" +var GitState string + +// BuildHost stores the hostname of the machine where the binary was built. +// Set via -ldflags "-X github.com/OpenCHAMI/magellan/internal/version.BuildHost=$(hostname)" +var BuildHost string + +// GoVersion captures the Go version used to build the binary. +// Typically, this can be obtained automatically with runtime.Version(), but you can set it manually. +// Set via -ldflags "-X github.com/OpenCHAMI/magellan/internal/version.GoVersion=$(go version | awk '{print $3}')" +var GoVersion string + +// BuildUser is the username of the person or system that initiated the build process. +// Set via -ldflags "-X github.com/OpenCHAMI/magellan/internal/version.BuildUser=$(whoami)" +var BuildUser string + +// PrintVersionInfo outputs all versioning information for troubleshooting or version checks. +func PrintVersionInfo() { + fmt.Printf("Version: %s\n", Version) + fmt.Printf("Git Commit: %s\n", GitCommit) + fmt.Printf("Build Time: %s\n", BuildTime) + fmt.Printf("Git Branch: %s\n", GitBranch) + fmt.Printf("Git Tag: %s\n", GitTag) + fmt.Printf("Git State: %s\n", GitState) + fmt.Printf("Build Host: %s\n", BuildHost) + fmt.Printf("Go Version: %s\n", GoVersion) + fmt.Printf("Build User: %s\n", BuildUser) +} + +func VersionInfo() string { + return fmt.Sprintf("Version: %s, Git Commit: %s, Build Time: %s, Git Branch: %s, Git Tag: %s, Git State: %s, Build Host: %s, Go Version: %s, Build User: %s", + Version, GitCommit, BuildTime, GitBranch, GitTag, GitState, BuildHost, GoVersion, BuildUser) +} diff --git a/main.go b/main.go index 0d248c4..ebe2d95 100644 --- a/main.go +++ b/main.go @@ -4,13 +4,6 @@ import ( "github.com/OpenCHAMI/magellan/cmd" ) -var ( - version string - commit string - date string -) - func main() { - cmd.SetVersionInfo(version, commit, date) cmd.Execute() }