diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..e9c9fac08 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,312 @@ +name: build + +on: + push: + branches: + - "main" + workflow_dispatch: + +env: + PKG_NAME: "nomad" + GO_TAGS: "release" + +jobs: + get-go-version: + runs-on: ubuntu-latest + outputs: + go-version: ${{ steps.get-go-version.outputs.go-version }} + steps: + - uses: actions/checkout@v2 + - name: Determine Go version + id: get-go-version + # We use .go-version as our source of truth for current Go + # version, because "goenv" can react to it automatically. + run: | + echo "Building with Go $(cat .go-version)" + echo "::set-output name=go-version::$(cat .go-version)" + get-product-version: + runs-on: ubuntu-latest + outputs: + product-version: ${{ steps.get-product-version.outputs.product-version }} + steps: + - uses: actions/checkout@v2 + - name: get product version + id: get-product-version + run: | + make version + echo "::set-output name=product-version::$(make version)" + generate-metadata-file: + needs: get-product-version + runs-on: ubuntu-latest + outputs: + filepath: ${{ steps.generate-metadata-file.outputs.filepath }} + steps: + - name: "Checkout directory" + uses: actions/checkout@v2 + - name: Generate metadata file + id: generate-metadata-file + uses: hashicorp/actions-generate-metadata@v1 + with: + version: ${{ needs.get-product-version.outputs.product-version }} + product: ${{ env.PKG_NAME }} + repositoryOwner: "hashicorp" + - uses: actions/upload-artifact@v2 + with: + name: metadata.json + path: ${{ steps.generate-metadata-file.outputs.filepath }} + generate-ld-flags: + needs: get-product-version + runs-on: ubuntu-latest + outputs: + ldflags: ${{ steps.generate-ld-flags.outputs.ldflags }} + steps: + - uses: actions/checkout@v2 + - name: "Generate ld flags" + id: generate-ld-flags + run: | + project="$(go list -m)" + sha="$(git rev-parse --short HEAD)" + echo "::set-output name=ldflags::"-s -w -X \'$project/version.Name=${{ env.PKG_NAME }}\' \ + -X \'$project/version.GitDescribe=v$(make version base=1)\'"" + + build-other: + needs: [get-go-version, get-product-version, generate-ld-flags] + runs-on: ubuntu-latest + strategy: + matrix: + goos: [windows] + goarch: ["386", "amd64"] + fail-fast: true + + name: Go ${{ needs.get-go-version.outputs.go-version }} ${{ matrix.goos }} ${{ matrix.goarch }} build + + steps: + - uses: actions/checkout@v2 + - name: Setup go + uses: actions/setup-go@v2 + with: + go-version: ${{ needs.get-go-version.outputs.go-version }} + + - name: Build dependencies + run: make deps + + - name: Setup node and yarn + uses: actions/setup-node@v2 + with: + node-version: "14" + cache-dependency-path: "ui/yarn.lock" + + - name: Install Yarn + run: | + npm install -g yarn + + - name: Build prerelease + run: make prerelease + + - name: Build + env: + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + GO_TAGS: ${{ env.GO_TAGS }} + GO_LDFLAGS: ${{ needs.generate-ld-flags.outputs.ldflags }} + CGO_ENABLED: 1 + run: | + make pkg/${{ matrix.goos }}_${{ matrix.goarch }}.zip + mv pkg/${{ matrix.goos }}_${{ matrix.goarch }}.zip ${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip + - uses: actions/upload-artifact@v2 + with: + name: ${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip + path: ${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip + + build-linux: + needs: [get-go-version, get-product-version, generate-ld-flags] + runs-on: ubuntu-latest + strategy: + matrix: + goos: [linux] + goarch: ["arm", "arm64", "386", "amd64"] + fail-fast: true + + name: Go ${{ needs.get-go-version.outputs.go-version }} ${{ matrix.goos }} ${{ matrix.goarch }} build + + steps: + - uses: actions/checkout@v2 + - name: Setup go + uses: actions/setup-go@v2 + with: + go-version: ${{ needs.get-go-version.outputs.go-version }} + + - name: Build dependencies + run: make deps + + - name: Setup node and yarn + uses: actions/setup-node@v2 + with: + node-version: "14" + cache-dependency-path: "ui/yarn.lock" + + - name: Install Yarn + run: | + npm install -g yarn + + - name: Build prerelease + run: make prerelease + + - name: Install Linux build utilties + run: | + sudo apt-get update + sudo apt-get install -y software-properties-common + sudo dpkg --add-architecture i386 + sudo apt-get update + sudo apt-get install -y \ + libc6-dev-i386 \ + libpcre3-dev \ + linux-libc-dev:i386 + sudo apt-get install -y \ + binutils-aarch64-linux-gnu \ + binutils-arm-linux-gnueabihf \ + gcc-aarch64-linux-gnu \ + gcc-arm-linux-gnueabihf \ + gcc-multilib-arm-linux-gnueabihf + + - name: Set gcc + run: | + if [ "${{ matrix.goarch }}" == "arm" ]; then + echo "CC=arm-linux-gnueabihf-gcc" >> $GITHUB_ENV + elif [ "${{ matrix.goarch }}" == "arm64" ]; then + echo "CC=aarch64-linux-gnu-gcc" >> $GITHUB_ENV + fi + + - name: Build + env: + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + GO_TAGS: ${{ env.GO_TAGS }} + GO_LDFLAGS: ${{ needs.generate-ld-flags.outputs.ldflags }} + CGO_ENABLED: 1 + run: | + make pkg/${{ matrix.goos }}_${{ matrix.goarch }}.zip + mv pkg/${{ matrix.goos }}_${{ matrix.goarch }}.zip ${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip + - uses: actions/upload-artifact@v2 + with: + name: ${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip + path: ${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip + + - name: Package + uses: hashicorp/actions-packaging-linux@v1 + with: + name: ${{ env.PKG_NAME }} + description: "Nomad is an easy-to-use, flexible, and performant workload orchestrator that can deploy a mix of microservice, batch, containerized, and non-containerized applications." + arch: ${{ matrix.goarch }} + version: ${{ needs.get-product-version.outputs.product-version }} + maintainer: "HashiCorp" + homepage: "https://github.com/hashicorp/nomad" + license: "MPL-2.0" + binary: "pkg/${{ matrix.goos }}_${{ matrix.goarch }}/${{ env.PKG_NAME }}" + deb_depends: "openssl" + rpm_depends: "openssl" + config_dir: ".release/linux/package/" + preinstall: ".release/linux/preinst" + postremove: ".release/linux/postrm" + + - name: Set Package Names + run: | + echo "RPM_PACKAGE=$(basename out/*.rpm)" >> $GITHUB_ENV + echo "DEB_PACKAGE=$(basename out/*.deb)" >> $GITHUB_ENV + + - uses: actions/upload-artifact@v2 + with: + name: ${{ env.RPM_PACKAGE }} + path: out/${{ env.RPM_PACKAGE }} + + - uses: actions/upload-artifact@v2 + with: + name: ${{ env.DEB_PACKAGE }} + path: out/${{ env.DEB_PACKAGE }} + + build-darwin: + needs: [get-go-version, get-product-version, generate-ld-flags] + runs-on: macos-latest + strategy: + matrix: + goos: [darwin] + goarch: ["arm64", "amd64"] + fail-fast: true + + name: Go ${{ needs.get-go-version.outputs.go-version }} ${{ matrix.goos }} ${{ matrix.goarch }} build + + steps: + - uses: actions/checkout@v2 + + - name: Setup go + uses: actions/setup-go@v2 + with: + go-version: ${{ needs.get-go-version.outputs.go-version }} + + - name: Build dependencies + run: make deps + + - name: Setup node and yarn + uses: actions/setup-node@v2 + with: + node-version: "14" + cache-dependency-path: "ui/yarn.lock" + + - name: Install Yarn + run: | + npm install -g yarn + + - name: Build prerelease + run: make prerelease + + - name: Build + env: + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + GO_TAGS: "${{ env.GO_TAGS }} netcgo" + GO_LDFLAGS: ${{ needs.generate-ld-flags.outputs.ldflags }} + CGO_ENABLED: 1 + run: | + make pkg/${{ matrix.goos }}_${{ matrix.goarch }}.zip + mv pkg/${{ matrix.goos }}_${{ matrix.goarch }}.zip ${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip + - uses: actions/upload-artifact@v2 + with: + name: ${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip + path: ${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip + + # This placed here for when the Nomad team is ready to build docker images. + # Please reach out the RDX team for assistance or refer to the CRT Self-Serve Onboarding doc. + + # build-docker-default: + # name: Docker ${{ matrix.arch }} default release build + # needs: + # - get-product-version + # - build + # runs-on: ubuntu-latest + # strategy: + # matrix: + # arch: ["arm", "arm64", "386", "amd64"] + # env: + # repo: ${{github.event.repository.name}} + # version: ${{needs.get-product-version.outputs.product-version}} + + # steps: + # - uses: actions/checkout@v2 + # - name: Docker Build (Action) + # uses: hashicorp/actions-docker-build@v1 + # with: + # # Add smoke test here. Below is a sample smoke test that runs the built image + # # and validates the version. + # smoke_test: | + # TEST_VERSION="$(docker run "${IMAGE_NAME}" | awk '/CLI version/{print $3}')" + # if [ "${TEST_VERSION}" != "${version}" ]; then + # echo "Test FAILED" + # exit 1 + # fi + # echo "Test PASSED" + # version: ${{env.version}} + # target: release-default + # arch: ${{matrix.arch}} + # tags: | + # docker.io/hashicorp/${{env.repo}}:${{env.version}} + # 986891699432.dkr.ecr.us-east-1.amazonaws.com/hashicorp/${{env.repo}}:${{env.version}} diff --git a/.github/workflows/generate-static-assets.yml b/.github/workflows/generate-static-assets.yml new file mode 100644 index 000000000..4bedd7b7b --- /dev/null +++ b/.github/workflows/generate-static-assets.yml @@ -0,0 +1,68 @@ +name: Generate Static Assets + +on: + push: + branches: + - "release/**" +env: + GO_TAGS: "release" + +jobs: + get-go-version: + runs-on: ubuntu-latest + outputs: + go-version: ${{ steps.get-go-version.outputs.go-version }} + steps: + - uses: actions/checkout@v2 + - name: Determine Go version + id: get-go-version + # We use .go-version as our source of truth for current Go + # version, because "goenv" can react to it automatically. + run: | + echo "Building with Go $(cat .go-version)" + echo "::set-output name=go-version::$(cat .go-version)" + generate-metadata: + runs-on: ubuntu-latest + needs: get-go-version + name: generate-metadata + steps: + - uses: actions/checkout@v2 + - name: Setup go + uses: actions/setup-go@v2 + with: + go-version: ${{ needs.get-go-version.outputs.go-version }} + + - name: Setup node and yarn + uses: actions/setup-node@v2 + with: + node-version: "14" + cache-dependency-path: "ui/yarn.lock" + - name: Install Yarn + run: | + npm install -g yarn + - uses: actions/checkout@v2 + - name: Generate static assets + id: generate-static-assets + run: | + make deps + make prerelease + - name: Commit and push changes + id: commit-change-push + run: | + git add -A . + find . -name '*.generated.go' -not -path './vendor/*' -exec git add -f '{}' \; + if ! git diff-index --quiet HEAD --; + then + git config --global user.email "github-team-nomad-core@hashicorp.com" + git config --global user.name "hc-github-team-nomad-core" + git commit --message "Generate files for release" + git push origin "$(git rev-parse --abbrev-ref HEAD)" + echo "committing generated files" + else + echo "no files were updated" + fi + - name: Invoke build workflow + uses: benc-uk/workflow-dispatch@4c044c1613fabbe5250deadc65452d54c4ad4fc7 + with: + workflow: build + token: ${{ secrets.ELEVATED_GITHUB_TOKEN}} diff --git a/.go-version b/.go-version new file mode 100644 index 000000000..3661bc037 --- /dev/null +++ b/.go-version @@ -0,0 +1 @@ +1.17.7 diff --git a/.release/ci.hcl b/.release/ci.hcl new file mode 100644 index 000000000..3e3309264 --- /dev/null +++ b/.release/ci.hcl @@ -0,0 +1,198 @@ +schema = "1" + +project "nomad" { + team = "nomad" + slack { + // #proj-nomad-releases + notification_channel = "CUYKT2A73" + } + github { + organization = "hashicorp" + repository = "nomad" + release_branches = ["main"] + } +} + +event "merge" { + // "entrypoint" to use if build is not run automatically + // i.e. send "merge" complete signal to orchestrator to trigger build +} + +event "build" { + depends = ["merge"] + action "build" { + organization = "hashicorp" + repository = "nomad" + workflow = "build" + } +} + +event "upload-dev" { + depends = ["build"] + action "upload-dev" { + organization = "hashicorp" + repository = "crt-workflows-common" + workflow = "upload-dev" + } + + notification { + on = "fail" + } +} + +event "security-scan-binaries" { + depends = ["upload-dev"] + action "security-scan-binaries" { + organization = "hashicorp" + repository = "crt-workflows-common" + workflow = "security-scan-binaries" + config = "security-scan.hcl" + } + + notification { + on = "fail" + } +} + +event "notarize-darwin-amd64" { + depends = ["security-scan-binaries"] + action "notarize-darwin-amd64" { + organization = "hashicorp" + repository = "crt-workflows-common" + workflow = "notarize-darwin-amd64" + } + + notification { + on = "fail" + } +} + +event "notarize-darwin-arm64" { + depends = ["notarize-darwin-amd64"] + action "notarize-darwin-arm64" { + organization = "hashicorp" + repository = "crt-workflows-common" + workflow = "notarize-darwin-arm64" + } + + notification { + on = "fail" + } +} + +event "notarize-windows-386" { + depends = ["notarize-darwin-arm64"] + action "notarize-windows-386" { + organization = "hashicorp" + repository = "crt-workflows-common" + workflow = "notarize-windows-386" + } + + notification { + on = "fail" + } +} + +event "notarize-windows-amd64" { + depends = ["notarize-windows-386"] + action "notarize-windows-amd64" { + organization = "hashicorp" + repository = "crt-workflows-common" + workflow = "notarize-windows-amd64" + } + + notification { + on = "fail" + } +} + +event "sign" { + depends = ["notarize-windows-amd64"] + action "sign" { + organization = "hashicorp" + repository = "crt-workflows-common" + workflow = "sign" + } + + notification { + on = "fail" + } +} + +event "sign-linux-rpms" { + depends = ["sign"] + action "sign-linux-rpms" { + organization = "hashicorp" + repository = "crt-workflows-common" + workflow = "sign-linux-rpms" + } + + notification { + on = "fail" + } +} + +event "verify" { + depends = ["sign-linux-rpms"] + action "verify" { + organization = "hashicorp" + repository = "crt-workflows-common" + workflow = "verify" + } + + notification { + on = "always" + } +} + +## These are promotion and post-publish events +## they should be added to the end of the file after the verify event stanza. + +event "trigger-staging" { + // This event is dispatched by the bob trigger-promotion command + // and is required - do not delete. +} + +event "promote-staging" { + depends = ["trigger-staging"] + action "promote-staging" { + organization = "hashicorp" + repository = "crt-workflows-common" + workflow = "promote-staging" + } + + notification { + on = "always" + } +} + +event "trigger-production" { + // This event is dispatched by the bob trigger-promotion command + // and is required - do not delete. +} + +event "promote-production" { + depends = ["trigger-production"] + action "promote-production" { + organization = "hashicorp" + repository = "crt-workflows-common" + workflow = "promote-production" + } + + notification { + on = "always" + } +} + +event "promote-production-packaging" { + depends = ["promote-production"] + action "promote-production-packaging" { + organization = "hashicorp" + repository = "crt-workflows-common" + workflow = "promote-production-packaging" + } + + notification { + on = "always" + } +} diff --git a/.release/linux/package/etc/nomad.d/nomad.env b/.release/linux/package/etc/nomad.d/nomad.env new file mode 100644 index 000000000..e69de29bb diff --git a/.release/linux/package/etc/nomad.d/nomad.hcl b/.release/linux/package/etc/nomad.d/nomad.hcl new file mode 100644 index 000000000..8b3204e96 --- /dev/null +++ b/.release/linux/package/etc/nomad.d/nomad.hcl @@ -0,0 +1,16 @@ +# Full configuration options can be found at https://www.nomadproject.io/docs/configuration + +data_dir = "/opt/nomad/data" +bind_addr = "0.0.0.0" + +server { + # license_path is required as of Nomad v1.1.1+ + #license_path = "/etc/nomad.d/nomad.hcl" + enabled = true + bootstrap_expect = 1 +} + +client { + enabled = true + servers = ["127.0.0.1"] +} diff --git a/.release/linux/package/etc/usr/lib/systemd/system/nomad.service b/.release/linux/package/etc/usr/lib/systemd/system/nomad.service new file mode 100644 index 000000000..93546f074 --- /dev/null +++ b/.release/linux/package/etc/usr/lib/systemd/system/nomad.service @@ -0,0 +1,43 @@ +[Unit] +Description=Nomad +Documentation=https://nomadproject.io/docs/ +Wants=network-online.target +After=network-online.target + +# When using Nomad with Consul it is not necessary to start Consul first. These +# lines start Consul before Nomad as an optimization to avoid Nomad logging +# that Consul is unavailable at startup. +#Wants=consul.service +#After=consul.service + +[Service] +EnvironmentFile=-/etc/nomad.d/nomad.env +ExecReload=/bin/kill -HUP $MAINPID +ExecStart=/usr/bin/nomad agent -config /etc/nomad.d +KillMode=process +KillSignal=SIGINT +LimitNOFILE=65536 +LimitNPROC=infinity +Restart=on-failure +RestartSec=2 + +## Configure unit start rate limiting. Units which are started more than +## *burst* times within an *interval* time span are not permitted to start any +## more. Use `StartLimitIntervalSec` or `StartLimitInterval` (depending on +## systemd version) to configure the checking interval and `StartLimitBurst` +## to configure how many starts per interval are allowed. The values in the +## commented lines are defaults. + +# StartLimitBurst = 5 + +## StartLimitIntervalSec is used for systemd versions >= 230 +# StartLimitIntervalSec = 10s + +## StartLimitInterval is used for systemd versions < 230 +# StartLimitInterval = 10s + +TasksMax=infinity +OOMScoreAdjust=-1000 + +[Install] +WantedBy=multi-user.target diff --git a/.release/linux/postinst b/.release/linux/postinst new file mode 100644 index 000000000..c3b96e7b7 --- /dev/null +++ b/.release/linux/postinst @@ -0,0 +1,16 @@ +#!/bin/bash + +mkdir -p /opt/nomad/data +chown nomad:nomad /opt/nomad/data +chown -R nomad:nomad /etc/nomad.d + +if [ -d /run/systemd/system ]; then + systemctl --system daemon-reload >/dev/null || true +fi + +if [[ $(nomad version) == *+ent* ]]; then + echo " +The following shall apply unless your organization has a separately signed Enterprise License Agreement or Evaluation Agreement governing your use of the software: +Software in this repository is subject to the license terms located in the software, copies of which are also available at https://eula.hashicorp.com/ClickThruELA-Global.pdf or https://www.hashicorp.com/terms-of-evaluation as applicable. Please read the license terms prior to using the software. Your installation and use of the software constitutes your acceptance of these terms. If you do not accept the terms, do not use the software. +" +fi diff --git a/.release/linux/postrm b/.release/linux/postrm new file mode 100644 index 000000000..8fa5dcffb --- /dev/null +++ b/.release/linux/postrm @@ -0,0 +1,7 @@ +#!/bin/bash + +if [ "$1" = "purge" ]; then + userdel nomad +fi + +exit 0 diff --git a/.release/linux/preinst b/.release/linux/preinst new file mode 100644 index 000000000..68bd2dea0 --- /dev/null +++ b/.release/linux/preinst @@ -0,0 +1,13 @@ +#!/bin/bash + +set -eu + +USER="nomad" + +if ! id -u $USER >/dev/null 2>&1; then + useradd \ + --system \ + --user-group \ + --shell /bin/false \ + $USER +fi diff --git a/.release/security-scan.hcl b/.release/security-scan.hcl new file mode 100644 index 000000000..cfe18040a --- /dev/null +++ b/.release/security-scan.hcl @@ -0,0 +1,18 @@ +container { + secrets { + all = false + } + + dependencies = false + alpine_security = false +} + +binary { + go_modules = true + osv = false + nvd = false + + secrets { + all = true + } +} diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 000000000..fd8112e6f --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,4 @@ +# release configuration + +/.release/ @hashicorp/release-engineering +/.github/workflows/build.yml @hashicorp/release-engineering diff --git a/GNUmakefile b/GNUmakefile index e33b9015a..0396f5f21 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -67,7 +67,8 @@ ALL_TARGETS = linux_s390x endif ifeq (Darwin,$(THIS_OS)) -ALL_TARGETS = darwin_amd64 +ALL_TARGETS = darwin_amd64 \ + darwin_arm64 endif ifeq (FreeBSD,$(THIS_OS)) @@ -371,7 +372,7 @@ test-ui: ## Run Nomad UI test suite .PHONY: ember-dist ember-dist: ## Build the static UI assets from source @echo "--> Installing JavaScript assets" - @cd ui && yarn install --silent + @cd ui && yarn install --silent --network-timeout 300000 @cd ui && npm rebuild node-sass @echo "--> Building Ember application" @cd ui && npm run build @@ -408,3 +409,12 @@ ui-screenshots: ui-screenshots-local: @echo "==> Collecting UI screenshots (local)..." @cd scripts/screenshots/src && SCREENSHOTS_DIR="../screenshots" node index.js + +version: +ifneq (,$(wildcard version/version_ent.go)) + @$(CURDIR)/scripts/version.sh version/version_ent.go +else + @$(CURDIR)/scripts/version.sh version/version.go +endif + +.PHONY: version diff --git a/scripts/version.sh b/scripts/version.sh new file mode 100755 index 000000000..9aed32ef4 --- /dev/null +++ b/scripts/version.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +version_file=$1 +version=$(awk '$1 == "Version" && $2 == "=" { gsub(/"/, "", $3); print $3 }' <"${version_file}") +prerelease=$(awk '$1 == "VersionPrerelease" && $2 == "=" { gsub(/"/, "", $3); print $3 }' <"${version_file}") + +if [ -n "$prerelease" ]; then + echo "${version}-${prerelease}" +else + echo "${version}" +fi