-
Notifications
You must be signed in to change notification settings - Fork 10
Add support for macOS and allow building stacks-core from commit hash #39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
fd26fbd
36ab6fe
ba0aaed
b78fbfb
b9c9fda
048630c
ab82285
7974108
13cbe1f
ed7e82d
353bf71
d2f59b7
cab2e7e
2114df7
ba369e7
2572c6f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| name: CI | ||
|
|
||
| on: | ||
| pull_request: | ||
| workflow_dispatch: | ||
|
|
||
| jobs: | ||
| dry-run: | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| os: [ubuntu-latest, macos-latest] | ||
| runs-on: ${{ matrix.os }} | ||
| steps: | ||
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||
|
|
||
| - name: Install dependencies (Linux) | ||
| if: runner.os == 'Linux' | ||
| run: sudo apt-get update && sudo apt-get install -y zstd stress | ||
|
|
||
| - name: Install dependencies (macOS) | ||
| if: runner.os == 'macOS' | ||
| run: brew install zstd stress | ||
|
|
||
| - name: Verify Makefile parses and dependency check passes | ||
| run: make -n up | ||
|
|
||
| # Linux-only: macOS runners lack Docker. The Darwin Makefile branch is | ||
| # already covered by dry-run; the live stack itself is OS-independent. | ||
| live-run: | ||
| needs: dry-run | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 20 | ||
| steps: | ||
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||
|
|
||
| - name: Install dependencies | ||
| run: sudo apt-get update && sudo apt-get install -y zstd stress jq | ||
|
|
||
| - name: Boot network from chainstate archive | ||
| run: make up | ||
|
|
||
| - name: Wait for network to be live | ||
| run: | | ||
| for i in $(seq 1 30); do | ||
| if make test; then | ||
| echo "Network is live" | ||
| exit 0 | ||
| fi | ||
| echo "Attempt $i/30 — not ready yet, sleeping 10s" | ||
| sleep 10 | ||
| done | ||
| echo "Network did not become live within timeout" | ||
| exit 1 | ||
|
|
||
| - name: Tear down | ||
| if: always() | ||
| run: make down-force | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,9 +1,34 @@ | ||||||
| # List of binaries hacknet needs to function properly | ||||||
| COMMANDS := sudo tar zstd getent stress | ||||||
| $(foreach bin,$(COMMANDS),\ | ||||||
| $(if $(shell command -v $(bin) 2> /dev/null),$(info),$(error Missing required dependency: `$(bin)`))) | ||||||
| # OS Detection and Cross-Platform Support | ||||||
| UNAME_S := $(shell uname -s) | ||||||
| ifeq ($(UNAME_S),Darwin) | ||||||
| OS := macos | ||||||
| export UID := $(shell id -u) | ||||||
| export GID := $(shell id -g) | ||||||
| # macOS: use sysctl for CPU count | ||||||
| STRESS_CORES ?= $(shell sysctl -n hw.ncpu) | ||||||
| # List of binaries hacknet needs to function properly | ||||||
| COMMANDS := sudo tar zstd stress | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Same for the Linux branch ( |
||||||
| # macOS Docker Desktop maps host UID into its VM; running BSD tar via sudo | ||||||
| # restores archive ownership and leaves bind-mount sources unwritable. | ||||||
| # Extract as the current user so everything lands user-owned. | ||||||
| TAR_EXTRACT := tar -xf | ||||||
| else | ||||||
|
radu-stacks marked this conversation as resolved.
|
||||||
| OS := linux | ||||||
| # Linux: use getent | ||||||
| export UID := $(shell getent passwd $$(whoami) | cut -d":" -f 3) | ||||||
| export GID := $(shell getent passwd $$(whoami) | cut -d":" -f 4) | ||||||
| # Linux: use /proc/cpuinfo for CPU count | ||||||
| STRESS_CORES ?= $(shell cat /proc/cpuinfo | grep processor | wc -l) | ||||||
| # List of binaries hacknet needs to function properly | ||||||
| COMMANDS := sudo tar zstd getent stress | ||||||
| TAR_EXTRACT := sudo tar --same-owner -xf | ||||||
| endif | ||||||
|
|
||||||
| # Verify required dependencies exist | ||||||
| $(foreach bin,$(COMMANDS),$(if $(shell command -v $(bin) 2> /dev/null),$(info),$(error Missing required dependency: `$(bin)`))) | ||||||
| TARGET := $(firstword $(MAKECMDGOALS)) | ||||||
| PARAMS := $(filter-out $(TARGET),$(MAKECMDGOALS)) | ||||||
|
|
||||||
| # Hardcode the chainstate dir if we're booting from genesis | ||||||
| ifeq ($(TARGET),up-genesis) | ||||||
| export CHAINSTATE_DIR := $(PWD)/docker/chainstate/genesis | ||||||
|
|
@@ -12,9 +37,6 @@ ifeq ($(TARGET),genesis) | |||||
| export CHAINSTATE_DIR := $(PWD)/docker/chainstate/genesis | ||||||
| endif | ||||||
|
|
||||||
| # UID and GID are not currently used, but may be later to ensure consistent file permissions | ||||||
| export UID := $(shell getent passwd $$(whoami) | cut -d":" -f 3) | ||||||
| export GID := $(shell getent passwd $$(whoami) | cut -d":" -f 4) | ||||||
| EPOCH := $(shell date +%s) | ||||||
| PWD = $(shell pwd) | ||||||
| # Set a unique project name (used for checking if the network is running) | ||||||
|
|
@@ -26,22 +48,15 @@ SERVICES := $(shell CHAINSTATE_DIR="" docker compose -f docker/docker-compose.ym | |||||
| # Pauses the bitcoin miner script. Default is set to nearly 1 trillion blocks | ||||||
| PAUSE_HEIGHT ?= 999999999999 | ||||||
| # Used for the stress testing target. modifies how much cpu to consume for how long | ||||||
| STRESS_CORES ?= $(shell cat /proc/cpuinfo | grep processor | wc -l) | ||||||
| STRESS_TIMEOUT ?= 120 | ||||||
|
|
||||||
| # Create the chainstate dir and extract an archive to it when the "up" target is used | ||||||
| $(CHAINSTATE_DIR): /usr/bin/tar /usr/bin/zstd | ||||||
| @if [ ! -d "$(CHAINSTATE_DIR)" ]; then \ | ||||||
| mkdir -p $(CHAINSTATE_DIR) | ||||||
| @if [ "$(TARGET)" = "up" ]; then | ||||||
| if [ -f "$(CHAINSTATE_ARCHIVE)" ]; then | ||||||
| sudo tar --same-owner -xf $(CHAINSTATE_ARCHIVE) -C $(CHAINSTATE_DIR) || exit 1 | ||||||
| else | ||||||
| @echo "Chainstate archive ($(CHAINSTATE_ARCHIVE)) not found. Exiting" | ||||||
| rm -rf $(CHAINSTATE_DIR) | ||||||
| exit 1 | ||||||
| fi | ||||||
| fi | ||||||
| $(CHAINSTATE_DIR): | ||||||
|
wileyj marked this conversation as resolved.
|
||||||
| @if [ ! -d "$(CHAINSTATE_DIR)" ]; then mkdir -p $(CHAINSTATE_DIR) && \ | ||||||
| if [ "$(TARGET)" = "up" ]; then \ | ||||||
| [ -f "$(CHAINSTATE_ARCHIVE)" ] && $(TAR_EXTRACT) $(CHAINSTATE_ARCHIVE) -C $(CHAINSTATE_DIR) || \ | ||||||
| { echo "Chainstate archive ($(CHAINSTATE_ARCHIVE)) not found. Exiting"; rm -rf $(CHAINSTATE_DIR); exit 1; }; \ | ||||||
| fi; \ | ||||||
|
radu-stacks marked this conversation as resolved.
|
||||||
| fi | ||||||
|
|
||||||
| # Build the images with a cache if present | ||||||
|
|
@@ -70,33 +85,26 @@ check-not-running: | |||||
|
|
||||||
| # If the network is not running, we need to exit (ex: trying to restart a container) | ||||||
| check-running: | ||||||
| @if test ! `docker compose ls --filter name=$(PROJECT) -q`; then \ | ||||||
| echo "Network not running. exiting"; \ | ||||||
| exit 1; \ | ||||||
| fi | ||||||
| @test `docker compose ls --filter name=$(PROJECT) -q` || { echo "Network not running. exiting"; exit 1; } | ||||||
|
|
||||||
| # For targets that need an arg, check that *something* is provided. it not, exit | ||||||
| # For targets that need an arg, check that *something* is provided. if not, exit | ||||||
| check-params: | check-running | ||||||
| @if [ ! "$(PARAMS)" ]; then \ | ||||||
| echo "No service defined. Exiting"; \ | ||||||
| exit 1; \ | ||||||
| fi | ||||||
| @[ "$(PARAMS)" ] || { echo "No service defined. Exiting"; exit 1; } | ||||||
|
|
||||||
| # Boot the network from a local chainstate archive | ||||||
| up: check-not-running | build $(CHAINSTATE_DIR) | ||||||
| @echo "Starting $(PROJECT) network from chainstate archive" | ||||||
| @echo " OS: $(OS)" | ||||||
|
radu-stacks marked this conversation as resolved.
|
||||||
| @echo " Chainstate Dir: $(CHAINSTATE_DIR)" | ||||||
| @echo " Chainstate Archive: $(CHAINSTATE_ARCHIVE)" | ||||||
| echo "$(CHAINSTATE_DIR)" > .current-chainstate-dir | ||||||
| docker compose -f docker/docker-compose.yml --profile default -p $(PROJECT) up -d | ||||||
|
|
||||||
| # Boot the network from genesis | ||||||
| genesis: check-not-running | build $(CHAINSTATE_DIR) /usr/bin/sudo | ||||||
| genesis: check-not-running | build $(CHAINSTATE_DIR) | ||||||
| @echo "Starting $(PROJECT) network from genesis" | ||||||
| @if [ -d "$(CHAINSTATE_DIR)" ]; then \ | ||||||
| echo " Removing existing genesis chainstate dir: $(CHAINSTATE_DIR)"; \ | ||||||
| sudo rm -rf $(CHAINSTATE_DIR); \ | ||||||
| fi | ||||||
| @echo " OS: $(OS)" | ||||||
| @[ -d "$(CHAINSTATE_DIR)" ] && { echo " Removing existing genesis chainstate dir: $(CHAINSTATE_DIR)"; sudo rm -rf $(CHAINSTATE_DIR); } | ||||||
| @echo " Chainstate Dir: $(CHAINSTATE_DIR)" | ||||||
| mkdir -p "$(CHAINSTATE_DIR)" | ||||||
| echo "$(CHAINSTATE_DIR)" > .current-chainstate-dir | ||||||
|
|
@@ -117,9 +125,7 @@ down-prom: | |||||
| down: backup-logs current-chainstate-dir | ||||||
| @echo "Shutting down $(PROJECT) network" | ||||||
| docker compose -f docker/docker-compose.yml --profile default -p $(PROJECT) down | ||||||
| @if [ -f .current-chainstate-dir ]; then \ | ||||||
| rm -f .current-chainstate-dir | ||||||
| fi | ||||||
| @[ -f .current-chainstate-dir ] && rm -f .current-chainstate-dir | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both It bites in the two spots where you'd least want it to.
Suggested change
|
||||||
|
|
||||||
| # Secondary name to bring down the genesis network | ||||||
| down-genesis: down | ||||||
|
|
@@ -128,9 +134,7 @@ down-genesis: down | |||||
| down-force: | ||||||
| @echo "Force Shutting down $(PROJECT) network" | ||||||
| docker compose -f docker/docker-compose.yml --profile default -p $(PROJECT) down | ||||||
| @if [ -f .current-chainstate-dir ]; then \ | ||||||
| rm -f .current-chainstate-dir | ||||||
| fi | ||||||
| @[ -f .current-chainstate-dir ] && rm -f .current-chainstate-dir | ||||||
|
|
||||||
| # Stream specified service logs to STDOUT. Does not validate if PARAMS is supplied | ||||||
| log: current-chainstate-dir | ||||||
|
|
@@ -142,31 +146,21 @@ log-all: current-chainstate-dir | |||||
| docker compose -f docker/docker-compose.yml --profile default -p $(PROJECT) logs -t -f | ||||||
|
|
||||||
| # Backup all service logs to $ACTIVE_CHAINSTATE_DIR/logs/<service-name>.log | ||||||
| backup-logs: current-chainstate-dir /usr/bin/sudo | ||||||
| backup-logs: current-chainstate-dir | ||||||
| @if [ -f .current-chainstate-dir ]; then \ | ||||||
| $(eval ACTIVE_CHAINSTATE_DIR=$(shell cat .current-chainstate-dir)) | ||||||
| if [ ! -d "$(ACTIVE_CHAINSTATE_DIR)" ]; then \ | ||||||
| echo "Chainstate Dir ($(ACTIVE_CHAINSTATE_DIR)) not found";\ | ||||||
| exit 1; \ | ||||||
| fi; \ | ||||||
| if [ ! -d "$(ACTIVE_CHAINSTATE_DIR)/logs" ]; then \ | ||||||
| mkdir -p $(ACTIVE_CHAINSTATE_DIR)/logs;\ | ||||||
| fi; \ | ||||||
| $(eval ACTIVE_CHAINSTATE_DIR=$(shell cat .current-chainstate-dir)) \ | ||||||
| [ -d "$(ACTIVE_CHAINSTATE_DIR)" ] || { echo "Chainstate Dir ($(ACTIVE_CHAINSTATE_DIR)) not found"; exit 1; }; \ | ||||||
| mkdir -p $(ACTIVE_CHAINSTATE_DIR)/logs; \ | ||||||
| echo "Backing up logs to $(ACTIVE_CHAINSTATE_DIR)/logs"; \ | ||||||
| for service in $(SERVICES); do \ | ||||||
| docker logs -t $$service > $(ACTIVE_CHAINSTATE_DIR)/logs/$$service.log 2>&1; \ | ||||||
| done; \ | ||||||
| for service in $(SERVICES); do docker logs -t $$service > $(ACTIVE_CHAINSTATE_DIR)/logs/$$service.log 2>&1; done; \ | ||||||
| fi | ||||||
|
|
||||||
| # Replace the existing chainstate archive. Will be used with target `up` | ||||||
| snapshot: current-chainstate-dir down | ||||||
| @echo "Creating $(PROJECT) chainstate snapshot from $(ACTIVE_CHAINSTATE_DIR)" | ||||||
| @if [ -d "$(ACTIVE_CHAINSTATE_DIR)/logs" ]; then \ | ||||||
| rm -rf $(ACTIVE_CHAINSTATE_DIR)/logs; \ | ||||||
| fi | ||||||
| @[ -d "$(ACTIVE_CHAINSTATE_DIR)/logs" ] && rm -rf $(ACTIVE_CHAINSTATE_DIR)/logs | ||||||
| @echo "Creating snapshot: $(CHAINSTATE_ARCHIVE)" | ||||||
| @echo "cd $(ACTIVE_CHAINSTATE_DIR); sudo tar --zstd -cf $(CHAINSTATE_ARCHIVE) *; cd $(PWD)" | ||||||
| cd $(ACTIVE_CHAINSTATE_DIR); sudo tar --zstd -cf $(CHAINSTATE_ARCHIVE) *; cd $(PWD) | ||||||
| (cd $(ACTIVE_CHAINSTATE_DIR) && sudo tar --zstd -cf $(CHAINSTATE_ARCHIVE) *) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The no-sudo |
||||||
|
|
||||||
| # Pause all services in the network (netork is down, but recoverably with target 'unpause') | ||||||
| pause: | ||||||
|
|
@@ -220,5 +214,5 @@ monitor: | |||||
| clean: down-force | ||||||
| sudo rm -rf ./docker/chainstate/* | ||||||
|
|
||||||
| .PHONY: build build-no-cache current-chainstate-dir check-not-running check-running check-params up genesis up-genesis down down-genesis down-force log log-all backup-logs snapshot pause unpause stop start restart stress test monitor clean | ||||||
| .PHONY: build build-no-cache current-chainstate-dir check-not-running check-running check-params up genesis up-genesis down down-genesis down-force log log-all backup-logs snapshot pause unpause stop start restart stress test monitor clean up-prom down-prom | ||||||
| .ONESHELL: all-in-one-shell | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
timeout-minutes: 20, butmake upcold-builds stacks-core from source (stacks-nodeandstacks-signer) with no caching anywhere in the repo. A cold 2-core compile of those two binaries might run past 20 minutes so in practice this might time out during the build and never reachesmake test.We could add buildx
cache-from/to: type=gha, raise the timeout to around 60, and add aconcurrency:group (withlinter.ymlyou now have twopull_requestworkflows and neither cancels an in-progress run). Or even better, we could pull a prebuilt stacks-core image, oractions/cachethe binary keyed on the resolved commit SHA, and move the from-source build to a schedule orworkflow_dispatch.One more thing: the macOS leg only runs
make -n, so the single OS-specific step, the zstd extract, never actually runs on a runner. A quicktar -xf docker/chainstate.tar.zstdinto a temp dir on that leg would at least smoke-test the codec