Ctrl K
ComunidadGuías…

Makefile

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
PROJECTDIR := $(shell pwd)

# Discover Helm charts that have a corresponding Replicated HelmChart manifest.
# Charts without a manifest (e.g. subcharts only used as dependencies) are
# excluded from the Replicated release to avoid lint errors.
CHARTDIR    := $(PROJECTDIR)/charts
MANIFESTDIR := $(PROJECTDIR)/replicated
CHARTS      := $(shell for f in $(MANIFESTDIR)/*.yaml $(MANIFESTDIR)/*.yml; do \
                  name=$$(yq '.spec.chart.name // ""' "$$f" 2>/dev/null); \
                  [ -n "$$name" ] && [ -d $(CHARTDIR)/$$name ] && echo $$name; \
                done | sort -u)

# Discover all Replicated manifest files
MANIFESTS   := $(shell find $(MANIFESTDIR) -name '*.yaml' -o -name '*.yml')

# All Chart.yaml files — used as dependencies so manifest builds re-run when any chart version changes
CHART_YAMLS := $(shell find $(CHARTDIR) -name 'Chart.yaml')

# Release metadata: version comes from the openhands chart, channel from the current git branch
VERSION     ?= $(shell yq .version $(CHARTDIR)/openhands/Chart.yaml)
REPLICATED_APP ?= openhands
BRANCH      := $(shell git branch --show-current)
CHANNEL     := $(BRANCH)
ifeq ($(CHANNEL), main)
	CHANNEL=Unstable
endif

# Guard: releasing from the main branch (which maps to the Unstable channel)
# or to the Unstable channel directly is reserved for CI. Require an explicit
# opt-in flag so a human can't accidentally publish local work to Unstable.
ALLOW_MAIN_RELEASE ?=

BUILDDIR      := $(PROJECTDIR)/build
RELEASE_FILES :=
RELEASE_CHART_PACKAGES = $(filter %.tgz,$(RELEASE_FILES))

# ── Manifest targets ────────────────────────────────────────────────
# For each replicated manifest, generate a build rule that:
#   1. Copies the source YAML into build/
#   2. If the manifest references a chart (spec.chart.name), injects the
#      matching chartVersion from charts/<name>/Chart.yaml
#
# This means replicated manifests don't need to hardcode chart versions —
# they're always pulled from the chart source of truth at build time.
#
# Note on escaping: this macro is expanded via $(eval $(call ...)), which
# double-expands variables. Shell variable references need $$$$ to survive
# both passes and arrive as $VAR in the shell. Make variables use $$ to
# defer expansion to recipe execution time.
define make-manifest-target
$(BUILDDIR)/$(notdir $1): $1 $(CHART_YAMLS) | $$(BUILDDIR)
	cp $1 $$(BUILDDIR)/$$(notdir $1)
	@CHART_NAME=$$$$(yq '.spec.chart.name // ""' $$(BUILDDIR)/$$(notdir $1)); \
	if [ -n "$$$$CHART_NAME" ] && [ -f $(CHARTDIR)/$$$$CHART_NAME/Chart.yaml ]; then \
		CHART_VER=$$$$(yq .version $(CHARTDIR)/$$$$CHART_NAME/Chart.yaml); \
		yq -i ".spec.chart.chartVersion = \"$$$$CHART_VER\"" $$(BUILDDIR)/$$(notdir $1); \
		echo "Updated $$(notdir $1) chartVersion to $$$$CHART_VER"; \
	fi
RELEASE_FILES := $(RELEASE_FILES) $(BUILDDIR)/$(notdir $1)
manifests:: $(BUILDDIR)/$(notdir $1)
endef
$(foreach element,$(MANIFESTS),$(eval $(call make-manifest-target,$(element))))

# ── Chart targets ───────────────────────────────────────────────────
# For each Helm chart, package it into a versioned .tgz in build/.
# Dependencies include all yaml/tpl/schema files so changes trigger a rebuild.
define make-chart-target
$(eval VER := $(shell yq .version $(CHARTDIR)/$1/Chart.yaml))
$(BUILDDIR)/$1-$(VER).tgz : $(CHARTDIR)/$1 $(shell find $(CHARTDIR)/$1 -name '*.yaml' -o -name '*.yml' -o -name "*.tpl" -o -name "NOTES.txt" -o -name "values.schema.json") | $$(BUILDDIR)
	@# Rewrite any dependency that points to a remote registry but exists as a
	@# sibling chart to use a local file:// reference instead. This lets
	@# `helm package -u` resolve unpublished chart versions during local builds.
	@# The copy lives outside the chart directory. Held inside it, `helm package`
	@# picks it up and every released chart ships a Chart.yaml.bak alongside the
	@# real one, because the restore only runs after packaging.
	@# Chart.lock is restored for the same reason: `helm package -u` regenerates it
	@# to match the rewritten repositories, and a lock describing a Chart.yaml that
	@# no longer exists fails `helm dependency build` with an out-of-sync error.
	@mkdir -p $(BUILDDIR)/.chartbak/$1
	@cp $(CHARTDIR)/$1/Chart.yaml $(BUILDDIR)/.chartbak/$1/Chart.yaml
	@if [ -f $(CHARTDIR)/$1/Chart.lock ]; then cp $(CHARTDIR)/$1/Chart.lock $(BUILDDIR)/.chartbak/$1/Chart.lock; fi
	@trap 'mv $(BUILDDIR)/.chartbak/$1/Chart.yaml $(CHARTDIR)/$1/Chart.yaml; \
		if [ -f $(BUILDDIR)/.chartbak/$1/Chart.lock ]; then mv $(BUILDDIR)/.chartbak/$1/Chart.lock $(CHARTDIR)/$1/Chart.lock; fi' EXIT; \
	for dep in $$$$(yq -r '.dependencies[].name // ""' $(CHARTDIR)/$1/Chart.yaml); do \
		if [ -d $(CHARTDIR)/$$$$dep ]; then \
			yq -i "(.dependencies[] | select(.name == \"$$$$dep\")).repository = \"file://../$$$$dep\"" $(CHARTDIR)/$1/Chart.yaml; \
		fi; \
	done; \
	n=0; until helm package -u $(CHARTDIR)/$1 -d $(BUILDDIR)/; do \
		n=$$$$((n+1)); \
		if [ $$$$n -ge 5 ]; then echo "helm package failed after $$$$n attempts"; exit 1; fi; \
		echo "helm package failed (likely transient upstream chart download); retry $$$$n/5 in $$$$((n*15))s"; \
		sleep $$$$((n*15)); \
	done
RELEASE_FILES := $(RELEASE_FILES) $(BUILDDIR)/$1-$(VER).tgz
charts:: $(BUILDDIR)/$1-$(VER).tgz
endef
$(foreach element,$(CHARTS),$(eval $(call make-chart-target,$(element))))

$(BUILDDIR):
	mkdir -p $(BUILDDIR)

# ── Phony targets ───────────────────────────────────────────────────

# Remove generated release output and ignored Helm dependency archives. Runs
# before lint/release so stale subchart archives cannot contaminate packages.
.PHONY: clean
clean:
	rm -rf $(BUILDDIR)
	find $(CHARTDIR) -path '*/charts/*.tgz' -type f -exec rm -f {} +

# Fail if any packaged chart contains duplicate archive paths. Duplicate paths
# let stale dependency contents win during extraction even when sources are new.
.PHONY: check-duplicate-chart-entries
check-duplicate-chart-entries: $(RELEASE_CHART_PACKAGES)
	@set -eu; \
	for chart in $(RELEASE_CHART_PACKAGES); do \
		listing=$$(tar tzf "$$chart") || { echo "ERROR: failed to list $$chart"; exit 1; }; \
		duplicates=$$(printf '%s\n' "$$listing" | sort | uniq -d); \
		if [ -n "$$duplicates" ]; then \
			echo "ERROR: $$chart contains duplicate archive paths:"; \
			echo "$$duplicates"; \
			exit 1; \
		fi; \
	done

# Validate all built manifests and charts with the Replicated linter
.PHONY: lint
lint: clean $(RELEASE_FILES) check-duplicate-chart-entries
	replicated release lint --app $(REPLICATED_APP) --yaml-dir $(BUILDDIR)

# Refuse to release from main or to the Unstable channel unless explicitly
# allowed via ALLOW_MAIN_RELEASE=1. CI passes this flag; humans should not.
.PHONY: check-release-guard
check-release-guard:
	@if [ -z "$(ALLOW_MAIN_RELEASE)" ] && { [ "$(BRANCH)" = "main" ] || [ "$(CHANNEL)" = "Unstable" ]; }; then \
		echo "ERROR: refusing to release from 'main' or to the 'Unstable' channel (branch=$(BRANCH) channel=$(CHANNEL))."; \
		echo "       This is reserved for CI. If you really mean to do this, re-run with ALLOW_MAIN_RELEASE=1."; \
		exit 1; \
	fi

# Echo the channel `release` publishes to, so CI can pin a deploy to it without
# re-deriving the branch mapping.
.PHONY: print-channel
print-channel:
	@echo $(CHANNEL)

# Build everything, lint, then publish a release to the Replicated channel
.PHONY: release
release: check-release-guard clean $(RELEASE_FILES) check-duplicate-chart-entries lint
	replicated release create \
	 	--app $(REPLICATED_APP) \
		--version $(VERSION) \
		--yaml-dir $(BUILDDIR) \
		--ensure-channel \
		--promote $(CHANNEL)