From f5c2e4813cef603032b54a16b69aeb3b976b1edc Mon Sep 17 00:00:00 2001 From: Pietro Abate Date: Mon, 16 Sep 2024 10:45:45 +0200 Subject: [PATCH 1/4] homebrew: push homebrew formula to an external repository - fix the formula to add a missing dependency - install and use gsutils from a script - minor refactoring --- .gitlab/ci/pipelines/before_merging.yml | 13 +- .../ci/pipelines/debian_repository_full.yml | 12 +- .../pipelines/debian_repository_partial.yml | 6 +- .gitlab/ci/pipelines/merge_train.yml | 13 +- .gitlab/ci/pipelines/non_release_tag.yml | 35 +- .gitlab/ci/pipelines/non_release_tag_test.yml | 35 +- .../ci/pipelines/octez_beta_release_tag.yml | 35 +- .gitlab/ci/pipelines/octez_release_tag.yml | 35 +- .../ci/pipelines/octez_release_tag_test.yml | 35 +- ci/bin/common.ml | 18 +- ci/bin/debian_repository.ml | 4 +- ci/bin/release_tag.ml | 26 + ...{prepare-apt-repo.sh => install-gsutil.sh} | 4 +- scripts/packaging/Formula/octez.rb.template | 8 +- scripts/packaging/homebrew_release.sh | 95 ++ .../octez/homebrew/Formula/octez.rb.template | 76 ++ .../octez/homebrew/homebrew_install.sh | 984 ++++++++++++++++++ .../octez/homebrew/homebrew_release.sh | 99 ++ 18 files changed, 1473 insertions(+), 60 deletions(-) rename scripts/ci/{prepare-apt-repo.sh => install-gsutil.sh} (84%) create mode 100755 scripts/packaging/homebrew_release.sh create mode 100644 scripts/packaging/octez/homebrew/Formula/octez.rb.template create mode 100755 scripts/packaging/octez/homebrew/homebrew_install.sh create mode 100755 scripts/packaging/octez/homebrew/homebrew_release.sh diff --git a/.gitlab/ci/pipelines/before_merging.yml b/.gitlab/ci/pipelines/before_merging.yml index 548462500cb7..4eff2cdd0a79 100644 --- a/.gitlab/ci/pipelines/before_merging.yml +++ b/.gitlab/ci/pipelines/before_merging.yml @@ -4812,17 +4812,14 @@ oc.build:homebrew: dependencies: [] timeout: 60 minutes before_script: - - apt update && apt install -y curl git build-essential + - ./scripts/ci/install-gsutil.sh + - apt install -y git build-essential - ./scripts/packaging/homebrew_install.sh - - eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" - - eval $(scripts/active_protocols.sh) - - sed "s|%%VERSION%%|0.0.0-dev| ; s|%%CI_MERGE_REQUEST_SOURCE_PROJECT_URL%%|$CI_MERGE_REQUEST_SOURCE_PROJECT_URL|; - s|%%CI_COMMIT_REF_NAME%%|$CI_COMMIT_REF_NAME|; s|%%CI_PROJECT_NAMESPACE%%|$CI_PROJECT_NAMESPACE|; - s|%%PROTO_CURRENT%%|$PROTO_CURRENT|; s|%%PROTO_NEXT%%|$PROTO_NEXT|" scripts/packaging/Formula/octez.rb.template - > scripts/packaging/Formula/octez.rb + - eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv) + - ./scripts/packaging/homebrew_release.sh script: - apt install -y autoconf cmake libev-dev libffi-dev libgmp-dev libprotobuf-dev - libsqlite3-dev postgresql-dev protobuf-compiler libhidapi-dev pkg-config zlib1g-dev + libsqlite3-dev protobuf-compiler libhidapi-dev pkg-config zlib1g-dev libpq-dev - brew install -v scripts/packaging/Formula/octez.rb variables: CARGO_NET_OFFLINE: "false" diff --git a/.gitlab/ci/pipelines/debian_repository_full.yml b/.gitlab/ci/pipelines/debian_repository_full.yml index 3b0ff2728853..489b2e582ef6 100644 --- a/.gitlab/ci/pipelines/debian_repository_full.yml +++ b/.gitlab/ci/pipelines/debian_repository_full.yml @@ -224,7 +224,8 @@ apt_repo_debian_current: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh debian bookworm variables: @@ -245,7 +246,8 @@ apt_repo_debian: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh debian bookworm variables: @@ -426,7 +428,8 @@ apt_repo_ubuntu_current: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh ubuntu noble jammy variables: @@ -447,7 +450,8 @@ apt_repo_ubuntu: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh ubuntu noble jammy variables: diff --git a/.gitlab/ci/pipelines/debian_repository_partial.yml b/.gitlab/ci/pipelines/debian_repository_partial.yml index a1f4e6107f98..94aa77758a84 100644 --- a/.gitlab/ci/pipelines/debian_repository_partial.yml +++ b/.gitlab/ci/pipelines/debian_repository_partial.yml @@ -216,7 +216,8 @@ apt_repo_debian_current: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh debian bookworm variables: @@ -237,7 +238,8 @@ apt_repo_debian: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh debian bookworm variables: diff --git a/.gitlab/ci/pipelines/merge_train.yml b/.gitlab/ci/pipelines/merge_train.yml index 55a689c99469..3a948a560666 100644 --- a/.gitlab/ci/pipelines/merge_train.yml +++ b/.gitlab/ci/pipelines/merge_train.yml @@ -4794,17 +4794,14 @@ oc.build:homebrew: dependencies: [] timeout: 60 minutes before_script: - - apt update && apt install -y curl git build-essential + - ./scripts/ci/install-gsutil.sh + - apt install -y git build-essential - ./scripts/packaging/homebrew_install.sh - - eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" - - eval $(scripts/active_protocols.sh) - - sed "s|%%VERSION%%|0.0.0-dev| ; s|%%CI_MERGE_REQUEST_SOURCE_PROJECT_URL%%|$CI_MERGE_REQUEST_SOURCE_PROJECT_URL|; - s|%%CI_COMMIT_REF_NAME%%|$CI_COMMIT_REF_NAME|; s|%%CI_PROJECT_NAMESPACE%%|$CI_PROJECT_NAMESPACE|; - s|%%PROTO_CURRENT%%|$PROTO_CURRENT|; s|%%PROTO_NEXT%%|$PROTO_NEXT|" scripts/packaging/Formula/octez.rb.template - > scripts/packaging/Formula/octez.rb + - eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv) + - ./scripts/packaging/homebrew_release.sh script: - apt install -y autoconf cmake libev-dev libffi-dev libgmp-dev libprotobuf-dev - libsqlite3-dev postgresql-dev protobuf-compiler libhidapi-dev pkg-config zlib1g-dev + libsqlite3-dev protobuf-compiler libhidapi-dev pkg-config zlib1g-dev libpq-dev - brew install -v scripts/packaging/Formula/octez.rb variables: CARGO_NET_OFFLINE: "false" diff --git a/.gitlab/ci/pipelines/non_release_tag.yml b/.gitlab/ci/pipelines/non_release_tag.yml index ede448d7eb1f..10ea5a810d70 100644 --- a/.gitlab/ci/pipelines/non_release_tag.yml +++ b/.gitlab/ci/pipelines/non_release_tag.yml @@ -238,6 +238,27 @@ oc.build:rpm:amd64: - fedora:39 - rockylinux:9.3 +homebrew release: + image: debian:bookworm + stage: build + tags: + - gcp + needs: [] + dependencies: [] + timeout: 60 minutes + script: + - ./scripts/ci/install-gsutil.sh + - apt install -y git build-essential + - ./scripts/packaging/homebrew_install.sh + - eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv) + - ./scripts/packaging/homebrew_release.sh + artifacts: + name: build-$CI_COMMIT_REF_SLUG + expire_in: 1 day + paths: + - scripts/packaging/Formula/octez.rb + when: on_success + docker:merge_manifests: image: ${GCP_REGISTRY}/tezos/docker-images/ci-docker:v1.12.0 stage: prepare_release @@ -266,6 +287,7 @@ gitlab:publish: needs: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries + - homebrew release - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a @@ -274,6 +296,7 @@ gitlab:publish: dependencies: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries + - homebrew release - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a @@ -479,7 +502,8 @@ apt_repo_debian_current: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh debian bookworm variables: @@ -500,7 +524,8 @@ apt_repo_debian: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh debian bookworm variables: @@ -681,7 +706,8 @@ apt_repo_ubuntu_current: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh ubuntu noble jammy variables: @@ -702,7 +728,8 @@ apt_repo_ubuntu: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh ubuntu noble jammy variables: diff --git a/.gitlab/ci/pipelines/non_release_tag_test.yml b/.gitlab/ci/pipelines/non_release_tag_test.yml index 496006f5a400..87af76978833 100644 --- a/.gitlab/ci/pipelines/non_release_tag_test.yml +++ b/.gitlab/ci/pipelines/non_release_tag_test.yml @@ -238,6 +238,27 @@ oc.build:rpm:amd64: - fedora:39 - rockylinux:9.3 +homebrew release: + image: debian:bookworm + stage: build + tags: + - gcp + needs: [] + dependencies: [] + timeout: 60 minutes + script: + - ./scripts/ci/install-gsutil.sh + - apt install -y git build-essential + - ./scripts/packaging/homebrew_install.sh + - eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv) + - ./scripts/packaging/homebrew_release.sh + artifacts: + name: build-$CI_COMMIT_REF_SLUG + expire_in: 1 day + paths: + - scripts/packaging/Formula/octez.rb + when: on_success + docker:merge_manifests: image: ${GCP_REGISTRY}/tezos/docker-images/ci-docker:v1.12.0 stage: prepare_release @@ -266,6 +287,7 @@ gitlab:publish: needs: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries + - homebrew release - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a @@ -274,6 +296,7 @@ gitlab:publish: dependencies: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries + - homebrew release - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a @@ -479,7 +502,8 @@ apt_repo_debian_current: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh debian bookworm variables: @@ -500,7 +524,8 @@ apt_repo_debian: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh debian bookworm variables: @@ -681,7 +706,8 @@ apt_repo_ubuntu_current: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh ubuntu noble jammy variables: @@ -702,7 +728,8 @@ apt_repo_ubuntu: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh ubuntu noble jammy variables: diff --git a/.gitlab/ci/pipelines/octez_beta_release_tag.yml b/.gitlab/ci/pipelines/octez_beta_release_tag.yml index f76045c87163..d72b9446305b 100644 --- a/.gitlab/ci/pipelines/octez_beta_release_tag.yml +++ b/.gitlab/ci/pipelines/octez_beta_release_tag.yml @@ -238,6 +238,27 @@ oc.build:rpm:amd64: - fedora:39 - rockylinux:9.3 +homebrew release: + image: debian:bookworm + stage: build + tags: + - gcp + needs: [] + dependencies: [] + timeout: 60 minutes + script: + - ./scripts/ci/install-gsutil.sh + - apt install -y git build-essential + - ./scripts/packaging/homebrew_install.sh + - eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv) + - ./scripts/packaging/homebrew_release.sh + artifacts: + name: build-$CI_COMMIT_REF_SLUG + expire_in: 1 day + paths: + - scripts/packaging/Formula/octez.rb + when: on_success + docker:merge_manifests: image: ${GCP_REGISTRY}/tezos/docker-images/ci-docker:v1.12.0 stage: prepare_release @@ -266,6 +287,7 @@ gitlab:release: needs: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries + - homebrew release - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a @@ -274,6 +296,7 @@ gitlab:release: dependencies: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries + - homebrew release - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a @@ -480,7 +503,8 @@ apt_repo_debian_current: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh debian bookworm variables: @@ -501,7 +525,8 @@ apt_repo_debian: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh debian bookworm variables: @@ -682,7 +707,8 @@ apt_repo_ubuntu_current: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh ubuntu noble jammy variables: @@ -703,7 +729,8 @@ apt_repo_ubuntu: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh ubuntu noble jammy variables: diff --git a/.gitlab/ci/pipelines/octez_release_tag.yml b/.gitlab/ci/pipelines/octez_release_tag.yml index 41ba6567acb5..b674d5d974b6 100644 --- a/.gitlab/ci/pipelines/octez_release_tag.yml +++ b/.gitlab/ci/pipelines/octez_release_tag.yml @@ -239,6 +239,27 @@ oc.build:rpm:amd64: - fedora:39 - rockylinux:9.3 +homebrew release: + image: debian:bookworm + stage: build + tags: + - gcp + needs: [] + dependencies: [] + timeout: 60 minutes + script: + - ./scripts/ci/install-gsutil.sh + - apt install -y git build-essential + - ./scripts/packaging/homebrew_install.sh + - eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv) + - ./scripts/packaging/homebrew_release.sh + artifacts: + name: build-$CI_COMMIT_REF_SLUG + expire_in: 1 day + paths: + - scripts/packaging/Formula/octez.rb + when: on_success + docker:merge_manifests: image: ${GCP_REGISTRY}/tezos/docker-images/ci-docker:v1.12.0 stage: prepare_release @@ -267,6 +288,7 @@ gitlab:release: needs: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries + - homebrew release - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a @@ -275,6 +297,7 @@ gitlab:release: dependencies: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries + - homebrew release - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a @@ -481,7 +504,8 @@ apt_repo_debian_current: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh debian bookworm variables: @@ -502,7 +526,8 @@ apt_repo_debian: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh debian bookworm variables: @@ -683,7 +708,8 @@ apt_repo_ubuntu_current: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh ubuntu noble jammy variables: @@ -704,7 +730,8 @@ apt_repo_ubuntu: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh ubuntu noble jammy variables: diff --git a/.gitlab/ci/pipelines/octez_release_tag_test.yml b/.gitlab/ci/pipelines/octez_release_tag_test.yml index f4dfdcea4ecc..94e478fefcd8 100644 --- a/.gitlab/ci/pipelines/octez_release_tag_test.yml +++ b/.gitlab/ci/pipelines/octez_release_tag_test.yml @@ -239,6 +239,27 @@ oc.build:rpm:amd64: - fedora:39 - rockylinux:9.3 +homebrew release: + image: debian:bookworm + stage: build + tags: + - gcp + needs: [] + dependencies: [] + timeout: 60 minutes + script: + - ./scripts/ci/install-gsutil.sh + - apt install -y git build-essential + - ./scripts/packaging/homebrew_install.sh + - eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv) + - ./scripts/packaging/homebrew_release.sh + artifacts: + name: build-$CI_COMMIT_REF_SLUG + expire_in: 1 day + paths: + - scripts/packaging/Formula/octez.rb + when: on_success + docker:merge_manifests: image: ${GCP_REGISTRY}/tezos/docker-images/ci-docker:v1.12.0 stage: prepare_release @@ -267,6 +288,7 @@ gitlab:release: needs: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries + - homebrew release - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a @@ -275,6 +297,7 @@ gitlab:release: dependencies: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries + - homebrew release - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a @@ -481,7 +504,8 @@ apt_repo_debian_current: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh debian bookworm variables: @@ -502,7 +526,8 @@ apt_repo_debian: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh debian bookworm variables: @@ -683,7 +708,8 @@ apt_repo_ubuntu_current: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh ubuntu noble jammy variables: @@ -704,7 +730,8 @@ apt_repo_ubuntu: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh ubuntu noble jammy variables: diff --git a/ci/bin/common.ml b/ci/bin/common.ml index 0dfdea5c01fa..05e2f44d6d86 100644 --- a/ci/bin/common.ml +++ b/ci/bin/common.ml @@ -1119,24 +1119,18 @@ let job_build_homebrew ?rules ~__POS__ ~name ?(stage = Stages.build) ~stage ~before_script: [ - "apt update && apt install -y curl git build-essential"; + "./scripts/ci/install-gsutil.sh"; + "apt install -y git build-essential"; "./scripts/packaging/homebrew_install.sh"; - "eval \"$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)\""; - "eval $(scripts/active_protocols.sh)"; - "sed \"s|%%VERSION%%|0.0.0-dev| ; \ - s|%%CI_MERGE_REQUEST_SOURCE_PROJECT_URL%%|$CI_MERGE_REQUEST_SOURCE_PROJECT_URL|; \ - s|%%CI_COMMIT_REF_NAME%%|$CI_COMMIT_REF_NAME|; \ - s|%%CI_PROJECT_NAMESPACE%%|$CI_PROJECT_NAMESPACE|; \ - s|%%PROTO_CURRENT%%|$PROTO_CURRENT|; s|%%PROTO_NEXT%%|$PROTO_NEXT|\" \ - scripts/packaging/Formula/octez.rb.template > \ - scripts/packaging/Formula/octez.rb"; + "eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"; + "./scripts/packaging/homebrew_release.sh"; ] [ (* These packages are needed on Linux. For macOS, Homebrew will make those available locally. *) "apt install -y autoconf cmake libev-dev libffi-dev libgmp-dev \ - libprotobuf-dev libsqlite3-dev postgresql-dev protobuf-compiler \ - libhidapi-dev pkg-config zlib1g-dev"; + libprotobuf-dev libsqlite3-dev protobuf-compiler libhidapi-dev \ + pkg-config zlib1g-dev libpq-dev"; "brew install -v scripts/packaging/Formula/octez.rb"; ] |> enable_networked_cargo diff --git a/ci/bin/debian_repository.ml b/ci/bin/debian_repository.ml index 53453daded31..8d93f916e473 100644 --- a/ci/bin/debian_repository.ml +++ b/ci/bin/debian_repository.ml @@ -67,7 +67,9 @@ let make_job_apt_repo ?rules ~__POS__ ~name ?(stage = Stages.publishing) ~name ~image ~before_script: - (before_script ~source_version:true ["./scripts/ci/prepare-apt-repo.sh"]) + (before_script + ~source_version:true + ["./scripts/ci/install-gsutil.sh"; "apt install -y apt-utils debsigs"]) ~variables script diff --git a/ci/bin/release_tag.ml b/ci/bin/release_tag.ml index d379049115c5..33e8cf72cf10 100644 --- a/ci/bin/release_tag.ml +++ b/ci/bin/release_tag.ml @@ -93,6 +93,30 @@ let octez_jobs ?(test = false) release_tag_pipeline_type = ~release:true () in + let job_build_homebrew_release = + let artifacts = + Gitlab_ci.Util.artifacts + ~expire_in:(Duration (Days 1)) + ~name:"build-$CI_COMMIT_REF_SLUG" + ~when_:On_success + ["scripts/packaging/Formula/octez.rb"] + in + job + ~__POS__ + ~name:"homebrew release" + ~arch:Amd64 + ~dependencies:(Dependent []) + ~image:Images.debian_bookworm + ~stage:Stages.build + ~artifacts + [ + "./scripts/ci/install-gsutil.sh"; + "apt install -y git build-essential"; + "./scripts/packaging/homebrew_install.sh"; + "eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"; + "./scripts/packaging/homebrew_release.sh"; + ] + in let job_gitlab_release ~dependencies : Tezos_ci.tezos_job = job ~__POS__ @@ -144,6 +168,7 @@ let octez_jobs ?(test = false) release_tag_pipeline_type = [ Artifacts job_static_x86_64_release; Artifacts job_static_arm64_release; + Artifacts job_build_homebrew_release; Artifacts job_build_rpm_amd64; Artifacts job_build_ubuntu_package_current_a; Artifacts job_build_debian_package_current_a; @@ -180,6 +205,7 @@ let octez_jobs ?(test = false) release_tag_pipeline_type = job_docker_amd64; job_docker_arm64; job_build_rpm_amd64; + job_build_homebrew_release; job_docker_merge; job_gitlab_release_or_publish; ] diff --git a/scripts/ci/prepare-apt-repo.sh b/scripts/ci/install-gsutil.sh similarity index 84% rename from scripts/ci/prepare-apt-repo.sh rename to scripts/ci/install-gsutil.sh index e0dd56b45d1b..4dbd0e3dfc4a 100755 --- a/scripts/ci/prepare-apt-repo.sh +++ b/scripts/ci/install-gsutil.sh @@ -1,11 +1,11 @@ #!/bin/sh -# Install depedendencies for the apt_repo job +# Install depedendencies to use gsutils export DEBIAN_FRONTEND=noninteractive apt-get update -apt-get install -y apt-utils debsigs gnupg curl +apt-get install -y gnupg curl # Install google-cloud-cli so we can upload packages to the Google Cloud Storage bucket. gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg \ diff --git a/scripts/packaging/Formula/octez.rb.template b/scripts/packaging/Formula/octez.rb.template index bab7c49f0143..2280af888e10 100644 --- a/scripts/packaging/Formula/octez.rb.template +++ b/scripts/packaging/Formula/octez.rb.template @@ -15,12 +15,12 @@ class Octez < Formula version "%%VERSION%%" license "MIT" - build_dependencies = %w[pkg-config coreutils autoconf rsync wget opam protobuf rustup-init cmake] + build_dependencies = %w[pkg-config coreutils autoconf rsync wget opam protobuf cmake] build_dependencies.each do |dependency| depends_on dependency => :build end - dependencies = %w[gmp hidapi libev libffi] + dependencies = %w[gmp hidapi libev libffi libpq] dependencies.each do |dependency| depends_on dependency end @@ -40,7 +40,9 @@ class Octez < Formula set +x . ./scripts/version.sh - rustup-init --profile minimal --default-toolchain $recommended_rust_version -y + wget https://sh.rustup.rs/rustup-init.sh + chmod +x rustup-init.sh + ./rustup-init.sh --profile minimal --default-toolchain $recommended_rust_version -y opam init --bare --disable-sandboxing . $CARGO_HOME/env diff --git a/scripts/packaging/homebrew_release.sh b/scripts/packaging/homebrew_release.sh new file mode 100755 index 000000000000..3caaf9f35ccd --- /dev/null +++ b/scripts/packaging/homebrew_release.sh @@ -0,0 +1,95 @@ +#!/bin/sh +# + +# This script assume that homebrew is correctly installed +# using the script ./scripts/packaging/homebrew_install.sh +# and creates a formula scripts/packaging/Formula/octez.rb +# that is ready to be installed with brew + +# If it's a protected branch the value of $bucket will +# be set accordingly but the CI. +BUCKET="$GCP_LINUX_PACKAGES_BUCKET" + +# set version + +. scripts/version.sh +. scripts/ci/octez-release.sh + +# fetch tags for releases +git fetch -q --tags + +if [ -n "${gitlab_release_no_v:-}" ]; then + VERSION=$gitlab_release_no_v +elif [ -n "$CI_COMMIT_TAG" ]; then + VERSION=$(date +'%Y%m%d%H%M')+$CI_COMMIT_TAG +else + VERSION=$(date +'%Y%m%d%H%M')+$CI_COMMIT_SHORT_SHA +fi + +# prepare target dir + +# if it's a release tag, then it can be a RC release or a final release +if [ -n "${gitlab_release_no_v:-}" ]; then + # It a release tag, this can be either a real or test release + if [ -n "${gitlab_release_rc_version}" ]; then + # Release candidate + TARGETDIR="public/homebrew/RC/Formula" + else + # Release + TARGETDIR="public/homebrew/Formula" + fi +else + if [ "$CI_COMMIT_REF_PROTECTED" = "false" ]; then + if [ "$CI_COMMIT_REF_NAME" = "RC" ]; then + echo "Cannot create a repository for a branch named 'RC'" + exit 1 + else + # Branch is not protected, this is for testing ordinary MRs + TARGETDIR="public/homebrew/$CI_COMMIT_REF_NAME/Formula" + fi + else + # For protected branches that are not release, we allow + # a repository only for master. + if [ "$CI_COMMIT_REF_NAME" = "master" ]; then + TARGETDIR="public/homebrew/master/Formula" + else + if [ -n "${CI_COMMIT_TAG}" ]; then + TARGETDIR="public/homebrew/${CI_COMMIT_TAG}/Formula" + else + echo "Cannot create a repository for a protected branch that is not associated to a tag or master" + exit 1 + fi + fi + fi +fi + +# prepare formula + +mkdir -p "$TARGETDIR" + +#shellcheck disable=SC2046 +eval $(scripts/active_protocols.sh) +sed "s|%%VERSION%%|$VERSION|; \ + s|%%CI_MERGE_REQUEST_SOURCE_PROJECT_URL%%|$CI_MERGE_REQUEST_SOURCE_PROJECT_URL|; \ + s|%%CI_COMMIT_REF_NAME%%|$CI_COMMIT_REF_NAME|; \ + s|%%CI_PROJECT_NAMESPACE%%|$CI_PROJECT_NAMESPACE|; \ + s|%%PROTO_CURRENT%%|$PROTO_CURRENT|; s|%%PROTO_NEXT%%|$PROTO_NEXT|" \ + scripts/packaging/Formula/octez.rb.template > "$TARGETDIR/octez.rb" + +# upload to bucket + +if [ "$CI_COMMIT_REF_PROTECTED" = "true" ]; then + echo "### Logging into protected repo ..." + echo "${GCP_PROTECTED_SERVICE_ACCOUNT}" | base64 -d > protected_sa.json + gcloud auth activate-service-account --key-file=protected_sa.json +else + echo "### Logging into standard repo ..." + # Nothing to do +fi + +GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token) +export GOOGLE_OAUTH_ACCESS_TOKEN + +echo "Push to $BUCKET" + +gsutil -m cp -r public/* gs://"${BUCKET}" diff --git a/scripts/packaging/octez/homebrew/Formula/octez.rb.template b/scripts/packaging/octez/homebrew/Formula/octez.rb.template new file mode 100644 index 000000000000..2280af888e10 --- /dev/null +++ b/scripts/packaging/octez/homebrew/Formula/octez.rb.template @@ -0,0 +1,76 @@ +# +# SPDX-License-Identifier: MIT +# SPDX-FileCopyrightText: 2024 Nomadic Labs +# + +# This is a Homebrew formula for installing Octez. +class Octez < Formula + @all_bins = [] + + class << self + attr_accessor :all_bins + end + homepage "https://gitlab.com/tezos/tezos" + url "%%CI_MERGE_REQUEST_SOURCE_PROJECT_URL%%.git", :tag => "%%CI_COMMIT_REF_NAME%%", :shallow => false + version "%%VERSION%%" + license "MIT" + + build_dependencies = %w[pkg-config coreutils autoconf rsync wget opam protobuf cmake] + build_dependencies.each do |dependency| + depends_on dependency => :build + end + + dependencies = %w[gmp hidapi libev libffi libpq] + dependencies.each do |dependency| + depends_on dependency + end + + def make_deps + ENV.deparallelize + ENV["CARGO_HOME"]="./.cargo" + ENV["OPAMROOT"]="./.opam" + ENV["OPAMYES"]="true" + ENV["BLST_PORTABLE"]="yes" + ENV["LDFLAGS"] = "-L#{HOMEBREW_PREFIX}/lib" + + + (buildpath/"script.sh").write <<~EOS + #!/bin/sh + + set +x + + . ./scripts/version.sh + wget https://sh.rustup.rs/rustup-init.sh + chmod +x rustup-init.sh + ./rustup-init.sh --profile minimal --default-toolchain $recommended_rust_version -y + opam init --bare --disable-sandboxing + + . $CARGO_HOME/env + make build-deps + + eval $(opam env) + make release + EOS + + chmod 0755, buildpath/"script.sh" + system "./script.sh" + end + + def install_template(name) + bin.mkpath + self.class.all_bins << name + bin.install name + end + + def install + make_deps + install_template "octez-node" + install_template "octez-client" + install_template "octez-signer" + install_template "octez-accuser-%%PROTO_CURRENT%%" + install_template "octez-baker-%%PROTO_CURRENT%%" + install_template "octez-accuser-%%PROTO_NEXT%%" + install_template "octez-baker-%%PROTO_NEXT%%" + end + +end diff --git a/scripts/packaging/octez/homebrew/homebrew_install.sh b/scripts/packaging/octez/homebrew/homebrew_install.sh new file mode 100755 index 000000000000..876a290a7003 --- /dev/null +++ b/scripts/packaging/octez/homebrew/homebrew_install.sh @@ -0,0 +1,984 @@ +#!/bin/bash + +# +# SPDX-License-Identifier: BSD 2-Clause License +# SPDX-FileCopyrightText: Copyright (c) 2009-present, Homebrew contributors +# + +# We don't need return codes for "$(command)", only stdout is needed. +# Allow `[[ -n "$(command)" ]]`, `func "$(command)"`, pipes, etc. +# shellcheck disable=SC2312 + +set -u + +abort() { + printf "%s\n" "$@" >&2 + exit 1 +} + +# Fail fast with a concise message when not using bash +# Single brackets are needed here for POSIX compatibility +# shellcheck disable=SC2292 +if [ -z "${BASH_VERSION:-}" ]; then + abort "Bash is required to interpret this script." +fi + +# Check if script is run with force-interactive mode in CI +if [[ -n "${CI-}" && -n "${INTERACTIVE-}" ]]; then + abort "Cannot run force-interactive mode in CI." +fi + +# Check if both `INTERACTIVE` and `NONINTERACTIVE` are set +# Always use single-quoted strings with `exp` expressions +# shellcheck disable=SC2016 +if [[ -n "${INTERACTIVE-}" && -n "${NONINTERACTIVE-}" ]]; then + abort 'Both `$INTERACTIVE` and `$NONINTERACTIVE` are set. Please unset at least one variable and try again.' +fi + +# Check if script is run in POSIX mode +if [[ -n "${POSIXLY_CORRECT+1}" ]]; then + abort 'Bash must not run in POSIX mode. Please unset POSIXLY_CORRECT and try again.' +fi + +usage() { + cat << EOS +Homebrew Installer +Usage: [NONINTERACTIVE=1] [CI=1] install.sh [options] + -h, --help Display this message. + NONINTERACTIVE Install without prompting for user input + CI Install in CI mode (e.g. do not prompt for user input) +EOS + exit "${1:-0}" +} + +while [[ $# -gt 0 ]]; do + case "$1" in + -h | --help) usage ;; + *) + warn "Unrecognized option: '$1'" + usage 1 + ;; + esac +done + +# string formatters +if [[ -t 1 ]]; then + tty_escape() { printf "\033[%sm" "$1"; } +else + tty_escape() { :; } +fi +tty_mkbold() { tty_escape "1;$1"; } +tty_underline="$(tty_escape "4;39")" +tty_blue="$(tty_mkbold 34)" +tty_red="$(tty_mkbold 31)" +tty_bold="$(tty_mkbold 39)" +tty_reset="$(tty_escape 0)" + +shell_join() { + local arg + printf "%s" "$1" + shift + for arg in "$@"; do + printf " " + printf "%s" "${arg// /\ }" + done +} + +chomp() { + printf "%s" "${1/"$'\n'"/}" +} + +ohai() { + printf "${tty_blue}==>${tty_bold} %s${tty_reset}\n" "$(shell_join "$@")" +} + +warn() { + printf "${tty_red}Warning${tty_reset}: %s\n" "$(chomp "$1")" >&2 +} + +# Check if script is run non-interactively (e.g. CI) +# If it is run non-interactively we should not prompt for passwords. +# Always use single-quoted strings with `exp` expressions +# shellcheck disable=SC2016 +if [[ -z "${NONINTERACTIVE-}" ]]; then + if [[ -n "${CI-}" ]]; then + warn 'Running in non-interactive mode because `$CI` is set.' + NONINTERACTIVE=1 + elif [[ ! -t 0 ]]; then + if [[ -z "${INTERACTIVE-}" ]]; then + warn 'Running in non-interactive mode because `stdin` is not a TTY.' + NONINTERACTIVE=1 + else + warn 'Running in interactive mode despite `stdin` not being a TTY because `$INTERACTIVE` is set.' + fi + fi +else + ohai 'Running in non-interactive mode because `$NONINTERACTIVE` is set.' +fi + +# USER isn't always set so provide a fall back for the installer and subprocesses. +if [[ -z "${USER-}" ]]; then + USER="$(chomp "$(id -un)")" + export USER +fi + +# First check OS. +OS="$(uname)" +if [[ "${OS}" == "Linux" ]]; then + HOMEBREW_ON_LINUX=1 +elif [[ "${OS}" == "Darwin" ]]; then + HOMEBREW_ON_MACOS=1 +else + abort "Homebrew is only supported on macOS and Linux." +fi + +# Required installation paths. To install elsewhere (which is unsupported) +# you can untar https://github.com/Homebrew/brew/tarball/master +# anywhere you like. +if [[ -n "${HOMEBREW_ON_MACOS-}" ]]; then + UNAME_MACHINE="$(/usr/bin/uname -m)" + + if [[ "${UNAME_MACHINE}" == "arm64" ]]; then + # On ARM macOS, this script installs to /opt/homebrew only + HOMEBREW_PREFIX="/opt/homebrew" + HOMEBREW_REPOSITORY="${HOMEBREW_PREFIX}" + else + # On Intel macOS, this script installs to /usr/local only + HOMEBREW_PREFIX="/usr/local" + HOMEBREW_REPOSITORY="${HOMEBREW_PREFIX}/Homebrew" + fi + HOMEBREW_CACHE="${HOME}/Library/Caches/Homebrew" + + STAT_PRINTF=("stat" "-f") + PERMISSION_FORMAT="%A" + CHOWN=("/usr/sbin/chown") + CHGRP=("/usr/bin/chgrp") + GROUP="admin" + TOUCH=("/usr/bin/touch") + INSTALL=("/usr/bin/install" -d -o "root" -g "wheel" -m "0755") +else + UNAME_MACHINE="$(uname -m)" + + # On Linux, this script installs to /home/linuxbrew/.linuxbrew only + HOMEBREW_PREFIX="/home/linuxbrew/.linuxbrew" + HOMEBREW_REPOSITORY="${HOMEBREW_PREFIX}/Homebrew" + HOMEBREW_CACHE="${HOME}/.cache/Homebrew" + + STAT_PRINTF=("stat" "--printf") + PERMISSION_FORMAT="%a" + CHOWN=("/bin/chown") + CHGRP=("/bin/chgrp") + GROUP="$(id -gn)" + TOUCH=("/bin/touch") + INSTALL=("/usr/bin/install" -d -o "${USER}" -g "${GROUP}" -m "0755") +fi +CHMOD=("/bin/chmod") +MKDIR=("/bin/mkdir" "-p") +HOMEBREW_BREW_DEFAULT_GIT_REMOTE="https://github.com/Homebrew/brew" +HOMEBREW_CORE_DEFAULT_GIT_REMOTE="https://github.com/Homebrew/homebrew-core" + +# Use remote URLs of Homebrew repositories from environment if set. +HOMEBREW_BREW_GIT_REMOTE="${HOMEBREW_BREW_GIT_REMOTE:-"${HOMEBREW_BREW_DEFAULT_GIT_REMOTE}"}" +HOMEBREW_CORE_GIT_REMOTE="${HOMEBREW_CORE_GIT_REMOTE:-"${HOMEBREW_CORE_DEFAULT_GIT_REMOTE}"}" +# The URLs with and without the '.git' suffix are the same Git remote. Do not prompt. +if [[ "${HOMEBREW_BREW_GIT_REMOTE}" == "${HOMEBREW_BREW_DEFAULT_GIT_REMOTE}.git" ]]; then + HOMEBREW_BREW_GIT_REMOTE="${HOMEBREW_BREW_DEFAULT_GIT_REMOTE}" +fi +if [[ "${HOMEBREW_CORE_GIT_REMOTE}" == "${HOMEBREW_CORE_DEFAULT_GIT_REMOTE}.git" ]]; then + HOMEBREW_CORE_GIT_REMOTE="${HOMEBREW_CORE_DEFAULT_GIT_REMOTE}" +fi +export HOMEBREW_{BREW,CORE}_GIT_REMOTE + +# TODO: bump version when new macOS is released or announced +MACOS_NEWEST_UNSUPPORTED="15.0" +# TODO: bump version when new macOS is released +MACOS_OLDEST_SUPPORTED="12.0" + +# For Homebrew on Linux +REQUIRED_RUBY_VERSION=2.6 # https://github.com/Homebrew/brew/pull/6556 +REQUIRED_GLIBC_VERSION=2.13 # https://docs.brew.sh/Homebrew-on-Linux#requirements +REQUIRED_CURL_VERSION=7.41.0 # HOMEBREW_MINIMUM_CURL_VERSION in brew.sh in Homebrew/brew +REQUIRED_GIT_VERSION=2.7.0 # HOMEBREW_MINIMUM_GIT_VERSION in brew.sh in Homebrew/brew + +# no analytics during installation +export HOMEBREW_NO_ANALYTICS_THIS_RUN=1 +export HOMEBREW_NO_ANALYTICS_MESSAGE_OUTPUT=1 + +unset HAVE_SUDO_ACCESS # unset this from the environment + +have_sudo_access() { + if [[ ! -x "/usr/bin/sudo" ]]; then + return 1 + fi + + local -a SUDO=("/usr/bin/sudo") + if [[ -n "${SUDO_ASKPASS-}" ]]; then + SUDO+=("-A") + elif [[ -n "${NONINTERACTIVE-}" ]]; then + SUDO+=("-n") + fi + + if [[ -z "${HAVE_SUDO_ACCESS-}" ]]; then + if [[ -n "${NONINTERACTIVE-}" ]]; then + "${SUDO[@]}" -l mkdir &> /dev/null + else + "${SUDO[@]}" -v && "${SUDO[@]}" -l mkdir &> /dev/null + fi + HAVE_SUDO_ACCESS="$?" + fi + + if [[ -n "${HOMEBREW_ON_MACOS-}" ]] && [[ "${HAVE_SUDO_ACCESS}" -ne 0 ]]; then + abort "Need sudo access on macOS (e.g. the user ${USER} needs to be an Administrator)!" + fi + + return "${HAVE_SUDO_ACCESS}" +} + +execute() { + if ! "$@"; then + abort "$(printf "Failed during: %s" "$(shell_join "$@")")" + fi +} + +execute_sudo() { + local -a args=("$@") + if [[ "${EUID:-${UID}}" != "0" ]] && have_sudo_access; then + if [[ -n "${SUDO_ASKPASS-}" ]]; then + args=("-A" "${args[@]}") + fi + ohai "/usr/bin/sudo" "${args[@]}" + execute "/usr/bin/sudo" "${args[@]}" + else + ohai "${args[@]}" + execute "${args[@]}" + fi +} + +getc() { + local save_state + save_state="$(/bin/stty -g)" + /bin/stty raw -echo + IFS='' read -r -n 1 -d '' "$@" + /bin/stty "${save_state}" +} + +ring_bell() { + # Use the shell's audible bell. + if [[ -t 1 ]]; then + printf "\a" + fi +} + +wait_for_user() { + local c + echo + echo "Press ${tty_bold}RETURN${tty_reset}/${tty_bold}ENTER${tty_reset} to continue or any other key to abort:" + getc c + # we test for \r and \n because some stuff does \r instead + if ! [[ "${c}" == $'\r' || "${c}" == $'\n' ]]; then + exit 1 + fi +} + +major_minor() { + echo "${1%%.*}.$( + x="${1#*.}" + echo "${x%%.*}" + )" +} + +version_gt() { + [[ "${1%.*}" -gt "${2%.*}" ]] || [[ "${1%.*}" -eq "${2%.*}" && "${1#*.}" -gt "${2#*.}" ]] +} +version_ge() { + [[ "${1%.*}" -gt "${2%.*}" ]] || [[ "${1%.*}" -eq "${2%.*}" && "${1#*.}" -ge "${2#*.}" ]] +} +version_lt() { + [[ "${1%.*}" -lt "${2%.*}" ]] || [[ "${1%.*}" -eq "${2%.*}" && "${1#*.}" -lt "${2#*.}" ]] +} + +check_run_command_as_root() { + [[ "${EUID:-${UID}}" == "0" ]] || return + + # Allow Azure Pipelines/GitHub Actions/Docker/Concourse/Kubernetes to do everything as root (as it's normal there) + [[ -f /.dockerenv ]] && return + [[ -f /run/.containerenv ]] && return + [[ -f /proc/1/cgroup ]] && grep -E "azpl_job|actions_job|docker|garden|kubepods" -q /proc/1/cgroup && return + + abort "Don't run this as root!" +} + +should_install_command_line_tools() { + if [[ -n "${HOMEBREW_ON_LINUX-}" ]]; then + return 1 + fi + + if version_gt "${macos_version}" "10.13"; then + ! [[ -e "/Library/Developer/CommandLineTools/usr/bin/git" ]] + else + ! [[ -e "/Library/Developer/CommandLineTools/usr/bin/git" ]] || + ! [[ -e "/usr/include/iconv.h" ]] + fi +} + +get_permission() { + "${STAT_PRINTF[@]}" "${PERMISSION_FORMAT}" "$1" +} + +user_only_chmod() { + [[ -d "$1" ]] && [[ "$(get_permission "$1")" != 75[0145] ]] +} + +exists_but_not_writable() { + [[ -e "$1" ]] && ! [[ -r "$1" && -w "$1" && -x "$1" ]] +} + +get_owner() { + "${STAT_PRINTF[@]}" "%u" "$1" +} + +file_not_owned() { + [[ "$(get_owner "$1")" != "$(id -u)" ]] +} + +get_group() { + "${STAT_PRINTF[@]}" "%g" "$1" +} + +file_not_grpowned() { + [[ " $(id -G "${USER}") " != *" $(get_group "$1") "* ]] +} + +# Please sync with 'test_ruby()' in 'Library/Homebrew/utils/ruby.sh' from the Homebrew/brew repository. +test_ruby() { + if [[ ! -x "$1" ]]; then + return 1 + fi + + "$1" --enable-frozen-string-literal --disable=gems,did_you_mean,rubyopt -rrubygems -e \ + "abort if Gem::Version.new(RUBY_VERSION.to_s.dup).to_s.split('.').first(2) != \ + Gem::Version.new('${REQUIRED_RUBY_VERSION}').to_s.split('.').first(2)" 2> /dev/null +} + +test_curl() { + if [[ ! -x "$1" ]]; then + return 1 + fi + + local curl_version_output curl_name_and_version + curl_version_output="$("$1" --version 2> /dev/null)" + curl_name_and_version="${curl_version_output%% (*}" + version_ge "$(major_minor "${curl_name_and_version##* }")" "$(major_minor "${REQUIRED_CURL_VERSION}")" +} + +test_git() { + if [[ ! -x "$1" ]]; then + return 1 + fi + + local git_version_output + git_version_output="$("$1" --version 2> /dev/null)" + if [[ "${git_version_output}" =~ "git version "([^ ]*).* ]]; then + version_ge "$(major_minor "${BASH_REMATCH[1]}")" "$(major_minor "${REQUIRED_GIT_VERSION}")" + else + abort "Unexpected Git version: '${git_version_output}'!" + fi +} + +# Search for the given executable in PATH (avoids a dependency on the `which` command) +which() { + # Alias to Bash built-in command `type -P` + type -P "$@" +} + +# Search PATH for the specified program that satisfies Homebrew requirements +# function which is set above +# shellcheck disable=SC2230 +find_tool() { + if [[ $# -ne 1 ]]; then + return 1 + fi + + local executable + while read -r executable; do + if [[ "${executable}" != /* ]]; then + warn "Ignoring ${executable} (relative paths don't work)" + elif "test_$1" "${executable}"; then + echo "${executable}" + break + fi + done < <(which -a "$1") +} + +no_usable_ruby() { + [[ -z "$(find_tool ruby)" ]] +} + +outdated_glibc() { + local glibc_version + glibc_version="$(ldd --version | head -n1 | grep -o '[0-9.]*$' | grep -o '^[0-9]\+\.[0-9]\+')" + version_lt "${glibc_version}" "${REQUIRED_GLIBC_VERSION}" +} + +if [[ -n "${HOMEBREW_ON_LINUX-}" ]] && no_usable_ruby && outdated_glibc; then + abort "$( + cat << EOABORT +Homebrew requires Ruby ${REQUIRED_RUBY_VERSION} which was not found on your system. +Homebrew portable Ruby requires Glibc version ${REQUIRED_GLIBC_VERSION} or newer, +and your Glibc version is too old. See: + ${tty_underline}https://docs.brew.sh/Homebrew-on-Linux#requirements${tty_reset} +Please install Ruby ${REQUIRED_RUBY_VERSION} and add its location to your PATH. +EOABORT + )" +fi + +# Invalidate sudo timestamp before exiting (if it wasn't active before). +if [[ -x /usr/bin/sudo ]] && ! /usr/bin/sudo -n -v 2> /dev/null; then + trap '/usr/bin/sudo -k' EXIT +fi + +# Things can fail later if `pwd` doesn't exist. +# Also sudo prints a warning message for no good reason +cd "/usr" || exit 1 + +####################################################################### script + +# shellcheck disable=SC2016 +ohai 'Checking for `sudo` access (which may request your password)...' + +if [[ -n "${HOMEBREW_ON_MACOS-}" ]]; then + [[ "${EUID:-${UID}}" == "0" ]] || have_sudo_access +elif ! [[ -w "${HOMEBREW_PREFIX}" ]] && + ! [[ -w "/home/linuxbrew" ]] && + ! [[ -w "/home" ]] && + ! have_sudo_access; then + abort "$( + cat << EOABORT +Insufficient permissions to install Homebrew to \"${HOMEBREW_PREFIX}\" (the default prefix). + +Alternative (unsupported) installation methods are available at: +https://docs.brew.sh/Installation#alternative-installs + +Please note this will require most formula to build from source, a buggy, slow and energy-inefficient experience. +We will close any issues without response for these unsupported configurations. +EOABORT + )" +fi +HOMEBREW_CORE="${HOMEBREW_REPOSITORY}/Library/Taps/homebrew/homebrew-core" + +check_run_command_as_root + +if [[ -d "${HOMEBREW_PREFIX}" && ! -x "${HOMEBREW_PREFIX}" ]]; then + abort "$( + cat << EOABORT +The Homebrew prefix ${tty_underline}${HOMEBREW_PREFIX}${tty_reset} exists but is not searchable. +If this is not intentional, please restore the default permissions and +try running the installer again: + sudo chmod 775 ${HOMEBREW_PREFIX} +EOABORT + )" +fi + +if [[ -n "${HOMEBREW_ON_MACOS-}" ]]; then + # On macOS, support 64-bit Intel and ARM + if [[ "${UNAME_MACHINE}" != "arm64" ]] && [[ "${UNAME_MACHINE}" != "x86_64" ]]; then + abort "Homebrew is only supported on Intel and ARM processors!" + fi +else + # On Linux, support only 64-bit Intel + if [[ "${UNAME_MACHINE}" == "aarch64" ]]; then + abort "$( + cat << EOABORT +Homebrew on Linux is not supported on ARM processors. + ${tty_underline}https://docs.brew.sh/Homebrew-on-Linux#arm-unsupported${tty_reset} +EOABORT + )" + elif [[ "${UNAME_MACHINE}" != "x86_64" ]]; then + abort "Homebrew on Linux is only supported on Intel processors!" + fi +fi + +if [[ -n "${HOMEBREW_ON_MACOS-}" ]]; then + macos_version="$(major_minor "$(/usr/bin/sw_vers -productVersion)")" + if version_lt "${macos_version}" "10.7"; then + abort "$( + cat << EOABORT +Your Mac OS X version is too old. See: + ${tty_underline}https://github.com/mistydemeo/tigerbrew${tty_reset} +EOABORT + )" + elif version_lt "${macos_version}" "10.11"; then + abort "Your OS X version is too old." + elif version_ge "${macos_version}" "${MACOS_NEWEST_UNSUPPORTED}" || + version_lt "${macos_version}" "${MACOS_OLDEST_SUPPORTED}"; then + who="We" + what="" + if version_ge "${macos_version}" "${MACOS_NEWEST_UNSUPPORTED}"; then + what="pre-release version" + else + who+=" (and Apple)" + what="old version" + fi + ohai "You are using macOS ${macos_version}." + ohai "${who} do not provide support for this ${what}." + + echo "$( + cat << EOS +This installation may not succeed. +After installation, you will encounter build failures with some formulae. +Please create pull requests instead of asking for help on Homebrew\'s GitHub, +Twitter or any other official channels. You are responsible for resolving any +issues you experience while you are running this ${what}. +EOS + ) +" | tr -d "\\" + fi +fi + +ohai "This script will install:" +echo "${HOMEBREW_PREFIX}/bin/brew" +echo "${HOMEBREW_PREFIX}/share/doc/homebrew" +echo "${HOMEBREW_PREFIX}/share/man/man1/brew.1" +echo "${HOMEBREW_PREFIX}/share/zsh/site-functions/_brew" +echo "${HOMEBREW_PREFIX}/etc/bash_completion.d/brew" +echo "${HOMEBREW_REPOSITORY}" + +# Keep relatively in sync with +# https://github.com/Homebrew/brew/blob/master/Library/Homebrew/keg.rb +directories=( + bin etc include lib sbin share opt var + Frameworks + etc/bash_completion.d lib/pkgconfig + share/aclocal share/doc share/info share/locale share/man + share/man/man1 share/man/man2 share/man/man3 share/man/man4 + share/man/man5 share/man/man6 share/man/man7 share/man/man8 + var/log var/homebrew var/homebrew/linked + bin/brew +) +group_chmods=() +for dir in "${directories[@]}"; do + if exists_but_not_writable "${HOMEBREW_PREFIX}/${dir}"; then + group_chmods+=("${HOMEBREW_PREFIX}/${dir}") + fi +done + +# zsh refuses to read from these directories if group writable +directories=(share/zsh share/zsh/site-functions) +zsh_dirs=() +for dir in "${directories[@]}"; do + zsh_dirs+=("${HOMEBREW_PREFIX}/${dir}") +done + +directories=( + bin etc include lib sbin share var opt + share/zsh share/zsh/site-functions + var/homebrew var/homebrew/linked + Cellar Caskroom Frameworks +) +mkdirs=() +for dir in "${directories[@]}"; do + if ! [[ -d "${HOMEBREW_PREFIX}/${dir}" ]]; then + mkdirs+=("${HOMEBREW_PREFIX}/${dir}") + fi +done + +user_chmods=() +mkdirs_user_only=() +if [[ "${#zsh_dirs[@]}" -gt 0 ]]; then + for dir in "${zsh_dirs[@]}"; do + if [[ ! -d "${dir}" ]]; then + mkdirs_user_only+=("${dir}") + elif user_only_chmod "${dir}"; then + user_chmods+=("${dir}") + fi + done +fi + +chmods=() +if [[ "${#group_chmods[@]}" -gt 0 ]]; then + chmods+=("${group_chmods[@]}") +fi +if [[ "${#user_chmods[@]}" -gt 0 ]]; then + chmods+=("${user_chmods[@]}") +fi + +chowns=() +chgrps=() +if [[ "${#chmods[@]}" -gt 0 ]]; then + for dir in "${chmods[@]}"; do + if file_not_owned "${dir}"; then + chowns+=("${dir}") + fi + if file_not_grpowned "${dir}"; then + chgrps+=("${dir}") + fi + done +fi + +if [[ "${#group_chmods[@]}" -gt 0 ]]; then + ohai "The following existing directories will be made group writable:" + printf "%s\n" "${group_chmods[@]}" +fi +if [[ "${#user_chmods[@]}" -gt 0 ]]; then + ohai "The following existing directories will be made writable by user only:" + printf "%s\n" "${user_chmods[@]}" +fi +if [[ "${#chowns[@]}" -gt 0 ]]; then + ohai "The following existing directories will have their owner set to ${tty_underline}${USER}${tty_reset}:" + printf "%s\n" "${chowns[@]}" +fi +if [[ "${#chgrps[@]}" -gt 0 ]]; then + ohai "The following existing directories will have their group set to ${tty_underline}${GROUP}${tty_reset}:" + printf "%s\n" "${chgrps[@]}" +fi +if [[ "${#mkdirs[@]}" -gt 0 ]]; then + ohai "The following new directories will be created:" + printf "%s\n" "${mkdirs[@]}" +fi + +if should_install_command_line_tools; then + ohai "The Xcode Command Line Tools will be installed." +fi + +non_default_repos="" +additional_shellenv_commands=() +if [[ "${HOMEBREW_BREW_DEFAULT_GIT_REMOTE}" != "${HOMEBREW_BREW_GIT_REMOTE}" ]]; then + ohai "HOMEBREW_BREW_GIT_REMOTE is set to a non-default URL:" + echo "${tty_underline}${HOMEBREW_BREW_GIT_REMOTE}${tty_reset} will be used as the Homebrew/brew Git remote." + non_default_repos="Homebrew/brew" + additional_shellenv_commands+=("export HOMEBREW_BREW_GIT_REMOTE=\"${HOMEBREW_BREW_GIT_REMOTE}\"") +fi + +if [[ "${HOMEBREW_CORE_DEFAULT_GIT_REMOTE}" != "${HOMEBREW_CORE_GIT_REMOTE}" ]]; then + ohai "HOMEBREW_CORE_GIT_REMOTE is set to a non-default URL:" + echo "${tty_underline}${HOMEBREW_CORE_GIT_REMOTE}${tty_reset} will be used as the Homebrew/homebrew-core Git remote." + non_default_repos="${non_default_repos:-}${non_default_repos:+ and }Homebrew/homebrew-core" + additional_shellenv_commands+=("export HOMEBREW_CORE_GIT_REMOTE=\"${HOMEBREW_CORE_GIT_REMOTE}\"") +fi + +if [[ -n "${HOMEBREW_NO_INSTALL_FROM_API-}" ]]; then + ohai "HOMEBREW_NO_INSTALL_FROM_API is set." + echo "Homebrew/homebrew-core will be tapped during this ${tty_bold}install${tty_reset} run." +fi + +if [[ -z "${NONINTERACTIVE-}" ]]; then + ring_bell + wait_for_user +fi + +if [[ -d "${HOMEBREW_PREFIX}" ]]; then + if [[ "${#chmods[@]}" -gt 0 ]]; then + execute_sudo "${CHMOD[@]}" "u+rwx" "${chmods[@]}" + fi + if [[ "${#group_chmods[@]}" -gt 0 ]]; then + execute_sudo "${CHMOD[@]}" "g+rwx" "${group_chmods[@]}" + fi + if [[ "${#user_chmods[@]}" -gt 0 ]]; then + execute_sudo "${CHMOD[@]}" "go-w" "${user_chmods[@]}" + fi + if [[ "${#chowns[@]}" -gt 0 ]]; then + execute_sudo "${CHOWN[@]}" "${USER}" "${chowns[@]}" + fi + if [[ "${#chgrps[@]}" -gt 0 ]]; then + execute_sudo "${CHGRP[@]}" "${GROUP}" "${chgrps[@]}" + fi +else + execute_sudo "${INSTALL[@]}" "${HOMEBREW_PREFIX}" +fi + +if [[ "${#mkdirs[@]}" -gt 0 ]]; then + execute_sudo "${MKDIR[@]}" "${mkdirs[@]}" + execute_sudo "${CHMOD[@]}" "ug=rwx" "${mkdirs[@]}" + if [[ "${#mkdirs_user_only[@]}" -gt 0 ]]; then + execute_sudo "${CHMOD[@]}" "go-w" "${mkdirs_user_only[@]}" + fi + execute_sudo "${CHOWN[@]}" "${USER}" "${mkdirs[@]}" + execute_sudo "${CHGRP[@]}" "${GROUP}" "${mkdirs[@]}" +fi + +if ! [[ -d "${HOMEBREW_REPOSITORY}" ]]; then + execute_sudo "${MKDIR[@]}" "${HOMEBREW_REPOSITORY}" +fi +execute_sudo "${CHOWN[@]}" "-R" "${USER}:${GROUP}" "${HOMEBREW_REPOSITORY}" + +if ! [[ -d "${HOMEBREW_CACHE}" ]]; then + if [[ -n "${HOMEBREW_ON_MACOS-}" ]]; then + execute_sudo "${MKDIR[@]}" "${HOMEBREW_CACHE}" + else + execute "${MKDIR[@]}" "${HOMEBREW_CACHE}" + fi +fi +if exists_but_not_writable "${HOMEBREW_CACHE}"; then + execute_sudo "${CHMOD[@]}" "g+rwx" "${HOMEBREW_CACHE}" +fi +if file_not_owned "${HOMEBREW_CACHE}"; then + execute_sudo "${CHOWN[@]}" "-R" "${USER}" "${HOMEBREW_CACHE}" +fi +if file_not_grpowned "${HOMEBREW_CACHE}"; then + execute_sudo "${CHGRP[@]}" "-R" "${GROUP}" "${HOMEBREW_CACHE}" +fi +if [[ -d "${HOMEBREW_CACHE}" ]]; then + execute "${TOUCH[@]}" "${HOMEBREW_CACHE}/.cleaned" +fi + +if should_install_command_line_tools && version_ge "${macos_version}" "10.13"; then + ohai "Searching online for the Command Line Tools" + # This temporary file prompts the 'softwareupdate' utility to list the Command Line Tools + clt_placeholder="/tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress" + execute_sudo "${TOUCH[@]}" "${clt_placeholder}" + + clt_label_command="/usr/sbin/softwareupdate -l | + grep -B 1 -E 'Command Line Tools' | + awk -F'*' '/^ *\\*/ {print \$2}' | + sed -e 's/^ *Label: //' -e 's/^ *//' | + sort -V | + tail -n1" + clt_label="$(chomp "$(/bin/bash -c "${clt_label_command}")")" + + if [[ -n "${clt_label}" ]]; then + ohai "Installing ${clt_label}" + execute_sudo "/usr/sbin/softwareupdate" "-i" "${clt_label}" + execute_sudo "/usr/bin/xcode-select" "--switch" "/Library/Developer/CommandLineTools" + fi + execute_sudo "/bin/rm" "-f" "${clt_placeholder}" +fi + +# Headless install may have failed, so fallback to original 'xcode-select' method +if should_install_command_line_tools && test -t 0; then + ohai "Installing the Command Line Tools (expect a GUI popup):" + execute "/usr/bin/xcode-select" "--install" + echo "Press any key when the installation has completed." + getc + execute_sudo "/usr/bin/xcode-select" "--switch" "/Library/Developer/CommandLineTools" +fi + +if [[ -n "${HOMEBREW_ON_MACOS-}" ]] && ! output="$(/usr/bin/xcrun clang 2>&1)" && [[ "${output}" == *"license"* ]]; then + abort "$( + cat << EOABORT +You have not agreed to the Xcode license. +Before running the installer again please agree to the license by opening +Xcode.app or running: + sudo xcodebuild -license +EOABORT + )" +fi + +USABLE_GIT=/usr/bin/git +if [[ -n "${HOMEBREW_ON_LINUX-}" ]]; then + USABLE_GIT="$(find_tool git)" + if [[ -z "$(command -v git)" ]]; then + abort "$( + cat << EOABORT + You must install Git before installing Homebrew. See: + ${tty_underline}https://docs.brew.sh/Installation${tty_reset} +EOABORT + )" + fi + if [[ -z "${USABLE_GIT}" ]]; then + abort "$( + cat << EOABORT + The version of Git that was found does not satisfy requirements for Homebrew. + Please install Git ${REQUIRED_GIT_VERSION} or newer and add it to your PATH. +EOABORT + )" + fi + if [[ "${USABLE_GIT}" != /usr/bin/git ]]; then + export HOMEBREW_GIT_PATH="${USABLE_GIT}" + ohai "Found Git: ${HOMEBREW_GIT_PATH}" + fi +fi + +if ! command -v curl > /dev/null; then + abort "$( + cat << EOABORT +You must install cURL before installing Homebrew. See: + ${tty_underline}https://docs.brew.sh/Installation${tty_reset} +EOABORT + )" +elif [[ -n "${HOMEBREW_ON_LINUX-}" ]]; then + USABLE_CURL="$(find_tool curl)" + if [[ -z "${USABLE_CURL}" ]]; then + abort "$( + cat << EOABORT +The version of cURL that was found does not satisfy requirements for Homebrew. +Please install cURL ${REQUIRED_CURL_VERSION} or newer and add it to your PATH. +EOABORT + )" + elif [[ "${USABLE_CURL}" != /usr/bin/curl ]]; then + export HOMEBREW_CURL_PATH="${USABLE_CURL}" + ohai "Found cURL: ${HOMEBREW_CURL_PATH}" + fi +fi + +ohai "Downloading and installing Homebrew..." +( + cd "${HOMEBREW_REPOSITORY}" > /dev/null || return + + # we do it in four steps to avoid merge errors when reinstalling + execute "${USABLE_GIT}" "-c" "init.defaultBranch=master" "init" "--quiet" + + # "git remote add" will fail if the remote is defined in the global config + execute "${USABLE_GIT}" "config" "remote.origin.url" "${HOMEBREW_BREW_GIT_REMOTE}" + execute "${USABLE_GIT}" "config" "remote.origin.fetch" "+refs/heads/*:refs/remotes/origin/*" + + # ensure we don't munge line endings on checkout + execute "${USABLE_GIT}" "config" "--bool" "core.autocrlf" "false" + + # make sure symlinks are saved as-is + execute "${USABLE_GIT}" "config" "--bool" "core.symlinks" "true" + + execute "${USABLE_GIT}" "fetch" "--force" "origin" + execute "${USABLE_GIT}" "fetch" "--force" "--tags" "origin" + execute "${USABLE_GIT}" "remote" "set-head" "origin" "--auto" > /dev/null + + LATEST_GIT_TAG="$("${USABLE_GIT}" tag --list --sort="-version:refname" | head -n1)" + if [[ -z "${LATEST_GIT_TAG}" ]]; then + abort "Failed to query latest Homebrew/brew Git tag." + fi + execute "${USABLE_GIT}" "checkout" "--force" "-B" "stable" "${LATEST_GIT_TAG}" + + if [[ "${HOMEBREW_REPOSITORY}" != "${HOMEBREW_PREFIX}" ]]; then + if [[ "${HOMEBREW_REPOSITORY}" == "${HOMEBREW_PREFIX}/Homebrew" ]]; then + execute "ln" "-sf" "../Homebrew/bin/brew" "${HOMEBREW_PREFIX}/bin/brew" + else + abort "The Homebrew/brew repository should be placed in the Homebrew prefix directory." + fi + fi + + if [[ -n "${HOMEBREW_NO_INSTALL_FROM_API-}" && ! -d "${HOMEBREW_CORE}" ]]; then + # Always use single-quoted strings with `exp` expressions + # shellcheck disable=SC2016 + ohai 'Tapping homebrew/core because `$HOMEBREW_NO_INSTALL_FROM_API` is set.' + ( + execute "${MKDIR[@]}" "${HOMEBREW_CORE}" + cd "${HOMEBREW_CORE}" > /dev/null || return + + execute "${USABLE_GIT}" "-c" "init.defaultBranch=master" "init" "--quiet" + execute "${USABLE_GIT}" "config" "remote.origin.url" "${HOMEBREW_CORE_GIT_REMOTE}" + execute "${USABLE_GIT}" "config" "remote.origin.fetch" "+refs/heads/*:refs/remotes/origin/*" + execute "${USABLE_GIT}" "config" "--bool" "core.autocrlf" "false" + execute "${USABLE_GIT}" "config" "--bool" "core.symlinks" "true" + execute "${USABLE_GIT}" "fetch" "--force" "origin" "refs/heads/master:refs/remotes/origin/master" + execute "${USABLE_GIT}" "remote" "set-head" "origin" "--auto" > /dev/null + execute "${USABLE_GIT}" "reset" "--hard" "origin/master" + + cd "${HOMEBREW_REPOSITORY}" > /dev/null || return + ) || exit 1 + fi + + execute "${HOMEBREW_PREFIX}/bin/brew" "update" "--force" "--quiet" +) || exit 1 + +if [[ ":${PATH}:" != *":${HOMEBREW_PREFIX}/bin:"* ]]; then + warn "${HOMEBREW_PREFIX}/bin is not in your PATH. + Instructions on how to configure your shell for Homebrew + can be found in the 'Next steps' section below." +fi + +ohai "Installation successful!" +echo + +ring_bell + +# Use an extra newline and bold to avoid this being missed. +ohai "Homebrew has enabled anonymous aggregate formulae and cask analytics." +echo "$( + cat << EOS +${tty_bold}Read the analytics documentation (and how to opt-out) here: + ${tty_underline}https://docs.brew.sh/Analytics${tty_reset} +No analytics data has been sent yet (nor will any be during this ${tty_bold}install${tty_reset} run). +EOS +) +" + +ohai "Homebrew is run entirely by unpaid volunteers. Please consider donating:" +echo "$( + cat << EOS + ${tty_underline}https://github.com/Homebrew/brew#donations${tty_reset} +EOS +) +" + +( + cd "${HOMEBREW_REPOSITORY}" > /dev/null || return + execute "${USABLE_GIT}" "config" "--replace-all" "homebrew.analyticsmessage" "true" + execute "${USABLE_GIT}" "config" "--replace-all" "homebrew.caskanalyticsmessage" "true" +) || exit 1 + +ohai "Next steps:" +case "${SHELL}" in +*/bash*) + if [[ -n "${HOMEBREW_ON_LINUX-}" ]]; then + shell_rcfile="${HOME}/.bashrc" + else + shell_rcfile="${HOME}/.bash_profile" + fi + ;; +*/zsh*) + if [[ -n "${HOMEBREW_ON_LINUX-}" ]]; then + shell_rcfile="${ZDOTDIR:-"${HOME}"}/.zshrc" + else + shell_rcfile="${ZDOTDIR:-"${HOME}"}/.zprofile" + fi + ;; +*/fish*) + shell_rcfile="${HOME}/.config/fish/config.fish" + ;; +*) + shell_rcfile="${ENV:-"${HOME}/.profile"}" + ;; +esac + +if grep -qs "eval \"\$(${HOMEBREW_PREFIX}/bin/brew shellenv)\"" "${shell_rcfile}"; then + if ! [[ -x "$(command -v brew)" ]]; then + cat << EOS +- Run this command in your terminal to add Homebrew to your ${tty_bold}PATH${tty_reset}: + eval "\$(${HOMEBREW_PREFIX}/bin/brew shellenv)" +EOS + fi +else + cat << EOS +- Run these two commands in your terminal to add Homebrew to your ${tty_bold}PATH${tty_reset}: + (echo; echo 'eval "\$(${HOMEBREW_PREFIX}/bin/brew shellenv)"') >> ${shell_rcfile} + eval "\$(${HOMEBREW_PREFIX}/bin/brew shellenv)" +EOS +fi + +if [[ -n "${non_default_repos}" ]]; then + plural="" + if [[ "${#additional_shellenv_commands[@]}" -gt 1 ]]; then + plural="s" + fi + printf -- "- Run these commands in your terminal to add the non-default Git remote%s for %s:\n" "${plural}" "${non_default_repos}" + printf " echo '# Set PATH, MANPATH, etc., for Homebrew.' >> %s\n" "${shell_rcfile}" + printf " echo '%s' >> ${shell_rcfile}\n" "${additional_shellenv_commands[@]}" + printf " %s\n" "${additional_shellenv_commands[@]}" +fi + +if [[ -n "${HOMEBREW_ON_LINUX-}" ]]; then + echo "- Install Homebrew's dependencies if you have sudo access:" + + if [[ -x "$(command -v apt-get)" ]]; then + echo " sudo apt-get install build-essential" + elif [[ -x "$(command -v yum)" ]]; then + echo " sudo yum groupinstall 'Development Tools'" + elif [[ -x "$(command -v pacman)" ]]; then + echo " sudo pacman -S base-devel" + elif [[ -x "$(command -v apk)" ]]; then + echo " sudo apk add build-base" + fi + + cat << EOS + For more information, see: + ${tty_underline}https://docs.brew.sh/Homebrew-on-Linux${tty_reset} +- We recommend that you install GCC: + brew install gcc +EOS +fi + +cat << EOS +- Run ${tty_bold}brew help${tty_reset} to get started +- Further documentation: + ${tty_underline}https://docs.brew.sh${tty_reset} + +EOS diff --git a/scripts/packaging/octez/homebrew/homebrew_release.sh b/scripts/packaging/octez/homebrew/homebrew_release.sh new file mode 100755 index 000000000000..feefbd71f4d7 --- /dev/null +++ b/scripts/packaging/octez/homebrew/homebrew_release.sh @@ -0,0 +1,99 @@ +#!/bin/sh +# + +# This script assume that homebrew is correctly installed +# using the script ./scripts/packaging/homebrew_install.sh +# and creates a formula scripts/packaging/Formula/octez.rb +# that is ready to be installed with brew + +set -ue + +# If it's a protected branch the value of $bucket will +# be set accordingly but the CI. +BUCKET="$GCP_LINUX_PACKAGES_BUCKET" + +# set version + +. scripts/version.sh +. scripts/ci/octez-release.sh + +# fetch tags for releases +git fetch -q --tags + +if [ -n "${gitlab_release_no_v:-}" ]; then + VERSION=$gitlab_release_no_v +elif [ -n "${CI_COMMIT_TAG:-}" ]; then + VERSION=$(date +'%Y%m%d%H%M')+$CI_COMMIT_TAG +else + VERSION=$(date +'%Y%m%d%H%M')+$CI_COMMIT_SHORT_SHA +fi + +# prepare target dir + +# if it's a release tag, then it can be a RC release or a final release +if [ -n "${gitlab_release_no_v:-}" ]; then + # It a release tag, this can be either a real or test release + if [ -n "${gitlab_release_rc_version}" ]; then + # Release candidate + TARGETDIR="public/homebrew/RC/Formula" + else + # Release + TARGETDIR="public/homebrew/Formula" + fi +else + if [ "$CI_COMMIT_REF_PROTECTED" = "false" ]; then + if [ "$CI_COMMIT_REF_NAME" = "RC" ]; then + echo "Cannot create a repository for a branch named 'RC'" + exit 1 + else + # Branch is not protected, this is for testing ordinary MRs + TARGETDIR="public/homebrew/$CI_COMMIT_REF_NAME/Formula" + fi + else + # For protected branches that are not release, we allow + # a repository only for master. + if [ "$CI_COMMIT_REF_NAME" = "master" ]; then + TARGETDIR="public/homebrew/master/Formula" + else + if [ -n "${CI_COMMIT_TAG:-}" ]; then + TARGETDIR="public/homebrew/${CI_COMMIT_TAG}/Formula" + else + echo "Cannot create a repository for a protected branch that is not associated to a tag or master" + exit 1 + fi + fi + fi +fi + +# prepare formula + +mkdir -p "$TARGETDIR" + +#shellcheck disable=SC2046 +eval $(scripts/active_protocols.sh) +sed "s|%%VERSION%%|$VERSION|; \ + s|%%CI_MERGE_REQUEST_SOURCE_PROJECT_URL%%|$CI_MERGE_REQUEST_SOURCE_PROJECT_URL|; \ + s|%%CI_COMMIT_REF_NAME%%|$CI_COMMIT_REF_NAME|; \ + s|%%CI_PROJECT_NAMESPACE%%|$CI_PROJECT_NAMESPACE|; \ + s|%%PROTO_CURRENT%%|$PROTO_CURRENT|; s|%%PROTO_NEXT%%|$PROTO_NEXT|" \ + scripts/packaging/octez/homebrew/Formula/octez.rb.template > "$TARGETDIR/octez.rb" + +# upload to bucket + +if [ "$CI_COMMIT_REF_PROTECTED" = "true" ]; then + echo "### Logging into protected repo ..." + echo "${GCP_PROTECTED_SERVICE_ACCOUNT}" | base64 -d > protected_sa.json + gcloud auth activate-service-account --key-file=protected_sa.json +else + echo "### Logging into standard repo ..." + # Nothing to do +fi + +GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token) +export GOOGLE_OAUTH_ACCESS_TOKEN + +echo "Push to $BUCKET" + +gsutil -m cp -r public/* gs://"${BUCKET}" + +echo "https://$BUCKET.storage.googleapis.com/${TARGETDIR##public/}/octez.rb" -- GitLab From d7bf5394fe6d085ea87e7a889121529f7d570cf6 Mon Sep 17 00:00:00 2001 From: Pietro Abate Date: Mon, 16 Sep 2024 12:33:58 +0200 Subject: [PATCH 2/4] homebrew: test formula from bucket --- .gitlab/ci/pipelines/before_merging.yml | 2 +- .gitlab/ci/pipelines/merge_train.yml | 2 +- ci/bin/common.ml | 2 +- scripts/packaging/Formula/octez.rb.template | 76 -- scripts/packaging/homebrew_install.sh | 984 ------------------ scripts/packaging/homebrew_release.sh | 95 -- .../octez/homebrew/homebrew_release.sh | 3 +- .../homebrew/tests/test_homebrew_install.sh | 64 ++ 8 files changed, 68 insertions(+), 1160 deletions(-) delete mode 100644 scripts/packaging/Formula/octez.rb.template delete mode 100755 scripts/packaging/homebrew_install.sh delete mode 100755 scripts/packaging/homebrew_release.sh create mode 100755 scripts/packaging/octez/homebrew/tests/test_homebrew_install.sh diff --git a/.gitlab/ci/pipelines/before_merging.yml b/.gitlab/ci/pipelines/before_merging.yml index 4eff2cdd0a79..e9e5db52e95f 100644 --- a/.gitlab/ci/pipelines/before_merging.yml +++ b/.gitlab/ci/pipelines/before_merging.yml @@ -4820,7 +4820,7 @@ oc.build:homebrew: script: - apt install -y autoconf cmake libev-dev libffi-dev libgmp-dev libprotobuf-dev libsqlite3-dev protobuf-compiler libhidapi-dev pkg-config zlib1g-dev libpq-dev - - brew install -v scripts/packaging/Formula/octez.rb + - ./scripts/packaging/test_homebrew_install.sh variables: CARGO_NET_OFFLINE: "false" diff --git a/.gitlab/ci/pipelines/merge_train.yml b/.gitlab/ci/pipelines/merge_train.yml index 3a948a560666..5b7ffe7da64f 100644 --- a/.gitlab/ci/pipelines/merge_train.yml +++ b/.gitlab/ci/pipelines/merge_train.yml @@ -4802,7 +4802,7 @@ oc.build:homebrew: script: - apt install -y autoconf cmake libev-dev libffi-dev libgmp-dev libprotobuf-dev libsqlite3-dev protobuf-compiler libhidapi-dev pkg-config zlib1g-dev libpq-dev - - brew install -v scripts/packaging/Formula/octez.rb + - ./scripts/packaging/test_homebrew_install.sh variables: CARGO_NET_OFFLINE: "false" diff --git a/ci/bin/common.ml b/ci/bin/common.ml index 05e2f44d6d86..6d163bd1ca4b 100644 --- a/ci/bin/common.ml +++ b/ci/bin/common.ml @@ -1131,7 +1131,7 @@ let job_build_homebrew ?rules ~__POS__ ~name ?(stage = Stages.build) "apt install -y autoconf cmake libev-dev libffi-dev libgmp-dev \ libprotobuf-dev libsqlite3-dev protobuf-compiler libhidapi-dev \ pkg-config zlib1g-dev libpq-dev"; - "brew install -v scripts/packaging/Formula/octez.rb"; + "./scripts/packaging/test_homebrew_install.sh"; ] |> enable_networked_cargo diff --git a/scripts/packaging/Formula/octez.rb.template b/scripts/packaging/Formula/octez.rb.template deleted file mode 100644 index 2280af888e10..000000000000 --- a/scripts/packaging/Formula/octez.rb.template +++ /dev/null @@ -1,76 +0,0 @@ -# -# SPDX-License-Identifier: MIT -# SPDX-FileCopyrightText: 2024 Nomadic Labs -# - -# This is a Homebrew formula for installing Octez. -class Octez < Formula - @all_bins = [] - - class << self - attr_accessor :all_bins - end - homepage "https://gitlab.com/tezos/tezos" - url "%%CI_MERGE_REQUEST_SOURCE_PROJECT_URL%%.git", :tag => "%%CI_COMMIT_REF_NAME%%", :shallow => false - version "%%VERSION%%" - license "MIT" - - build_dependencies = %w[pkg-config coreutils autoconf rsync wget opam protobuf cmake] - build_dependencies.each do |dependency| - depends_on dependency => :build - end - - dependencies = %w[gmp hidapi libev libffi libpq] - dependencies.each do |dependency| - depends_on dependency - end - - def make_deps - ENV.deparallelize - ENV["CARGO_HOME"]="./.cargo" - ENV["OPAMROOT"]="./.opam" - ENV["OPAMYES"]="true" - ENV["BLST_PORTABLE"]="yes" - ENV["LDFLAGS"] = "-L#{HOMEBREW_PREFIX}/lib" - - - (buildpath/"script.sh").write <<~EOS - #!/bin/sh - - set +x - - . ./scripts/version.sh - wget https://sh.rustup.rs/rustup-init.sh - chmod +x rustup-init.sh - ./rustup-init.sh --profile minimal --default-toolchain $recommended_rust_version -y - opam init --bare --disable-sandboxing - - . $CARGO_HOME/env - make build-deps - - eval $(opam env) - make release - EOS - - chmod 0755, buildpath/"script.sh" - system "./script.sh" - end - - def install_template(name) - bin.mkpath - self.class.all_bins << name - bin.install name - end - - def install - make_deps - install_template "octez-node" - install_template "octez-client" - install_template "octez-signer" - install_template "octez-accuser-%%PROTO_CURRENT%%" - install_template "octez-baker-%%PROTO_CURRENT%%" - install_template "octez-accuser-%%PROTO_NEXT%%" - install_template "octez-baker-%%PROTO_NEXT%%" - end - -end diff --git a/scripts/packaging/homebrew_install.sh b/scripts/packaging/homebrew_install.sh deleted file mode 100755 index 876a290a7003..000000000000 --- a/scripts/packaging/homebrew_install.sh +++ /dev/null @@ -1,984 +0,0 @@ -#!/bin/bash - -# -# SPDX-License-Identifier: BSD 2-Clause License -# SPDX-FileCopyrightText: Copyright (c) 2009-present, Homebrew contributors -# - -# We don't need return codes for "$(command)", only stdout is needed. -# Allow `[[ -n "$(command)" ]]`, `func "$(command)"`, pipes, etc. -# shellcheck disable=SC2312 - -set -u - -abort() { - printf "%s\n" "$@" >&2 - exit 1 -} - -# Fail fast with a concise message when not using bash -# Single brackets are needed here for POSIX compatibility -# shellcheck disable=SC2292 -if [ -z "${BASH_VERSION:-}" ]; then - abort "Bash is required to interpret this script." -fi - -# Check if script is run with force-interactive mode in CI -if [[ -n "${CI-}" && -n "${INTERACTIVE-}" ]]; then - abort "Cannot run force-interactive mode in CI." -fi - -# Check if both `INTERACTIVE` and `NONINTERACTIVE` are set -# Always use single-quoted strings with `exp` expressions -# shellcheck disable=SC2016 -if [[ -n "${INTERACTIVE-}" && -n "${NONINTERACTIVE-}" ]]; then - abort 'Both `$INTERACTIVE` and `$NONINTERACTIVE` are set. Please unset at least one variable and try again.' -fi - -# Check if script is run in POSIX mode -if [[ -n "${POSIXLY_CORRECT+1}" ]]; then - abort 'Bash must not run in POSIX mode. Please unset POSIXLY_CORRECT and try again.' -fi - -usage() { - cat << EOS -Homebrew Installer -Usage: [NONINTERACTIVE=1] [CI=1] install.sh [options] - -h, --help Display this message. - NONINTERACTIVE Install without prompting for user input - CI Install in CI mode (e.g. do not prompt for user input) -EOS - exit "${1:-0}" -} - -while [[ $# -gt 0 ]]; do - case "$1" in - -h | --help) usage ;; - *) - warn "Unrecognized option: '$1'" - usage 1 - ;; - esac -done - -# string formatters -if [[ -t 1 ]]; then - tty_escape() { printf "\033[%sm" "$1"; } -else - tty_escape() { :; } -fi -tty_mkbold() { tty_escape "1;$1"; } -tty_underline="$(tty_escape "4;39")" -tty_blue="$(tty_mkbold 34)" -tty_red="$(tty_mkbold 31)" -tty_bold="$(tty_mkbold 39)" -tty_reset="$(tty_escape 0)" - -shell_join() { - local arg - printf "%s" "$1" - shift - for arg in "$@"; do - printf " " - printf "%s" "${arg// /\ }" - done -} - -chomp() { - printf "%s" "${1/"$'\n'"/}" -} - -ohai() { - printf "${tty_blue}==>${tty_bold} %s${tty_reset}\n" "$(shell_join "$@")" -} - -warn() { - printf "${tty_red}Warning${tty_reset}: %s\n" "$(chomp "$1")" >&2 -} - -# Check if script is run non-interactively (e.g. CI) -# If it is run non-interactively we should not prompt for passwords. -# Always use single-quoted strings with `exp` expressions -# shellcheck disable=SC2016 -if [[ -z "${NONINTERACTIVE-}" ]]; then - if [[ -n "${CI-}" ]]; then - warn 'Running in non-interactive mode because `$CI` is set.' - NONINTERACTIVE=1 - elif [[ ! -t 0 ]]; then - if [[ -z "${INTERACTIVE-}" ]]; then - warn 'Running in non-interactive mode because `stdin` is not a TTY.' - NONINTERACTIVE=1 - else - warn 'Running in interactive mode despite `stdin` not being a TTY because `$INTERACTIVE` is set.' - fi - fi -else - ohai 'Running in non-interactive mode because `$NONINTERACTIVE` is set.' -fi - -# USER isn't always set so provide a fall back for the installer and subprocesses. -if [[ -z "${USER-}" ]]; then - USER="$(chomp "$(id -un)")" - export USER -fi - -# First check OS. -OS="$(uname)" -if [[ "${OS}" == "Linux" ]]; then - HOMEBREW_ON_LINUX=1 -elif [[ "${OS}" == "Darwin" ]]; then - HOMEBREW_ON_MACOS=1 -else - abort "Homebrew is only supported on macOS and Linux." -fi - -# Required installation paths. To install elsewhere (which is unsupported) -# you can untar https://github.com/Homebrew/brew/tarball/master -# anywhere you like. -if [[ -n "${HOMEBREW_ON_MACOS-}" ]]; then - UNAME_MACHINE="$(/usr/bin/uname -m)" - - if [[ "${UNAME_MACHINE}" == "arm64" ]]; then - # On ARM macOS, this script installs to /opt/homebrew only - HOMEBREW_PREFIX="/opt/homebrew" - HOMEBREW_REPOSITORY="${HOMEBREW_PREFIX}" - else - # On Intel macOS, this script installs to /usr/local only - HOMEBREW_PREFIX="/usr/local" - HOMEBREW_REPOSITORY="${HOMEBREW_PREFIX}/Homebrew" - fi - HOMEBREW_CACHE="${HOME}/Library/Caches/Homebrew" - - STAT_PRINTF=("stat" "-f") - PERMISSION_FORMAT="%A" - CHOWN=("/usr/sbin/chown") - CHGRP=("/usr/bin/chgrp") - GROUP="admin" - TOUCH=("/usr/bin/touch") - INSTALL=("/usr/bin/install" -d -o "root" -g "wheel" -m "0755") -else - UNAME_MACHINE="$(uname -m)" - - # On Linux, this script installs to /home/linuxbrew/.linuxbrew only - HOMEBREW_PREFIX="/home/linuxbrew/.linuxbrew" - HOMEBREW_REPOSITORY="${HOMEBREW_PREFIX}/Homebrew" - HOMEBREW_CACHE="${HOME}/.cache/Homebrew" - - STAT_PRINTF=("stat" "--printf") - PERMISSION_FORMAT="%a" - CHOWN=("/bin/chown") - CHGRP=("/bin/chgrp") - GROUP="$(id -gn)" - TOUCH=("/bin/touch") - INSTALL=("/usr/bin/install" -d -o "${USER}" -g "${GROUP}" -m "0755") -fi -CHMOD=("/bin/chmod") -MKDIR=("/bin/mkdir" "-p") -HOMEBREW_BREW_DEFAULT_GIT_REMOTE="https://github.com/Homebrew/brew" -HOMEBREW_CORE_DEFAULT_GIT_REMOTE="https://github.com/Homebrew/homebrew-core" - -# Use remote URLs of Homebrew repositories from environment if set. -HOMEBREW_BREW_GIT_REMOTE="${HOMEBREW_BREW_GIT_REMOTE:-"${HOMEBREW_BREW_DEFAULT_GIT_REMOTE}"}" -HOMEBREW_CORE_GIT_REMOTE="${HOMEBREW_CORE_GIT_REMOTE:-"${HOMEBREW_CORE_DEFAULT_GIT_REMOTE}"}" -# The URLs with and without the '.git' suffix are the same Git remote. Do not prompt. -if [[ "${HOMEBREW_BREW_GIT_REMOTE}" == "${HOMEBREW_BREW_DEFAULT_GIT_REMOTE}.git" ]]; then - HOMEBREW_BREW_GIT_REMOTE="${HOMEBREW_BREW_DEFAULT_GIT_REMOTE}" -fi -if [[ "${HOMEBREW_CORE_GIT_REMOTE}" == "${HOMEBREW_CORE_DEFAULT_GIT_REMOTE}.git" ]]; then - HOMEBREW_CORE_GIT_REMOTE="${HOMEBREW_CORE_DEFAULT_GIT_REMOTE}" -fi -export HOMEBREW_{BREW,CORE}_GIT_REMOTE - -# TODO: bump version when new macOS is released or announced -MACOS_NEWEST_UNSUPPORTED="15.0" -# TODO: bump version when new macOS is released -MACOS_OLDEST_SUPPORTED="12.0" - -# For Homebrew on Linux -REQUIRED_RUBY_VERSION=2.6 # https://github.com/Homebrew/brew/pull/6556 -REQUIRED_GLIBC_VERSION=2.13 # https://docs.brew.sh/Homebrew-on-Linux#requirements -REQUIRED_CURL_VERSION=7.41.0 # HOMEBREW_MINIMUM_CURL_VERSION in brew.sh in Homebrew/brew -REQUIRED_GIT_VERSION=2.7.0 # HOMEBREW_MINIMUM_GIT_VERSION in brew.sh in Homebrew/brew - -# no analytics during installation -export HOMEBREW_NO_ANALYTICS_THIS_RUN=1 -export HOMEBREW_NO_ANALYTICS_MESSAGE_OUTPUT=1 - -unset HAVE_SUDO_ACCESS # unset this from the environment - -have_sudo_access() { - if [[ ! -x "/usr/bin/sudo" ]]; then - return 1 - fi - - local -a SUDO=("/usr/bin/sudo") - if [[ -n "${SUDO_ASKPASS-}" ]]; then - SUDO+=("-A") - elif [[ -n "${NONINTERACTIVE-}" ]]; then - SUDO+=("-n") - fi - - if [[ -z "${HAVE_SUDO_ACCESS-}" ]]; then - if [[ -n "${NONINTERACTIVE-}" ]]; then - "${SUDO[@]}" -l mkdir &> /dev/null - else - "${SUDO[@]}" -v && "${SUDO[@]}" -l mkdir &> /dev/null - fi - HAVE_SUDO_ACCESS="$?" - fi - - if [[ -n "${HOMEBREW_ON_MACOS-}" ]] && [[ "${HAVE_SUDO_ACCESS}" -ne 0 ]]; then - abort "Need sudo access on macOS (e.g. the user ${USER} needs to be an Administrator)!" - fi - - return "${HAVE_SUDO_ACCESS}" -} - -execute() { - if ! "$@"; then - abort "$(printf "Failed during: %s" "$(shell_join "$@")")" - fi -} - -execute_sudo() { - local -a args=("$@") - if [[ "${EUID:-${UID}}" != "0" ]] && have_sudo_access; then - if [[ -n "${SUDO_ASKPASS-}" ]]; then - args=("-A" "${args[@]}") - fi - ohai "/usr/bin/sudo" "${args[@]}" - execute "/usr/bin/sudo" "${args[@]}" - else - ohai "${args[@]}" - execute "${args[@]}" - fi -} - -getc() { - local save_state - save_state="$(/bin/stty -g)" - /bin/stty raw -echo - IFS='' read -r -n 1 -d '' "$@" - /bin/stty "${save_state}" -} - -ring_bell() { - # Use the shell's audible bell. - if [[ -t 1 ]]; then - printf "\a" - fi -} - -wait_for_user() { - local c - echo - echo "Press ${tty_bold}RETURN${tty_reset}/${tty_bold}ENTER${tty_reset} to continue or any other key to abort:" - getc c - # we test for \r and \n because some stuff does \r instead - if ! [[ "${c}" == $'\r' || "${c}" == $'\n' ]]; then - exit 1 - fi -} - -major_minor() { - echo "${1%%.*}.$( - x="${1#*.}" - echo "${x%%.*}" - )" -} - -version_gt() { - [[ "${1%.*}" -gt "${2%.*}" ]] || [[ "${1%.*}" -eq "${2%.*}" && "${1#*.}" -gt "${2#*.}" ]] -} -version_ge() { - [[ "${1%.*}" -gt "${2%.*}" ]] || [[ "${1%.*}" -eq "${2%.*}" && "${1#*.}" -ge "${2#*.}" ]] -} -version_lt() { - [[ "${1%.*}" -lt "${2%.*}" ]] || [[ "${1%.*}" -eq "${2%.*}" && "${1#*.}" -lt "${2#*.}" ]] -} - -check_run_command_as_root() { - [[ "${EUID:-${UID}}" == "0" ]] || return - - # Allow Azure Pipelines/GitHub Actions/Docker/Concourse/Kubernetes to do everything as root (as it's normal there) - [[ -f /.dockerenv ]] && return - [[ -f /run/.containerenv ]] && return - [[ -f /proc/1/cgroup ]] && grep -E "azpl_job|actions_job|docker|garden|kubepods" -q /proc/1/cgroup && return - - abort "Don't run this as root!" -} - -should_install_command_line_tools() { - if [[ -n "${HOMEBREW_ON_LINUX-}" ]]; then - return 1 - fi - - if version_gt "${macos_version}" "10.13"; then - ! [[ -e "/Library/Developer/CommandLineTools/usr/bin/git" ]] - else - ! [[ -e "/Library/Developer/CommandLineTools/usr/bin/git" ]] || - ! [[ -e "/usr/include/iconv.h" ]] - fi -} - -get_permission() { - "${STAT_PRINTF[@]}" "${PERMISSION_FORMAT}" "$1" -} - -user_only_chmod() { - [[ -d "$1" ]] && [[ "$(get_permission "$1")" != 75[0145] ]] -} - -exists_but_not_writable() { - [[ -e "$1" ]] && ! [[ -r "$1" && -w "$1" && -x "$1" ]] -} - -get_owner() { - "${STAT_PRINTF[@]}" "%u" "$1" -} - -file_not_owned() { - [[ "$(get_owner "$1")" != "$(id -u)" ]] -} - -get_group() { - "${STAT_PRINTF[@]}" "%g" "$1" -} - -file_not_grpowned() { - [[ " $(id -G "${USER}") " != *" $(get_group "$1") "* ]] -} - -# Please sync with 'test_ruby()' in 'Library/Homebrew/utils/ruby.sh' from the Homebrew/brew repository. -test_ruby() { - if [[ ! -x "$1" ]]; then - return 1 - fi - - "$1" --enable-frozen-string-literal --disable=gems,did_you_mean,rubyopt -rrubygems -e \ - "abort if Gem::Version.new(RUBY_VERSION.to_s.dup).to_s.split('.').first(2) != \ - Gem::Version.new('${REQUIRED_RUBY_VERSION}').to_s.split('.').first(2)" 2> /dev/null -} - -test_curl() { - if [[ ! -x "$1" ]]; then - return 1 - fi - - local curl_version_output curl_name_and_version - curl_version_output="$("$1" --version 2> /dev/null)" - curl_name_and_version="${curl_version_output%% (*}" - version_ge "$(major_minor "${curl_name_and_version##* }")" "$(major_minor "${REQUIRED_CURL_VERSION}")" -} - -test_git() { - if [[ ! -x "$1" ]]; then - return 1 - fi - - local git_version_output - git_version_output="$("$1" --version 2> /dev/null)" - if [[ "${git_version_output}" =~ "git version "([^ ]*).* ]]; then - version_ge "$(major_minor "${BASH_REMATCH[1]}")" "$(major_minor "${REQUIRED_GIT_VERSION}")" - else - abort "Unexpected Git version: '${git_version_output}'!" - fi -} - -# Search for the given executable in PATH (avoids a dependency on the `which` command) -which() { - # Alias to Bash built-in command `type -P` - type -P "$@" -} - -# Search PATH for the specified program that satisfies Homebrew requirements -# function which is set above -# shellcheck disable=SC2230 -find_tool() { - if [[ $# -ne 1 ]]; then - return 1 - fi - - local executable - while read -r executable; do - if [[ "${executable}" != /* ]]; then - warn "Ignoring ${executable} (relative paths don't work)" - elif "test_$1" "${executable}"; then - echo "${executable}" - break - fi - done < <(which -a "$1") -} - -no_usable_ruby() { - [[ -z "$(find_tool ruby)" ]] -} - -outdated_glibc() { - local glibc_version - glibc_version="$(ldd --version | head -n1 | grep -o '[0-9.]*$' | grep -o '^[0-9]\+\.[0-9]\+')" - version_lt "${glibc_version}" "${REQUIRED_GLIBC_VERSION}" -} - -if [[ -n "${HOMEBREW_ON_LINUX-}" ]] && no_usable_ruby && outdated_glibc; then - abort "$( - cat << EOABORT -Homebrew requires Ruby ${REQUIRED_RUBY_VERSION} which was not found on your system. -Homebrew portable Ruby requires Glibc version ${REQUIRED_GLIBC_VERSION} or newer, -and your Glibc version is too old. See: - ${tty_underline}https://docs.brew.sh/Homebrew-on-Linux#requirements${tty_reset} -Please install Ruby ${REQUIRED_RUBY_VERSION} and add its location to your PATH. -EOABORT - )" -fi - -# Invalidate sudo timestamp before exiting (if it wasn't active before). -if [[ -x /usr/bin/sudo ]] && ! /usr/bin/sudo -n -v 2> /dev/null; then - trap '/usr/bin/sudo -k' EXIT -fi - -# Things can fail later if `pwd` doesn't exist. -# Also sudo prints a warning message for no good reason -cd "/usr" || exit 1 - -####################################################################### script - -# shellcheck disable=SC2016 -ohai 'Checking for `sudo` access (which may request your password)...' - -if [[ -n "${HOMEBREW_ON_MACOS-}" ]]; then - [[ "${EUID:-${UID}}" == "0" ]] || have_sudo_access -elif ! [[ -w "${HOMEBREW_PREFIX}" ]] && - ! [[ -w "/home/linuxbrew" ]] && - ! [[ -w "/home" ]] && - ! have_sudo_access; then - abort "$( - cat << EOABORT -Insufficient permissions to install Homebrew to \"${HOMEBREW_PREFIX}\" (the default prefix). - -Alternative (unsupported) installation methods are available at: -https://docs.brew.sh/Installation#alternative-installs - -Please note this will require most formula to build from source, a buggy, slow and energy-inefficient experience. -We will close any issues without response for these unsupported configurations. -EOABORT - )" -fi -HOMEBREW_CORE="${HOMEBREW_REPOSITORY}/Library/Taps/homebrew/homebrew-core" - -check_run_command_as_root - -if [[ -d "${HOMEBREW_PREFIX}" && ! -x "${HOMEBREW_PREFIX}" ]]; then - abort "$( - cat << EOABORT -The Homebrew prefix ${tty_underline}${HOMEBREW_PREFIX}${tty_reset} exists but is not searchable. -If this is not intentional, please restore the default permissions and -try running the installer again: - sudo chmod 775 ${HOMEBREW_PREFIX} -EOABORT - )" -fi - -if [[ -n "${HOMEBREW_ON_MACOS-}" ]]; then - # On macOS, support 64-bit Intel and ARM - if [[ "${UNAME_MACHINE}" != "arm64" ]] && [[ "${UNAME_MACHINE}" != "x86_64" ]]; then - abort "Homebrew is only supported on Intel and ARM processors!" - fi -else - # On Linux, support only 64-bit Intel - if [[ "${UNAME_MACHINE}" == "aarch64" ]]; then - abort "$( - cat << EOABORT -Homebrew on Linux is not supported on ARM processors. - ${tty_underline}https://docs.brew.sh/Homebrew-on-Linux#arm-unsupported${tty_reset} -EOABORT - )" - elif [[ "${UNAME_MACHINE}" != "x86_64" ]]; then - abort "Homebrew on Linux is only supported on Intel processors!" - fi -fi - -if [[ -n "${HOMEBREW_ON_MACOS-}" ]]; then - macos_version="$(major_minor "$(/usr/bin/sw_vers -productVersion)")" - if version_lt "${macos_version}" "10.7"; then - abort "$( - cat << EOABORT -Your Mac OS X version is too old. See: - ${tty_underline}https://github.com/mistydemeo/tigerbrew${tty_reset} -EOABORT - )" - elif version_lt "${macos_version}" "10.11"; then - abort "Your OS X version is too old." - elif version_ge "${macos_version}" "${MACOS_NEWEST_UNSUPPORTED}" || - version_lt "${macos_version}" "${MACOS_OLDEST_SUPPORTED}"; then - who="We" - what="" - if version_ge "${macos_version}" "${MACOS_NEWEST_UNSUPPORTED}"; then - what="pre-release version" - else - who+=" (and Apple)" - what="old version" - fi - ohai "You are using macOS ${macos_version}." - ohai "${who} do not provide support for this ${what}." - - echo "$( - cat << EOS -This installation may not succeed. -After installation, you will encounter build failures with some formulae. -Please create pull requests instead of asking for help on Homebrew\'s GitHub, -Twitter or any other official channels. You are responsible for resolving any -issues you experience while you are running this ${what}. -EOS - ) -" | tr -d "\\" - fi -fi - -ohai "This script will install:" -echo "${HOMEBREW_PREFIX}/bin/brew" -echo "${HOMEBREW_PREFIX}/share/doc/homebrew" -echo "${HOMEBREW_PREFIX}/share/man/man1/brew.1" -echo "${HOMEBREW_PREFIX}/share/zsh/site-functions/_brew" -echo "${HOMEBREW_PREFIX}/etc/bash_completion.d/brew" -echo "${HOMEBREW_REPOSITORY}" - -# Keep relatively in sync with -# https://github.com/Homebrew/brew/blob/master/Library/Homebrew/keg.rb -directories=( - bin etc include lib sbin share opt var - Frameworks - etc/bash_completion.d lib/pkgconfig - share/aclocal share/doc share/info share/locale share/man - share/man/man1 share/man/man2 share/man/man3 share/man/man4 - share/man/man5 share/man/man6 share/man/man7 share/man/man8 - var/log var/homebrew var/homebrew/linked - bin/brew -) -group_chmods=() -for dir in "${directories[@]}"; do - if exists_but_not_writable "${HOMEBREW_PREFIX}/${dir}"; then - group_chmods+=("${HOMEBREW_PREFIX}/${dir}") - fi -done - -# zsh refuses to read from these directories if group writable -directories=(share/zsh share/zsh/site-functions) -zsh_dirs=() -for dir in "${directories[@]}"; do - zsh_dirs+=("${HOMEBREW_PREFIX}/${dir}") -done - -directories=( - bin etc include lib sbin share var opt - share/zsh share/zsh/site-functions - var/homebrew var/homebrew/linked - Cellar Caskroom Frameworks -) -mkdirs=() -for dir in "${directories[@]}"; do - if ! [[ -d "${HOMEBREW_PREFIX}/${dir}" ]]; then - mkdirs+=("${HOMEBREW_PREFIX}/${dir}") - fi -done - -user_chmods=() -mkdirs_user_only=() -if [[ "${#zsh_dirs[@]}" -gt 0 ]]; then - for dir in "${zsh_dirs[@]}"; do - if [[ ! -d "${dir}" ]]; then - mkdirs_user_only+=("${dir}") - elif user_only_chmod "${dir}"; then - user_chmods+=("${dir}") - fi - done -fi - -chmods=() -if [[ "${#group_chmods[@]}" -gt 0 ]]; then - chmods+=("${group_chmods[@]}") -fi -if [[ "${#user_chmods[@]}" -gt 0 ]]; then - chmods+=("${user_chmods[@]}") -fi - -chowns=() -chgrps=() -if [[ "${#chmods[@]}" -gt 0 ]]; then - for dir in "${chmods[@]}"; do - if file_not_owned "${dir}"; then - chowns+=("${dir}") - fi - if file_not_grpowned "${dir}"; then - chgrps+=("${dir}") - fi - done -fi - -if [[ "${#group_chmods[@]}" -gt 0 ]]; then - ohai "The following existing directories will be made group writable:" - printf "%s\n" "${group_chmods[@]}" -fi -if [[ "${#user_chmods[@]}" -gt 0 ]]; then - ohai "The following existing directories will be made writable by user only:" - printf "%s\n" "${user_chmods[@]}" -fi -if [[ "${#chowns[@]}" -gt 0 ]]; then - ohai "The following existing directories will have their owner set to ${tty_underline}${USER}${tty_reset}:" - printf "%s\n" "${chowns[@]}" -fi -if [[ "${#chgrps[@]}" -gt 0 ]]; then - ohai "The following existing directories will have their group set to ${tty_underline}${GROUP}${tty_reset}:" - printf "%s\n" "${chgrps[@]}" -fi -if [[ "${#mkdirs[@]}" -gt 0 ]]; then - ohai "The following new directories will be created:" - printf "%s\n" "${mkdirs[@]}" -fi - -if should_install_command_line_tools; then - ohai "The Xcode Command Line Tools will be installed." -fi - -non_default_repos="" -additional_shellenv_commands=() -if [[ "${HOMEBREW_BREW_DEFAULT_GIT_REMOTE}" != "${HOMEBREW_BREW_GIT_REMOTE}" ]]; then - ohai "HOMEBREW_BREW_GIT_REMOTE is set to a non-default URL:" - echo "${tty_underline}${HOMEBREW_BREW_GIT_REMOTE}${tty_reset} will be used as the Homebrew/brew Git remote." - non_default_repos="Homebrew/brew" - additional_shellenv_commands+=("export HOMEBREW_BREW_GIT_REMOTE=\"${HOMEBREW_BREW_GIT_REMOTE}\"") -fi - -if [[ "${HOMEBREW_CORE_DEFAULT_GIT_REMOTE}" != "${HOMEBREW_CORE_GIT_REMOTE}" ]]; then - ohai "HOMEBREW_CORE_GIT_REMOTE is set to a non-default URL:" - echo "${tty_underline}${HOMEBREW_CORE_GIT_REMOTE}${tty_reset} will be used as the Homebrew/homebrew-core Git remote." - non_default_repos="${non_default_repos:-}${non_default_repos:+ and }Homebrew/homebrew-core" - additional_shellenv_commands+=("export HOMEBREW_CORE_GIT_REMOTE=\"${HOMEBREW_CORE_GIT_REMOTE}\"") -fi - -if [[ -n "${HOMEBREW_NO_INSTALL_FROM_API-}" ]]; then - ohai "HOMEBREW_NO_INSTALL_FROM_API is set." - echo "Homebrew/homebrew-core will be tapped during this ${tty_bold}install${tty_reset} run." -fi - -if [[ -z "${NONINTERACTIVE-}" ]]; then - ring_bell - wait_for_user -fi - -if [[ -d "${HOMEBREW_PREFIX}" ]]; then - if [[ "${#chmods[@]}" -gt 0 ]]; then - execute_sudo "${CHMOD[@]}" "u+rwx" "${chmods[@]}" - fi - if [[ "${#group_chmods[@]}" -gt 0 ]]; then - execute_sudo "${CHMOD[@]}" "g+rwx" "${group_chmods[@]}" - fi - if [[ "${#user_chmods[@]}" -gt 0 ]]; then - execute_sudo "${CHMOD[@]}" "go-w" "${user_chmods[@]}" - fi - if [[ "${#chowns[@]}" -gt 0 ]]; then - execute_sudo "${CHOWN[@]}" "${USER}" "${chowns[@]}" - fi - if [[ "${#chgrps[@]}" -gt 0 ]]; then - execute_sudo "${CHGRP[@]}" "${GROUP}" "${chgrps[@]}" - fi -else - execute_sudo "${INSTALL[@]}" "${HOMEBREW_PREFIX}" -fi - -if [[ "${#mkdirs[@]}" -gt 0 ]]; then - execute_sudo "${MKDIR[@]}" "${mkdirs[@]}" - execute_sudo "${CHMOD[@]}" "ug=rwx" "${mkdirs[@]}" - if [[ "${#mkdirs_user_only[@]}" -gt 0 ]]; then - execute_sudo "${CHMOD[@]}" "go-w" "${mkdirs_user_only[@]}" - fi - execute_sudo "${CHOWN[@]}" "${USER}" "${mkdirs[@]}" - execute_sudo "${CHGRP[@]}" "${GROUP}" "${mkdirs[@]}" -fi - -if ! [[ -d "${HOMEBREW_REPOSITORY}" ]]; then - execute_sudo "${MKDIR[@]}" "${HOMEBREW_REPOSITORY}" -fi -execute_sudo "${CHOWN[@]}" "-R" "${USER}:${GROUP}" "${HOMEBREW_REPOSITORY}" - -if ! [[ -d "${HOMEBREW_CACHE}" ]]; then - if [[ -n "${HOMEBREW_ON_MACOS-}" ]]; then - execute_sudo "${MKDIR[@]}" "${HOMEBREW_CACHE}" - else - execute "${MKDIR[@]}" "${HOMEBREW_CACHE}" - fi -fi -if exists_but_not_writable "${HOMEBREW_CACHE}"; then - execute_sudo "${CHMOD[@]}" "g+rwx" "${HOMEBREW_CACHE}" -fi -if file_not_owned "${HOMEBREW_CACHE}"; then - execute_sudo "${CHOWN[@]}" "-R" "${USER}" "${HOMEBREW_CACHE}" -fi -if file_not_grpowned "${HOMEBREW_CACHE}"; then - execute_sudo "${CHGRP[@]}" "-R" "${GROUP}" "${HOMEBREW_CACHE}" -fi -if [[ -d "${HOMEBREW_CACHE}" ]]; then - execute "${TOUCH[@]}" "${HOMEBREW_CACHE}/.cleaned" -fi - -if should_install_command_line_tools && version_ge "${macos_version}" "10.13"; then - ohai "Searching online for the Command Line Tools" - # This temporary file prompts the 'softwareupdate' utility to list the Command Line Tools - clt_placeholder="/tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress" - execute_sudo "${TOUCH[@]}" "${clt_placeholder}" - - clt_label_command="/usr/sbin/softwareupdate -l | - grep -B 1 -E 'Command Line Tools' | - awk -F'*' '/^ *\\*/ {print \$2}' | - sed -e 's/^ *Label: //' -e 's/^ *//' | - sort -V | - tail -n1" - clt_label="$(chomp "$(/bin/bash -c "${clt_label_command}")")" - - if [[ -n "${clt_label}" ]]; then - ohai "Installing ${clt_label}" - execute_sudo "/usr/sbin/softwareupdate" "-i" "${clt_label}" - execute_sudo "/usr/bin/xcode-select" "--switch" "/Library/Developer/CommandLineTools" - fi - execute_sudo "/bin/rm" "-f" "${clt_placeholder}" -fi - -# Headless install may have failed, so fallback to original 'xcode-select' method -if should_install_command_line_tools && test -t 0; then - ohai "Installing the Command Line Tools (expect a GUI popup):" - execute "/usr/bin/xcode-select" "--install" - echo "Press any key when the installation has completed." - getc - execute_sudo "/usr/bin/xcode-select" "--switch" "/Library/Developer/CommandLineTools" -fi - -if [[ -n "${HOMEBREW_ON_MACOS-}" ]] && ! output="$(/usr/bin/xcrun clang 2>&1)" && [[ "${output}" == *"license"* ]]; then - abort "$( - cat << EOABORT -You have not agreed to the Xcode license. -Before running the installer again please agree to the license by opening -Xcode.app or running: - sudo xcodebuild -license -EOABORT - )" -fi - -USABLE_GIT=/usr/bin/git -if [[ -n "${HOMEBREW_ON_LINUX-}" ]]; then - USABLE_GIT="$(find_tool git)" - if [[ -z "$(command -v git)" ]]; then - abort "$( - cat << EOABORT - You must install Git before installing Homebrew. See: - ${tty_underline}https://docs.brew.sh/Installation${tty_reset} -EOABORT - )" - fi - if [[ -z "${USABLE_GIT}" ]]; then - abort "$( - cat << EOABORT - The version of Git that was found does not satisfy requirements for Homebrew. - Please install Git ${REQUIRED_GIT_VERSION} or newer and add it to your PATH. -EOABORT - )" - fi - if [[ "${USABLE_GIT}" != /usr/bin/git ]]; then - export HOMEBREW_GIT_PATH="${USABLE_GIT}" - ohai "Found Git: ${HOMEBREW_GIT_PATH}" - fi -fi - -if ! command -v curl > /dev/null; then - abort "$( - cat << EOABORT -You must install cURL before installing Homebrew. See: - ${tty_underline}https://docs.brew.sh/Installation${tty_reset} -EOABORT - )" -elif [[ -n "${HOMEBREW_ON_LINUX-}" ]]; then - USABLE_CURL="$(find_tool curl)" - if [[ -z "${USABLE_CURL}" ]]; then - abort "$( - cat << EOABORT -The version of cURL that was found does not satisfy requirements for Homebrew. -Please install cURL ${REQUIRED_CURL_VERSION} or newer and add it to your PATH. -EOABORT - )" - elif [[ "${USABLE_CURL}" != /usr/bin/curl ]]; then - export HOMEBREW_CURL_PATH="${USABLE_CURL}" - ohai "Found cURL: ${HOMEBREW_CURL_PATH}" - fi -fi - -ohai "Downloading and installing Homebrew..." -( - cd "${HOMEBREW_REPOSITORY}" > /dev/null || return - - # we do it in four steps to avoid merge errors when reinstalling - execute "${USABLE_GIT}" "-c" "init.defaultBranch=master" "init" "--quiet" - - # "git remote add" will fail if the remote is defined in the global config - execute "${USABLE_GIT}" "config" "remote.origin.url" "${HOMEBREW_BREW_GIT_REMOTE}" - execute "${USABLE_GIT}" "config" "remote.origin.fetch" "+refs/heads/*:refs/remotes/origin/*" - - # ensure we don't munge line endings on checkout - execute "${USABLE_GIT}" "config" "--bool" "core.autocrlf" "false" - - # make sure symlinks are saved as-is - execute "${USABLE_GIT}" "config" "--bool" "core.symlinks" "true" - - execute "${USABLE_GIT}" "fetch" "--force" "origin" - execute "${USABLE_GIT}" "fetch" "--force" "--tags" "origin" - execute "${USABLE_GIT}" "remote" "set-head" "origin" "--auto" > /dev/null - - LATEST_GIT_TAG="$("${USABLE_GIT}" tag --list --sort="-version:refname" | head -n1)" - if [[ -z "${LATEST_GIT_TAG}" ]]; then - abort "Failed to query latest Homebrew/brew Git tag." - fi - execute "${USABLE_GIT}" "checkout" "--force" "-B" "stable" "${LATEST_GIT_TAG}" - - if [[ "${HOMEBREW_REPOSITORY}" != "${HOMEBREW_PREFIX}" ]]; then - if [[ "${HOMEBREW_REPOSITORY}" == "${HOMEBREW_PREFIX}/Homebrew" ]]; then - execute "ln" "-sf" "../Homebrew/bin/brew" "${HOMEBREW_PREFIX}/bin/brew" - else - abort "The Homebrew/brew repository should be placed in the Homebrew prefix directory." - fi - fi - - if [[ -n "${HOMEBREW_NO_INSTALL_FROM_API-}" && ! -d "${HOMEBREW_CORE}" ]]; then - # Always use single-quoted strings with `exp` expressions - # shellcheck disable=SC2016 - ohai 'Tapping homebrew/core because `$HOMEBREW_NO_INSTALL_FROM_API` is set.' - ( - execute "${MKDIR[@]}" "${HOMEBREW_CORE}" - cd "${HOMEBREW_CORE}" > /dev/null || return - - execute "${USABLE_GIT}" "-c" "init.defaultBranch=master" "init" "--quiet" - execute "${USABLE_GIT}" "config" "remote.origin.url" "${HOMEBREW_CORE_GIT_REMOTE}" - execute "${USABLE_GIT}" "config" "remote.origin.fetch" "+refs/heads/*:refs/remotes/origin/*" - execute "${USABLE_GIT}" "config" "--bool" "core.autocrlf" "false" - execute "${USABLE_GIT}" "config" "--bool" "core.symlinks" "true" - execute "${USABLE_GIT}" "fetch" "--force" "origin" "refs/heads/master:refs/remotes/origin/master" - execute "${USABLE_GIT}" "remote" "set-head" "origin" "--auto" > /dev/null - execute "${USABLE_GIT}" "reset" "--hard" "origin/master" - - cd "${HOMEBREW_REPOSITORY}" > /dev/null || return - ) || exit 1 - fi - - execute "${HOMEBREW_PREFIX}/bin/brew" "update" "--force" "--quiet" -) || exit 1 - -if [[ ":${PATH}:" != *":${HOMEBREW_PREFIX}/bin:"* ]]; then - warn "${HOMEBREW_PREFIX}/bin is not in your PATH. - Instructions on how to configure your shell for Homebrew - can be found in the 'Next steps' section below." -fi - -ohai "Installation successful!" -echo - -ring_bell - -# Use an extra newline and bold to avoid this being missed. -ohai "Homebrew has enabled anonymous aggregate formulae and cask analytics." -echo "$( - cat << EOS -${tty_bold}Read the analytics documentation (and how to opt-out) here: - ${tty_underline}https://docs.brew.sh/Analytics${tty_reset} -No analytics data has been sent yet (nor will any be during this ${tty_bold}install${tty_reset} run). -EOS -) -" - -ohai "Homebrew is run entirely by unpaid volunteers. Please consider donating:" -echo "$( - cat << EOS - ${tty_underline}https://github.com/Homebrew/brew#donations${tty_reset} -EOS -) -" - -( - cd "${HOMEBREW_REPOSITORY}" > /dev/null || return - execute "${USABLE_GIT}" "config" "--replace-all" "homebrew.analyticsmessage" "true" - execute "${USABLE_GIT}" "config" "--replace-all" "homebrew.caskanalyticsmessage" "true" -) || exit 1 - -ohai "Next steps:" -case "${SHELL}" in -*/bash*) - if [[ -n "${HOMEBREW_ON_LINUX-}" ]]; then - shell_rcfile="${HOME}/.bashrc" - else - shell_rcfile="${HOME}/.bash_profile" - fi - ;; -*/zsh*) - if [[ -n "${HOMEBREW_ON_LINUX-}" ]]; then - shell_rcfile="${ZDOTDIR:-"${HOME}"}/.zshrc" - else - shell_rcfile="${ZDOTDIR:-"${HOME}"}/.zprofile" - fi - ;; -*/fish*) - shell_rcfile="${HOME}/.config/fish/config.fish" - ;; -*) - shell_rcfile="${ENV:-"${HOME}/.profile"}" - ;; -esac - -if grep -qs "eval \"\$(${HOMEBREW_PREFIX}/bin/brew shellenv)\"" "${shell_rcfile}"; then - if ! [[ -x "$(command -v brew)" ]]; then - cat << EOS -- Run this command in your terminal to add Homebrew to your ${tty_bold}PATH${tty_reset}: - eval "\$(${HOMEBREW_PREFIX}/bin/brew shellenv)" -EOS - fi -else - cat << EOS -- Run these two commands in your terminal to add Homebrew to your ${tty_bold}PATH${tty_reset}: - (echo; echo 'eval "\$(${HOMEBREW_PREFIX}/bin/brew shellenv)"') >> ${shell_rcfile} - eval "\$(${HOMEBREW_PREFIX}/bin/brew shellenv)" -EOS -fi - -if [[ -n "${non_default_repos}" ]]; then - plural="" - if [[ "${#additional_shellenv_commands[@]}" -gt 1 ]]; then - plural="s" - fi - printf -- "- Run these commands in your terminal to add the non-default Git remote%s for %s:\n" "${plural}" "${non_default_repos}" - printf " echo '# Set PATH, MANPATH, etc., for Homebrew.' >> %s\n" "${shell_rcfile}" - printf " echo '%s' >> ${shell_rcfile}\n" "${additional_shellenv_commands[@]}" - printf " %s\n" "${additional_shellenv_commands[@]}" -fi - -if [[ -n "${HOMEBREW_ON_LINUX-}" ]]; then - echo "- Install Homebrew's dependencies if you have sudo access:" - - if [[ -x "$(command -v apt-get)" ]]; then - echo " sudo apt-get install build-essential" - elif [[ -x "$(command -v yum)" ]]; then - echo " sudo yum groupinstall 'Development Tools'" - elif [[ -x "$(command -v pacman)" ]]; then - echo " sudo pacman -S base-devel" - elif [[ -x "$(command -v apk)" ]]; then - echo " sudo apk add build-base" - fi - - cat << EOS - For more information, see: - ${tty_underline}https://docs.brew.sh/Homebrew-on-Linux${tty_reset} -- We recommend that you install GCC: - brew install gcc -EOS -fi - -cat << EOS -- Run ${tty_bold}brew help${tty_reset} to get started -- Further documentation: - ${tty_underline}https://docs.brew.sh${tty_reset} - -EOS diff --git a/scripts/packaging/homebrew_release.sh b/scripts/packaging/homebrew_release.sh deleted file mode 100755 index 3caaf9f35ccd..000000000000 --- a/scripts/packaging/homebrew_release.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/sh -# - -# This script assume that homebrew is correctly installed -# using the script ./scripts/packaging/homebrew_install.sh -# and creates a formula scripts/packaging/Formula/octez.rb -# that is ready to be installed with brew - -# If it's a protected branch the value of $bucket will -# be set accordingly but the CI. -BUCKET="$GCP_LINUX_PACKAGES_BUCKET" - -# set version - -. scripts/version.sh -. scripts/ci/octez-release.sh - -# fetch tags for releases -git fetch -q --tags - -if [ -n "${gitlab_release_no_v:-}" ]; then - VERSION=$gitlab_release_no_v -elif [ -n "$CI_COMMIT_TAG" ]; then - VERSION=$(date +'%Y%m%d%H%M')+$CI_COMMIT_TAG -else - VERSION=$(date +'%Y%m%d%H%M')+$CI_COMMIT_SHORT_SHA -fi - -# prepare target dir - -# if it's a release tag, then it can be a RC release or a final release -if [ -n "${gitlab_release_no_v:-}" ]; then - # It a release tag, this can be either a real or test release - if [ -n "${gitlab_release_rc_version}" ]; then - # Release candidate - TARGETDIR="public/homebrew/RC/Formula" - else - # Release - TARGETDIR="public/homebrew/Formula" - fi -else - if [ "$CI_COMMIT_REF_PROTECTED" = "false" ]; then - if [ "$CI_COMMIT_REF_NAME" = "RC" ]; then - echo "Cannot create a repository for a branch named 'RC'" - exit 1 - else - # Branch is not protected, this is for testing ordinary MRs - TARGETDIR="public/homebrew/$CI_COMMIT_REF_NAME/Formula" - fi - else - # For protected branches that are not release, we allow - # a repository only for master. - if [ "$CI_COMMIT_REF_NAME" = "master" ]; then - TARGETDIR="public/homebrew/master/Formula" - else - if [ -n "${CI_COMMIT_TAG}" ]; then - TARGETDIR="public/homebrew/${CI_COMMIT_TAG}/Formula" - else - echo "Cannot create a repository for a protected branch that is not associated to a tag or master" - exit 1 - fi - fi - fi -fi - -# prepare formula - -mkdir -p "$TARGETDIR" - -#shellcheck disable=SC2046 -eval $(scripts/active_protocols.sh) -sed "s|%%VERSION%%|$VERSION|; \ - s|%%CI_MERGE_REQUEST_SOURCE_PROJECT_URL%%|$CI_MERGE_REQUEST_SOURCE_PROJECT_URL|; \ - s|%%CI_COMMIT_REF_NAME%%|$CI_COMMIT_REF_NAME|; \ - s|%%CI_PROJECT_NAMESPACE%%|$CI_PROJECT_NAMESPACE|; \ - s|%%PROTO_CURRENT%%|$PROTO_CURRENT|; s|%%PROTO_NEXT%%|$PROTO_NEXT|" \ - scripts/packaging/Formula/octez.rb.template > "$TARGETDIR/octez.rb" - -# upload to bucket - -if [ "$CI_COMMIT_REF_PROTECTED" = "true" ]; then - echo "### Logging into protected repo ..." - echo "${GCP_PROTECTED_SERVICE_ACCOUNT}" | base64 -d > protected_sa.json - gcloud auth activate-service-account --key-file=protected_sa.json -else - echo "### Logging into standard repo ..." - # Nothing to do -fi - -GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token) -export GOOGLE_OAUTH_ACCESS_TOKEN - -echo "Push to $BUCKET" - -gsutil -m cp -r public/* gs://"${BUCKET}" diff --git a/scripts/packaging/octez/homebrew/homebrew_release.sh b/scripts/packaging/octez/homebrew/homebrew_release.sh index feefbd71f4d7..0d221d4f1ce7 100755 --- a/scripts/packaging/octez/homebrew/homebrew_release.sh +++ b/scripts/packaging/octez/homebrew/homebrew_release.sh @@ -30,9 +30,8 @@ fi # prepare target dir -# if it's a release tag, then it can be a RC release or a final release if [ -n "${gitlab_release_no_v:-}" ]; then - # It a release tag, this can be either a real or test release + # if it's a release tag, then it can be a RC release or a final release if [ -n "${gitlab_release_rc_version}" ]; then # Release candidate TARGETDIR="public/homebrew/RC/Formula" diff --git a/scripts/packaging/octez/homebrew/tests/test_homebrew_install.sh b/scripts/packaging/octez/homebrew/tests/test_homebrew_install.sh new file mode 100755 index 000000000000..d95a68fa1537 --- /dev/null +++ b/scripts/packaging/octez/homebrew/tests/test_homebrew_install.sh @@ -0,0 +1,64 @@ +#!/bin/sh +# + +set -ue + +# This script assume that homebrew is correctly installed +# using the script ./scripts/packaging/homebrew_install.sh +# and creates a formula scripts/packaging/Formula/octez.rb +# that is ready to be installed with brew + +# If it's a protected branch the value of $bucket will +# be set accordingly but the CI. +BUCKET="$GCP_LINUX_PACKAGES_BUCKET" + +# set version + +. scripts/version.sh +. scripts/ci/octez-release.sh + +# prepare target dir + +if [ -n "${gitlab_release_no_v:-}" ]; then + # if it's a release tag, then it can be a RC release or a final release + if [ -n "${gitlab_release_rc_version}" ]; then + # Release candidate + TARGETDIR="homebrew/RC/Formula" + else + # Release + TARGETDIR="homebrew/Formula" + fi +else + if [ "$CI_COMMIT_REF_PROTECTED" = "false" ]; then + if [ "$CI_COMMIT_REF_NAME" = "RC" ]; then + echo "Cannot create a repository for a branch named 'RC'" + exit 1 + else + # Branch is not protected, this is for testing ordinary MRs + TARGETDIR="homebrew/$CI_COMMIT_REF_NAME/Formula" + fi + else + # For protected branches that are not release, we allow + # a repository only for master. + if [ "$CI_COMMIT_REF_NAME" = "master" ]; then + TARGETDIR="homebrew/master/Formula" + else + if [ -n "${CI_COMMIT_TAG}" ]; then + TARGETDIR="homebrew/${CI_COMMIT_TAG}/Formula" + else + echo "Cannot create a repository for a protected branch that is not associated to a tag or master" + exit 1 + fi + fi + fi +fi + +echo "installing formula from https://$BUCKET.storage.googleapis.com/$TARGETDIR/octez.rb" + +# get around the fact that we cannot install a formula directly from https +curl -q "https://$BUCKET.storage.googleapis.com/$TARGETDIR/octez.rb" -O +brew install -v ./octez.rb + +octez-node --version + +#brew audit --strict octez -- GitLab From ce0cd565cfb7528f87ea99c83e5d125b82290210 Mon Sep 17 00:00:00 2001 From: Pietro Abate Date: Mon, 16 Sep 2024 16:14:19 +0200 Subject: [PATCH 3/4] homebrew: run pipeline automatically in merge_release pipelines --- .gitlab/ci/pipelines/before_merging.yml | 68 +++++++++----- .../debian_repository_partial_auto.yml | 6 +- .gitlab/ci/pipelines/homebrew.yml | 61 +++++++++++++ .gitlab/ci/pipelines/homebrew_auto.yml | 61 +++++++++++++ .gitlab/ci/pipelines/merge_train.yml | 59 +++++++----- .gitlab/ci/pipelines/non_release_tag.yml | 8 +- .gitlab/ci/pipelines/non_release_tag_test.yml | 8 +- .../ci/pipelines/octez_beta_release_tag.yml | 8 +- .gitlab/ci/pipelines/octez_release_tag.yml | 8 +- .../ci/pipelines/octez_release_tag_test.yml | 8 +- .../ci/pipelines/schedule_extended_test.yml | 7 ++ .../schedule_master_test_release.yml | 35 ++++++- ci/bin/code_verification.ml | 50 +++++++--- ci/bin/common.ml | 40 +++----- ci/bin/homebrew.ml | 91 +++++++++++++++++++ ci/bin/release_tag.ml | 4 +- .../{octez/homebrew => }/homebrew_install.sh | 0 .../{octez/homebrew => }/homebrew_release.sh | 12 +-- .../tests => }/test_homebrew_install.sh | 6 +- 19 files changed, 412 insertions(+), 128 deletions(-) create mode 100644 .gitlab/ci/pipelines/homebrew.yml create mode 100644 .gitlab/ci/pipelines/homebrew_auto.yml create mode 100644 ci/bin/homebrew.ml rename scripts/packaging/{octez/homebrew => }/homebrew_install.sh (100%) rename scripts/packaging/{octez/homebrew => }/homebrew_release.sh (87%) rename scripts/packaging/{octez/homebrew/tests => }/test_homebrew_install.sh (93%) diff --git a/.gitlab/ci/pipelines/before_merging.yml b/.gitlab/ci/pipelines/before_merging.yml index e9e5db52e95f..d8fcd06e0544 100644 --- a/.gitlab/ci/pipelines/before_merging.yml +++ b/.gitlab/ci/pipelines/before_merging.yml @@ -2146,6 +2146,41 @@ trigger:rpm_repository_partial_auto: trigger: include: .gitlab/ci/pipelines/rpm_repository_partial_auto.yml +trigger:homebrew_auto: + stage: test + rules: + - changes: + - scripts/ci/install-gsutil.sh + - scripts/packaging/Formula/* + - scripts/packaging/homebrew_install.sh + - scripts/packaging/homebrew_release.sh + - scripts/packaging/test_homebrew_install.sh + when: on_success + needs: + - job: trigger + - job: sanity_ci + optional: true + - job: docker:hadolint + optional: true + - job: oc.ocaml_fmt + optional: true + - job: oc.semgrep + optional: true + - job: oc.misc_checks + optional: true + - job: check_jsonnet + optional: true + - job: check_rust_fmt + optional: true + - job: documentation:rst-check + optional: true + - job: nix + optional: true + - job: commit_titles + optional: true + trigger: + include: .gitlab/ci/pipelines/homebrew_auto.yml + kaitai_checks: image: ${ci_image_name}/build:${ci_image_tag} stage: test @@ -4675,6 +4710,15 @@ documentation:linkcheck: - make -C docs redirectcheck - make -C docs linkcheck +trigger:homebrew: + stage: manual + rules: + - when: manual + allow_failure: true + needs: [] + trigger: + include: .gitlab/ci/pipelines/homebrew.yml + trigger:rpm_repository_partial: stage: manual rules: @@ -4800,30 +4844,6 @@ oc.build:rpm:amd64: - fedora:39 - rockylinux:9.3 -oc.build:homebrew: - image: debian:bookworm - stage: manual - tags: - - gcp - rules: - - when: manual - allow_failure: true - needs: [] - dependencies: [] - timeout: 60 minutes - before_script: - - ./scripts/ci/install-gsutil.sh - - apt install -y git build-essential - - ./scripts/packaging/homebrew_install.sh - - eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv) - - ./scripts/packaging/homebrew_release.sh - script: - - apt install -y autoconf cmake libev-dev libffi-dev libgmp-dev libprotobuf-dev - libsqlite3-dev protobuf-compiler libhidapi-dev pkg-config zlib1g-dev libpq-dev - - ./scripts/packaging/test_homebrew_install.sh - variables: - CARGO_NET_OFFLINE: "false" - oc.script.docker_verify_image_arm64: image: ${GCP_REGISTRY}/tezos/docker-images/ci-docker:v1.12.0 stage: manual diff --git a/.gitlab/ci/pipelines/debian_repository_partial_auto.yml b/.gitlab/ci/pipelines/debian_repository_partial_auto.yml index 5b47c83f06ef..1145266587ef 100644 --- a/.gitlab/ci/pipelines/debian_repository_partial_auto.yml +++ b/.gitlab/ci/pipelines/debian_repository_partial_auto.yml @@ -216,7 +216,8 @@ apt_repo_debian_current: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh debian bookworm variables: @@ -237,7 +238,8 @@ apt_repo_debian: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh debian bookworm variables: diff --git a/.gitlab/ci/pipelines/homebrew.yml b/.gitlab/ci/pipelines/homebrew.yml new file mode 100644 index 000000000000..a80c5c3278ba --- /dev/null +++ b/.gitlab/ci/pipelines/homebrew.yml @@ -0,0 +1,61 @@ +# This file was automatically generated, do not edit. +# Edit file ci/bin/main.ml instead. + +workflow: + rules: + - if: $foo != "bar" || $foo == "bar" + when: always + +variables: + PIPELINE_TYPE: homebrew + +stages: +- start +- build + +datadog_pipeline_trace: + image: datadog/ci:v2.44.0 + stage: start + tags: + - gcp + dependencies: [] + allow_failure: true + timeout: 60 minutes + script: + - CI_MERGE_REQUEST_IID=${CI_MERGE_REQUEST_IID:-none} + - DATADOG_SITE=datadoghq.eu datadog-ci tag --level pipeline --tags pipeline_type:$PIPELINE_TYPE + --tags mr_number:$CI_MERGE_REQUEST_IID + +oc.install-homebrew: + image: debian:bookworm + stage: build + tags: + - gcp + needs: + - oc.build-homebrew + dependencies: [] + timeout: 60 minutes + before_script: + - apt-get update && apt-get install -y git curl + - ./scripts/packaging/homebrew_install.sh + - eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv) + script: + - apt-get install -y autoconf cmake g++ libev-dev libffi-dev libgmp-dev libprotobuf-dev + libsqlite3-dev protobuf-compiler libhidapi-dev pkg-config zlib1g-dev libpq-dev + - ./scripts/packaging/test_homebrew_install.sh + variables: + CARGO_NET_OFFLINE: "false" + +oc.build-homebrew: + image: debian:bookworm + stage: build + tags: + - gcp + dependencies: [] + timeout: 60 minutes + script: + - ./scripts/ci/install-gsutil.sh + - apt-get update && apt-get install -y git curl + - ./scripts/packaging/homebrew_release.sh + variables: + CARGO_NET_OFFLINE: "false" diff --git a/.gitlab/ci/pipelines/homebrew_auto.yml b/.gitlab/ci/pipelines/homebrew_auto.yml new file mode 100644 index 000000000000..fa1d9398cdfe --- /dev/null +++ b/.gitlab/ci/pipelines/homebrew_auto.yml @@ -0,0 +1,61 @@ +# This file was automatically generated, do not edit. +# Edit file ci/bin/main.ml instead. + +workflow: + rules: + - if: $foo != "bar" || $foo == "bar" + when: always + +variables: + PIPELINE_TYPE: homebrew_auto + +stages: +- start +- build + +datadog_pipeline_trace: + image: datadog/ci:v2.44.0 + stage: start + tags: + - gcp + dependencies: [] + allow_failure: true + timeout: 60 minutes + script: + - CI_MERGE_REQUEST_IID=${CI_MERGE_REQUEST_IID:-none} + - DATADOG_SITE=datadoghq.eu datadog-ci tag --level pipeline --tags pipeline_type:$PIPELINE_TYPE + --tags mr_number:$CI_MERGE_REQUEST_IID + +oc.install-homebrew: + image: debian:bookworm + stage: build + tags: + - gcp + needs: + - oc.build-homebrew + dependencies: [] + timeout: 60 minutes + before_script: + - apt-get update && apt-get install -y git curl + - ./scripts/packaging/homebrew_install.sh + - eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv) + script: + - apt-get install -y autoconf cmake g++ libev-dev libffi-dev libgmp-dev libprotobuf-dev + libsqlite3-dev protobuf-compiler libhidapi-dev pkg-config zlib1g-dev libpq-dev + - ./scripts/packaging/test_homebrew_install.sh + variables: + CARGO_NET_OFFLINE: "false" + +oc.build-homebrew: + image: debian:bookworm + stage: build + tags: + - gcp + dependencies: [] + timeout: 60 minutes + script: + - ./scripts/ci/install-gsutil.sh + - apt-get update && apt-get install -y git curl + - ./scripts/packaging/homebrew_release.sh + variables: + CARGO_NET_OFFLINE: "false" diff --git a/.gitlab/ci/pipelines/merge_train.yml b/.gitlab/ci/pipelines/merge_train.yml index 5b7ffe7da64f..cad98f9379eb 100644 --- a/.gitlab/ci/pipelines/merge_train.yml +++ b/.gitlab/ci/pipelines/merge_train.yml @@ -2146,6 +2146,41 @@ trigger:rpm_repository_partial_auto: trigger: include: .gitlab/ci/pipelines/rpm_repository_partial_auto.yml +trigger:homebrew_auto: + stage: test + rules: + - changes: + - scripts/ci/install-gsutil.sh + - scripts/packaging/Formula/* + - scripts/packaging/homebrew_install.sh + - scripts/packaging/homebrew_release.sh + - scripts/packaging/test_homebrew_install.sh + when: on_success + needs: + - job: trigger + - job: sanity_ci + optional: true + - job: docker:hadolint + optional: true + - job: oc.ocaml_fmt + optional: true + - job: oc.semgrep + optional: true + - job: oc.misc_checks + optional: true + - job: check_jsonnet + optional: true + - job: check_rust_fmt + optional: true + - job: documentation:rst-check + optional: true + - job: nix + optional: true + - job: commit_titles + optional: true + trigger: + include: .gitlab/ci/pipelines/homebrew_auto.yml + kaitai_checks: image: ${ci_image_name}/build:${ci_image_tag} stage: test @@ -4782,30 +4817,6 @@ oc.build:rpm:amd64: - fedora:39 - rockylinux:9.3 -oc.build:homebrew: - image: debian:bookworm - stage: manual - tags: - - gcp - rules: - - when: manual - allow_failure: true - needs: [] - dependencies: [] - timeout: 60 minutes - before_script: - - ./scripts/ci/install-gsutil.sh - - apt install -y git build-essential - - ./scripts/packaging/homebrew_install.sh - - eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv) - - ./scripts/packaging/homebrew_release.sh - script: - - apt install -y autoconf cmake libev-dev libffi-dev libgmp-dev libprotobuf-dev - libsqlite3-dev protobuf-compiler libhidapi-dev pkg-config zlib1g-dev libpq-dev - - ./scripts/packaging/test_homebrew_install.sh - variables: - CARGO_NET_OFFLINE: "false" - oc.script.docker_verify_image_arm64: image: ${GCP_REGISTRY}/tezos/docker-images/ci-docker:v1.12.0 stage: manual diff --git a/.gitlab/ci/pipelines/non_release_tag.yml b/.gitlab/ci/pipelines/non_release_tag.yml index 10ea5a810d70..9fe864cb824f 100644 --- a/.gitlab/ci/pipelines/non_release_tag.yml +++ b/.gitlab/ci/pipelines/non_release_tag.yml @@ -238,7 +238,7 @@ oc.build:rpm:amd64: - fedora:39 - rockylinux:9.3 -homebrew release: +oc.install-release-homebrew: image: debian:bookworm stage: build tags: @@ -256,7 +256,7 @@ homebrew release: name: build-$CI_COMMIT_REF_SLUG expire_in: 1 day paths: - - scripts/packaging/Formula/octez.rb + - public/homebrew/* when: on_success docker:merge_manifests: @@ -287,7 +287,7 @@ gitlab:publish: needs: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries - - homebrew release + - oc.install-release-homebrew - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a @@ -296,7 +296,7 @@ gitlab:publish: dependencies: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries - - homebrew release + - oc.install-release-homebrew - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a diff --git a/.gitlab/ci/pipelines/non_release_tag_test.yml b/.gitlab/ci/pipelines/non_release_tag_test.yml index 87af76978833..dff611b121ce 100644 --- a/.gitlab/ci/pipelines/non_release_tag_test.yml +++ b/.gitlab/ci/pipelines/non_release_tag_test.yml @@ -238,7 +238,7 @@ oc.build:rpm:amd64: - fedora:39 - rockylinux:9.3 -homebrew release: +oc.install-release-homebrew: image: debian:bookworm stage: build tags: @@ -256,7 +256,7 @@ homebrew release: name: build-$CI_COMMIT_REF_SLUG expire_in: 1 day paths: - - scripts/packaging/Formula/octez.rb + - public/homebrew/* when: on_success docker:merge_manifests: @@ -287,7 +287,7 @@ gitlab:publish: needs: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries - - homebrew release + - oc.install-release-homebrew - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a @@ -296,7 +296,7 @@ gitlab:publish: dependencies: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries - - homebrew release + - oc.install-release-homebrew - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a diff --git a/.gitlab/ci/pipelines/octez_beta_release_tag.yml b/.gitlab/ci/pipelines/octez_beta_release_tag.yml index d72b9446305b..631c5ab4a8ca 100644 --- a/.gitlab/ci/pipelines/octez_beta_release_tag.yml +++ b/.gitlab/ci/pipelines/octez_beta_release_tag.yml @@ -238,7 +238,7 @@ oc.build:rpm:amd64: - fedora:39 - rockylinux:9.3 -homebrew release: +oc.install-release-homebrew: image: debian:bookworm stage: build tags: @@ -256,7 +256,7 @@ homebrew release: name: build-$CI_COMMIT_REF_SLUG expire_in: 1 day paths: - - scripts/packaging/Formula/octez.rb + - public/homebrew/* when: on_success docker:merge_manifests: @@ -287,7 +287,7 @@ gitlab:release: needs: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries - - homebrew release + - oc.install-release-homebrew - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a @@ -296,7 +296,7 @@ gitlab:release: dependencies: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries - - homebrew release + - oc.install-release-homebrew - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a diff --git a/.gitlab/ci/pipelines/octez_release_tag.yml b/.gitlab/ci/pipelines/octez_release_tag.yml index b674d5d974b6..ebe1edf0073e 100644 --- a/.gitlab/ci/pipelines/octez_release_tag.yml +++ b/.gitlab/ci/pipelines/octez_release_tag.yml @@ -239,7 +239,7 @@ oc.build:rpm:amd64: - fedora:39 - rockylinux:9.3 -homebrew release: +oc.install-release-homebrew: image: debian:bookworm stage: build tags: @@ -257,7 +257,7 @@ homebrew release: name: build-$CI_COMMIT_REF_SLUG expire_in: 1 day paths: - - scripts/packaging/Formula/octez.rb + - public/homebrew/* when: on_success docker:merge_manifests: @@ -288,7 +288,7 @@ gitlab:release: needs: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries - - homebrew release + - oc.install-release-homebrew - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a @@ -297,7 +297,7 @@ gitlab:release: dependencies: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries - - homebrew release + - oc.install-release-homebrew - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a diff --git a/.gitlab/ci/pipelines/octez_release_tag_test.yml b/.gitlab/ci/pipelines/octez_release_tag_test.yml index 94e478fefcd8..79da0f0833b4 100644 --- a/.gitlab/ci/pipelines/octez_release_tag_test.yml +++ b/.gitlab/ci/pipelines/octez_release_tag_test.yml @@ -239,7 +239,7 @@ oc.build:rpm:amd64: - fedora:39 - rockylinux:9.3 -homebrew release: +oc.install-release-homebrew: image: debian:bookworm stage: build tags: @@ -257,7 +257,7 @@ homebrew release: name: build-$CI_COMMIT_REF_SLUG expire_in: 1 day paths: - - scripts/packaging/Formula/octez.rb + - public/homebrew/* when: on_success docker:merge_manifests: @@ -288,7 +288,7 @@ gitlab:release: needs: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries - - homebrew release + - oc.install-release-homebrew - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a @@ -297,7 +297,7 @@ gitlab:release: dependencies: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries - - homebrew release + - oc.install-release-homebrew - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a diff --git a/.gitlab/ci/pipelines/schedule_extended_test.yml b/.gitlab/ci/pipelines/schedule_extended_test.yml index cd0011881eeb..40948a0fc363 100644 --- a/.gitlab/ci/pipelines/schedule_extended_test.yml +++ b/.gitlab/ci/pipelines/schedule_extended_test.yml @@ -1505,6 +1505,13 @@ trigger:rpm_repository_full: trigger: include: .gitlab/ci/pipelines/rpm_repository_full.yml +trigger:homebrew: + stage: test + rules: + - when: always + trigger: + include: .gitlab/ci/pipelines/homebrew.yml + kaitai_checks: image: ${ci_image_name}/build:${ci_image_tag} stage: test diff --git a/.gitlab/ci/pipelines/schedule_master_test_release.yml b/.gitlab/ci/pipelines/schedule_master_test_release.yml index 9c6ae7f22ddf..ad0ae898753b 100644 --- a/.gitlab/ci/pipelines/schedule_master_test_release.yml +++ b/.gitlab/ci/pipelines/schedule_master_test_release.yml @@ -238,6 +238,27 @@ oc.build:rpm:amd64: - fedora:39 - rockylinux:9.3 +oc.install-release-homebrew: + image: debian:bookworm + stage: build + tags: + - gcp + needs: [] + dependencies: [] + timeout: 60 minutes + script: + - ./scripts/ci/install-gsutil.sh + - apt install -y git build-essential + - ./scripts/packaging/homebrew_install.sh + - eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv) + - ./scripts/packaging/homebrew_release.sh + artifacts: + name: build-$CI_COMMIT_REF_SLUG + expire_in: 1 day + paths: + - public/homebrew/* + when: on_success + docker:merge_manifests: image: ${GCP_REGISTRY}/tezos/docker-images/ci-docker:v1.12.0 stage: prepare_release @@ -266,6 +287,7 @@ gitlab:publish: needs: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries + - oc.install-release-homebrew - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a @@ -274,6 +296,7 @@ gitlab:publish: dependencies: - oc.build:static-x86_64-linux-binaries - oc.build:static-arm64-linux-binaries + - oc.install-release-homebrew - oc.build:rpm:amd64 - oc.build-ubuntu-current_a - oc.build-debian-current_a @@ -483,7 +506,8 @@ apt_repo_debian_current: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh debian bookworm variables: @@ -504,7 +528,8 @@ apt_repo_debian: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh debian bookworm variables: @@ -685,7 +710,8 @@ apt_repo_ubuntu_current: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh ubuntu noble jammy variables: @@ -706,7 +732,8 @@ apt_repo_ubuntu: timeout: 60 minutes before_script: - . ./scripts/version.sh - - ./scripts/ci/prepare-apt-repo.sh + - ./scripts/ci/install-gsutil.sh + - apt install -y apt-utils debsigs script: - ./scripts/ci/create_debian_repo.sh ubuntu noble jammy variables: diff --git a/ci/bin/code_verification.ml b/ci/bin/code_verification.ml index bed02242f8ba..7347ca3f82b7 100644 --- a/ci/bin/code_verification.ml +++ b/ci/bin/code_verification.ml @@ -831,6 +831,22 @@ let jobs pipeline_type = Rpm_repository.child_pipeline_full in + let job_homebrew_trigger_auto = + trigger_job + ~__POS__ + ~rules:(make_rules ~manual:No ~changes:changeset_homebrew ()) + ~stage:Stages.test + ~dependencies:dependencies_needs_start + Homebrew.child_pipeline_full_auto + in + let job_homebrew_trigger_full = + trigger_job + ~__POS__ + ~rules:(make_rules ~manual:No ~changes:changeset_homebrew ()) + ~stage:Stages.test + ~dependencies:dependencies_needs_start + Homebrew.child_pipeline_full + in (* check that ksy files are still up-to-date with octez *) let job_kaitai_checks : tezos_job = job @@ -1613,9 +1629,17 @@ let jobs pipeline_type = let jobs_debian = match pipeline_type with | Before_merging | Merge_train -> - [job_debian_repository_trigger_auto; job_rpm_repository_trigger_auto] + [ + job_debian_repository_trigger_auto; + job_rpm_repository_trigger_auto; + job_homebrew_trigger_auto; + ] | Schedule_extended_test -> - [job_debian_repository_trigger_full; job_rpm_repository_trigger_full] + [ + job_debian_repository_trigger_full; + job_rpm_repository_trigger_full; + job_homebrew_trigger_full; + ] in jobs_debian @ jobs_misc @ jobs_kernels @ jobs_unit @ jobs_install_octez @ jobs_tezt @@ -1811,6 +1835,16 @@ let jobs pipeline_type = ~stage:Stages.manual Rpm_repository.child_pipeline_partial in + let job_homebrew_repository_trigger : tezos_job = + (* We leave the possibility to run this pipeline manually, in particular + to generate the formula on scheduled pipelines *) + trigger_job + ~__POS__ + ~rules:(make_rules ~manual:Yes ()) + ~dependencies:(Dependent []) + ~stage:Stages.manual + Homebrew.child_pipeline_full + in match pipeline_type with | Before_merging | Merge_train -> (* Note: manual jobs in stage [manual] (which is the final @@ -1849,15 +1883,6 @@ let jobs pipeline_type = ~stage:Stages.manual () in - let job_build_homebrew_manual = - job_build_homebrew - ~__POS__ - ~name:"oc.build:homebrew" - ~rules:(make_rules ~manual:Yes ()) - ~dependencies:(Dependent []) - ~stage:Stages.manual - () - in let job_docker_verify_test_amd64 : tezos_job = job_docker_authenticated ~__POS__ @@ -1883,13 +1908,12 @@ let jobs pipeline_type = job_docker_amd64_test_manual; job_docker_arm64_test_manual; job_build_rpm_amd64_manual; - job_build_homebrew_manual; ] @ [job_docker_verify_test_arm64; job_docker_verify_test_amd64] in if pipeline_type = Merge_train then jobs else - job_rpm_repository_trigger_partial + job_homebrew_repository_trigger :: job_rpm_repository_trigger_partial :: job_debian_repository_trigger_partial :: jobs (* No manual jobs on the scheduled pipeline *) | Schedule_extended_test -> [] diff --git a/ci/bin/common.ml b/ci/bin/common.ml index 6d163bd1ca4b..ccd55e7002aa 100644 --- a/ci/bin/common.ml +++ b/ci/bin/common.ml @@ -524,6 +524,17 @@ let changeset_rpm_packages = "scripts/ci/create_rpm_repo.sh"; ]) +let changeset_homebrew = + Changeset.( + make + [ + "scripts/packaging/test_homebrew_install.sh"; + "scripts/packaging/homebrew_release.sh"; + "scripts/ci/install-gsutil.sh"; + "scripts/packaging/homebrew_install.sh"; + "scripts/packaging/Formula/*"; + ]) + (** The set of [changes:] that select opam jobs. Note: unlike all other changesets, this one does not include {!changeset_base}. @@ -1106,35 +1117,6 @@ let job_build_rpm_amd64 : unit -> tezos_job = ~arch:Amd64 ~dependencies:(Dependent []) -let job_build_homebrew ?rules ~__POS__ ~name ?(stage = Stages.build) - ?dependencies () : tezos_job = - let image = Images.debian_bookworm in - job - ?rules - ~__POS__ - ~name - ~arch:Amd64 - ?dependencies - ~image - ~stage - ~before_script: - [ - "./scripts/ci/install-gsutil.sh"; - "apt install -y git build-essential"; - "./scripts/packaging/homebrew_install.sh"; - "eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"; - "./scripts/packaging/homebrew_release.sh"; - ] - [ - (* These packages are needed on Linux. For macOS, Homebrew will - make those available locally. *) - "apt install -y autoconf cmake libev-dev libffi-dev libgmp-dev \ - libprotobuf-dev libsqlite3-dev protobuf-compiler libhidapi-dev \ - pkg-config zlib1g-dev libpq-dev"; - "./scripts/packaging/test_homebrew_install.sh"; - ] - |> enable_networked_cargo - let job_build_dynamic_binaries ?rules ~__POS__ ~arch ?(release = false) ?dependencies () = let arch_string = arch_to_string arch in diff --git a/ci/bin/homebrew.ml b/ci/bin/homebrew.ml new file mode 100644 index 000000000000..210da10309de --- /dev/null +++ b/ci/bin/homebrew.ml @@ -0,0 +1,91 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Nomadic Labs. *) +(* *) +(*****************************************************************************) + +open Tezos_ci +open Common + +type homebrew_pipeline = Full | Release + +let jobs pipeline_type : tezos_job list = + let image = Images.debian_bookworm in + let stage = Stages.build in + + (* this job creates a formula from a template + using the homebrew_release.sh script *) + let job_create_homebrew_formula : tezos_job = + job + ~__POS__ + ~name:"oc.build-homebrew" + ~arch:Amd64 + ~image + ~stage + [ + "./scripts/ci/install-gsutil.sh"; + "apt-get update && apt-get install -y git curl"; + "./scripts/packaging/homebrew_release.sh"; + ] + |> enable_networked_cargo + in + + (* this job tests if the formula created by job_create_homebrew_formula + can be compiled and installed *) + let job_build_homebrew_formula : tezos_job = + job + ~__POS__ + ~name:"oc.install-homebrew" + ~arch:Amd64 + ~image + ~stage + ~dependencies:(Dependent [Job job_create_homebrew_formula]) + ~before_script: + [ + "apt-get update && apt-get install -y git curl"; + "./scripts/packaging/homebrew_install.sh"; + "eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"; + ] + [ + (* These packages are needed on Linux. For macOS, Homebrew will + make those available locally. *) + "apt-get install -y autoconf cmake g++ libev-dev libffi-dev libgmp-dev \ + libprotobuf-dev libsqlite3-dev protobuf-compiler libhidapi-dev \ + pkg-config zlib1g-dev libpq-dev"; + "./scripts/packaging/test_homebrew_install.sh"; + ] + |> enable_networked_cargo + in + match pipeline_type with + | Release -> [job_create_homebrew_formula] + | Full -> [job_build_homebrew_formula; job_create_homebrew_formula] + +let child_pipeline_release = + let jobs : tezos_job list = jobs Release in + Pipeline.register_child + "homebrew_release" + ~description: + "A child pipeline of 'before_merging' (and thus 'merge_train') building \ + homebrew packages." + ~jobs + +let jobs pipeline_type = job_datadog_pipeline_trace :: jobs pipeline_type + +let child_pipeline_full = + let jobs = jobs Full in + Pipeline.register_child + "homebrew" + ~description: + "A child pipeline of 'schedule_extended_test' testing the build of \ + homebrew packages." + ~jobs + +let child_pipeline_full_auto = + let jobs = jobs Full in + Pipeline.register_child + "homebrew_auto" + ~description: + "A child pipeline of 'schedule_extended_test' testing the build of all \ + .deb packages. This pipelines starts automatically" + ~jobs diff --git a/ci/bin/release_tag.ml b/ci/bin/release_tag.ml index 33e8cf72cf10..88ad7dc754b1 100644 --- a/ci/bin/release_tag.ml +++ b/ci/bin/release_tag.ml @@ -99,11 +99,11 @@ let octez_jobs ?(test = false) release_tag_pipeline_type = ~expire_in:(Duration (Days 1)) ~name:"build-$CI_COMMIT_REF_SLUG" ~when_:On_success - ["scripts/packaging/Formula/octez.rb"] + ["public/homebrew/*"] in job ~__POS__ - ~name:"homebrew release" + ~name:"oc.install-release-homebrew" ~arch:Amd64 ~dependencies:(Dependent []) ~image:Images.debian_bookworm diff --git a/scripts/packaging/octez/homebrew/homebrew_install.sh b/scripts/packaging/homebrew_install.sh similarity index 100% rename from scripts/packaging/octez/homebrew/homebrew_install.sh rename to scripts/packaging/homebrew_install.sh diff --git a/scripts/packaging/octez/homebrew/homebrew_release.sh b/scripts/packaging/homebrew_release.sh similarity index 87% rename from scripts/packaging/octez/homebrew/homebrew_release.sh rename to scripts/packaging/homebrew_release.sh index 0d221d4f1ce7..8ff2d48a1511 100755 --- a/scripts/packaging/octez/homebrew/homebrew_release.sh +++ b/scripts/packaging/homebrew_release.sh @@ -1,9 +1,9 @@ #!/bin/sh # -# This script assume that homebrew is correctly installed +# This script assumes that homebrew is correctly installed # using the script ./scripts/packaging/homebrew_install.sh -# and creates a formula scripts/packaging/Formula/octez.rb +# and creates a formula scripts/packaging/octez/homebrew/Formula/octez.rb # that is ready to be installed with brew set -ue @@ -14,8 +14,8 @@ BUCKET="$GCP_LINUX_PACKAGES_BUCKET" # set version -. scripts/version.sh -. scripts/ci/octez-release.sh +. ./scripts/version.sh +. ./scripts/ci/octez-release.sh # fetch tags for releases git fetch -q --tags @@ -71,8 +71,8 @@ mkdir -p "$TARGETDIR" #shellcheck disable=SC2046 eval $(scripts/active_protocols.sh) sed "s|%%VERSION%%|$VERSION|; \ - s|%%CI_MERGE_REQUEST_SOURCE_PROJECT_URL%%|$CI_MERGE_REQUEST_SOURCE_PROJECT_URL|; \ - s|%%CI_COMMIT_REF_NAME%%|$CI_COMMIT_REF_NAME|; \ + s|%%CI_MERGE_REQUEST_SOURCE_PROJECT_URL%%|${CI_MERGE_REQUEST_SOURCE_PROJECT_URL:-$CI_PROJECT_URL}|; \ + s|%%CI_COMMIT_REF_NAME%%|${CI_COMMIT_REF_NAME:-master}|; \ s|%%CI_PROJECT_NAMESPACE%%|$CI_PROJECT_NAMESPACE|; \ s|%%PROTO_CURRENT%%|$PROTO_CURRENT|; s|%%PROTO_NEXT%%|$PROTO_NEXT|" \ scripts/packaging/octez/homebrew/Formula/octez.rb.template > "$TARGETDIR/octez.rb" diff --git a/scripts/packaging/octez/homebrew/tests/test_homebrew_install.sh b/scripts/packaging/test_homebrew_install.sh similarity index 93% rename from scripts/packaging/octez/homebrew/tests/test_homebrew_install.sh rename to scripts/packaging/test_homebrew_install.sh index d95a68fa1537..261f7beef42f 100755 --- a/scripts/packaging/octez/homebrew/tests/test_homebrew_install.sh +++ b/scripts/packaging/test_homebrew_install.sh @@ -3,10 +3,10 @@ set -ue -# This script assume that homebrew is correctly installed +# This script assumes that homebrew is correctly installed # using the script ./scripts/packaging/homebrew_install.sh # and creates a formula scripts/packaging/Formula/octez.rb -# that is ready to be installed with brew +# that is ready to be installed with brew. # If it's a protected branch the value of $bucket will # be set accordingly but the CI. @@ -60,5 +60,3 @@ curl -q "https://$BUCKET.storage.googleapis.com/$TARGETDIR/octez.rb" -O brew install -v ./octez.rb octez-node --version - -#brew audit --strict octez -- GitLab From 89f0230ef018d032238a5fd3cb12ade9e67dd165 Mon Sep 17 00:00:00 2001 From: Bruno Bernardo Date: Thu, 21 Nov 2024 12:26:29 +0100 Subject: [PATCH 4/4] homebrew: add [datadog_pipeline_trace] job --- ci/bin/homebrew.ml | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/ci/bin/homebrew.ml b/ci/bin/homebrew.ml index 210da10309de..e9df1caf9199 100644 --- a/ci/bin/homebrew.ml +++ b/ci/bin/homebrew.ml @@ -61,31 +61,20 @@ let jobs pipeline_type : tezos_job list = | Release -> [job_create_homebrew_formula] | Full -> [job_build_homebrew_formula; job_create_homebrew_formula] -let child_pipeline_release = - let jobs : tezos_job list = jobs Release in - Pipeline.register_child - "homebrew_release" - ~description: - "A child pipeline of 'before_merging' (and thus 'merge_train') building \ - homebrew packages." - ~jobs - let jobs pipeline_type = job_datadog_pipeline_trace :: jobs pipeline_type let child_pipeline_full = - let jobs = jobs Full in Pipeline.register_child "homebrew" ~description: "A child pipeline of 'schedule_extended_test' testing the build of \ homebrew packages." - ~jobs + ~jobs:(jobs Full) let child_pipeline_full_auto = - let jobs = jobs Full in Pipeline.register_child "homebrew_auto" ~description: - "A child pipeline of 'schedule_extended_test' testing the build of all \ - .deb packages. This pipelines starts automatically" - ~jobs + "A child pipeline of 'schedule_extended_test' testing the homebrew \ + packaging. This pipelines starts automatically" + ~jobs:(jobs Full) -- GitLab