diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 00000000..a4147761 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,154 @@ +name: Release + +on: + push: + tags: + - 'v*' + +jobs: + release: + strategy: + matrix: + include: + - goos: linux + goarch: amd64 + runner: ubuntu-latest + - goos: linux + goarch: arm64 + runner: ubuntu-24.04-arm + - goos: darwin + goarch: amd64 + runner: macos-13 + - goos: darwin + goarch: arm64 + runner: macos-latest + + runs-on: ${{ matrix.runner }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.24' # Adjust to your Go version + + - name: Install dependencies + run: go mod download + + - name: Install CGO dependencies for Linux + if: matrix.goos == 'linux' + run: | + sudo apt-get update + sudo apt-get install -y pkg-config + sudo apt update && \ + sudo DEBIAN_FRONTEND=noninteractive apt install -y build-essential cmake pkg-config libssl-dev libssh2-1-dev zlib1g-dev libhttp-parser-dev python3 wget tar git && \ + wget https://github.com/libgit2/libgit2/archive/refs/tags/v1.5.1.tar.gz -O libgit2-v1.5.1.tar.gz && \ + tar -xzf libgit2-v1.5.1.tar.gz && \ + cd libgit2-1.5.1 && \ + mkdir build && \ + cd build && \ + cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF && \ + make -j$(nproc) && \ + sudo make install && \ + sudo ldconfig + + - name: Install CGO dependencies for macOS + if: matrix.goos == 'darwin' + run: | + brew install cmake wget zlib libiconv && \ + wget https://github.com/libgit2/libgit2/archive/refs/tags/v1.5.1.tar.gz -O libgit2-v1.5.1.tar.gz && \ + tar -xzf libgit2-v1.5.1.tar.gz && \ + cd libgit2-1.5.1 && \ + mkdir build && \ + cd build && \ + cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF && \ + make -j$(nproc) && \ + sudo make install + + - name: Build binary for linux + if: matrix.goos == 'linux' + env: + CGO_ENABLED: 1 + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + run: | + go build \ + -tags "static system_libgit2" \ + -ldflags "-X github.com/CloudNativeAI/modctl/pkg/version.GitVersion=${{ github.ref_name }} \ + -X github.com/CloudNativeAI/modctl/pkg/version.GitCommit=$(git rev-parse --short HEAD) \ + -X github.com/CloudNativeAI/modctl/pkg/version.BuildTime=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \ + -extldflags '-static'" \ + -o modctl \ + main.go + + - name: Build binary for macOS + if: matrix.goos == 'darwin' + env: + CGO_ENABLED: 1 + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + CGO_LDFLAGS: "-lgit2 -lz -liconv -Wl,-rpath,/Users/runner/work/modctl/modctl/libgit2-1.5.1/build" + run: | + go build \ + -tags "static system_libgit2" \ + -ldflags "-X github.com/CloudNativeAI/modctl/pkg/version.GitVersion=${{ github.ref_name }} \ + -X github.com/CloudNativeAI/modctl/pkg/version.GitCommit=$(git rev-parse --short HEAD) \ + -X github.com/CloudNativeAI/modctl/pkg/version.BuildTime=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" \ + -o modctl \ + main.go + + - name: Create archive + run: | + mkdir -p dist + tar -czf dist/modctl-${{ github.ref_name }}-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz \ + LICENSE README.md modctl + + - name: Build deb/rpm packages + if: matrix.goos == 'linux' + env: + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + VERSION: ${{ github.ref_name }} + run: | + echo 'deb [trusted=yes] https://repo.goreleaser.com/apt/ /' | sudo tee /etc/apt/sources.list.d/goreleaser.list + sudo apt update + sudo apt install nfpm + nfpm pkg --packager deb --config hack/nfpm.yaml --target dist/modctl-${{ github.ref_name }}-${{ matrix.goos }}-${{ matrix.goarch }}.deb + nfpm pkg --packager rpm --config hack/nfpm.yaml --target dist/modctl-${{ github.ref_name }}-${{ matrix.goos }}-${{ matrix.goarch }}.rpm + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: modctl-${{ matrix.goos }}-${{ matrix.goarch }} + path: dist/ + + create-release: + needs: release + runs-on: ubuntu-latest + steps: + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Generate unified checksums + run: | + cd artifacts + find . -type f \( -name "modctl-*.tar.gz" -o -name "modctl-*.deb" -o -name "modctl-*.rpm" \) -exec shasum -a 256 {} \; > ../checksums.txt + + - name: Create draft release + uses: softprops/action-gh-release@v2 + with: + draft: true + files: | + artifacts/**/modctl-*.tar.gz + artifacts/**/modctl-*.deb + artifacts/**/modctl-*.rpm + checksums.txt + generate_release_notes: true + env: + GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index a155cfff..00000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,92 +0,0 @@ -name: Release - -on: - push: - tags: - - v* - -permissions: - contents: read - -jobs: - goreleaser: - permissions: - contents: write - runs-on: ubuntu-latest - timeout-minutes: 60 - outputs: - hashes: ${{ steps.hash.outputs.hashes }} - steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - with: - fetch-depth: 0 - submodules: recursive - - - name: Setup Go - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b - with: - go-version-file: go.mod - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y pkg-config - sudo apt update && \ - sudo DEBIAN_FRONTEND=noninteractive apt install -y build-essential cmake pkg-config libssl-dev libssh2-1-dev zlib1g-dev libhttp-parser-dev python3 wget tar git && \ - wget https://github.com/libgit2/libgit2/archive/refs/tags/v1.5.1.tar.gz -O libgit2-v1.5.1.tar.gz && \ - tar -xzf libgit2-v1.5.1.tar.gz && \ - cd libgit2-1.5.1 && \ - mkdir build && \ - cd build && \ - cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF && \ - make -j$(nproc) && \ - sudo make install && \ - sudo ldconfig - env: - LIBGIT2_SYS_USE_PKG_CONFIG: "1" - - - name: Check GoReleaser config - uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 - with: - version: latest - args: check - - - name: Run GoReleaser - uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 - id: run-goreleaser - with: - version: latest - args: release --clean - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Generate subject - id: hash - env: - ARTIFACTS: "${{ steps.run-goreleaser.outputs.artifacts }}" - run: | - set -euo pipefail - hashes=$(echo $ARTIFACTS | jq --raw-output '.[] | {name, "digest": (.extra.Digest // .extra.Checksum)} | select(.digest) | {digest} + {name} | join(" ") | sub("^sha256:";"")' | base64 -w0) - if test "$hashes" = ""; then # goreleaser < v1.13.0 - checksum_file=$(echo "$ARTIFACTS" | jq -r '.[] | select (.type=="Checksum") | .path') - hashes=$(cat $checksum_file | base64 -w0) - fi - echo "hashes=$hashes" >> $GITHUB_OUTPUT - - - name: Set tag output - id: tag - run: echo "tag_name=${GITHUB_REF#refs/*/}" >> "$GITHUB_OUTPUT" - - provenance: - needs: [goreleaser] - permissions: - actions: read # To read the workflow path. - id-token: write # To sign the provenance. - contents: write # To add assets to a release. - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 - with: - base64-subjects: "${{ needs.goreleaser.outputs.hashes }}" - upload-assets: true # upload to a new release - upload-tag-name: "${{ needs.release.outputs.tag_name }}" - draft-release: true diff --git a/.goreleaser.yml b/.goreleaser.yml deleted file mode 100644 index 1ce8a466..00000000 --- a/.goreleaser.yml +++ /dev/null @@ -1,68 +0,0 @@ -release: - draft: true - replace_existing_draft: true - -before: - hooks: - - go mod download - -builds: - - main: main.go - id: modctl - binary: modctl - goos: - - linux - - darwin - goarch: - - amd64 - - arm64 - env: - - CGO_ENABLED=1 - ldflags: - - -X github.com/CloudNativeAI/modctl/pkg/version.GitVersion={{ .Tag }} - - -X github.com/CloudNativeAI/modctl/pkg/version.GitCommit={{ .ShortCommit }} - - -X github.com/CloudNativeAI/modctl/pkg/version.BuildTime={{ .Date }} - - -extldflags "-static" - tags: - - static - - system_libgit2 - -archives: - - name_template: "modctl-{{ .Version }}-{{ .Os }}-{{ .Arch }}" - formats: ["tar.gz"] - files: - - LICENSE - - README.md - -checksum: - name_template: "checksums.txt" - -snapshot: - version_template: "{{ .Tag }}-next" - -changelog: - sort: asc - filters: - exclude: - - "^docs:" - - "^test:" - -nfpms: - - id: modctl - maintainer: Model Spec Maintainers - file_name_template: "modctl-{{ .Version }}-{{ .Os }}-{{ .Arch }}" - package_name: modctl - description: A command line tool for managing artifact bundled based on the Model Format Specification - license: "Apache 2.0" - bindir: /usr/bin - ids: - - modctl - formats: - - rpm - - deb - contents: - - src: build/package/docs/modctl.1 - dst: /usr/share/man/man1/modctl.1 - - - src: LICENSE - dst: /usr/share/doc/modctl/License diff --git a/hack/nfpm.yaml b/hack/nfpm.yaml new file mode 100644 index 00000000..fd7c3fea --- /dev/null +++ b/hack/nfpm.yaml @@ -0,0 +1,17 @@ +arch: ${GOARCH} +platform: ${GOOS} +name: modctl +version: ${VERSION} +maintainer: "Model Spec Maintainers " +description: "A command line tool for managing artifact bundled based on the Model Format Specification" +license: "Apache 2.0" +contents: + - src: modctl + dst: /usr/bin/modctl + expand: true + + - src: build/package/docs/modctl.1 + dst: /usr/share/man/man1/modctl.1 + + - src: LICENSE + dst: /usr/share/doc/modctl/License