Package and Publish a Release

Two scripts drive a release of apache/skywalking-helm. They are the procedure; this page explains what they do and what is left for a human.

Script Covers
tools/releasing/release.sh everything up to and including the call for vote — build, verify, tag, upload to svn, print the vote mail
tools/releasing/release-passed.sh everything after the vote passes — promote the artifacts, create the GitHub release, print the ANNOUNCE mail

release.sh reads the version out of chart/skywalking/Chart.yaml; release-passed.sh takes it as its first argument. Both accept --dry-run. Both call the Makefile, whose per-target detail is in Makefile reference at the end — reference, not procedure.

What gets released

Two artifacts are signed, uploaded and voted on — the source tarball and the packaged chart. That is settled by precedent: every version under dist/release/skywalking/helm/ carries six files.

Where Artifact For chart 5.0.0
dist.apache.org source tarball, .asc, .sha512 skywalking-helm-5.0.0-src.tgz
dist.apache.org packaged chart, .asc, .sha512 skywalking-helm-5.0.0.tgz
Docker Hub (OCI) the chart users install — a convenience binary, pushed after the vote oci://registry-1.docker.io/apache/skywalking-helm:5.0.0
ghcr.io (OCI) 0.0.0-<sha> snapshot of every master commit — not a release oci://ghcr.io/apache/skywalking-helm/skywalking-helm:0.0.0-<sha>

The dist path for this project is skywalking/helm/. The skywalking/kubernetes/ directory on dist is a leftover from the repository’s old name (skywalking-kubernetes) and still holds 4.7.0; nothing new goes there.

The Git tag is v$VERSION (v5.0.0). Every other coordinate is the plain $VERSION (5.0.0). VERSION and CHART_NAME are read out of chart/skywalking/Chart.yaml by the Makefile and are never passed as arguments — see The version is read, never passed.

1. Prepare

Everything here lands in one “Ready to release $VERSION” PR against master. Do not push to master directly — that is the project’s rule, not something the tooling stops you doing. The .asf.yaml ruleset on the default branch restricts deletion and force-push only, so a direct push would succeed.

Milestones

Issues are disabled on this repository, so a release spans two milestones:

Close everything finished in both; move the rest to the next milestone, creating it if needed.

Changelog

docs/changes/changes.md must have a finished section for $VERSION, headed ## $VERSION, covering breaking changes, features and fixes. This is what the vote mail and the ANNOUNCE mail link to.

Version bump

# chart/skywalking/Chart.yaml
version: 5.0.0

Then sweep the prose. The chart version is quoted in helm install examples across nearly the whole docs tree — at 5.0.0 that is 19 files under README.md and docs/, not a handful. Do not work from a remembered list; let grep produce it:

grep -rln '4\.9\.0' README.md docs/          # the version you are leaving behind
grep -rn -- '--version' README.md docs/ | grep -v '4\.9\.0\|5\.0\.0'   # stragglers on other pins

Neither comes back empty, so read the hits rather than counting them. The first keeps the deliberate historical references — Upgrading documents the 4.9.05.0.0 bump, Where to Get the Chart records that 4.9.0 never reached Docker Hub, and this page cites the dist layout.

The second command is there because not every occurrence is literal: docs/install/quick-start.md passes the chart version through a SKYWALKING_RELEASE_VERSION shell variable, and docs/install/chart-sources.md also carries --version for the subchart pins (3.3.1 and friends), which must not be bumped along with the chart. Image tags quoted in the docs (oap.image.tag, ui.image.tag, banyandb.image.tag) must match Version Compatibility — which itself carries the chart version in its own install example, so it is part of the sweep, not the reference standing outside it.

Dependency versions

Every dependency version has to resolve before you can build. BanyanDB Helm is released by apache/skywalking-banyandb-helm and pushed to the same Docker Hub OCI namespace, so ask the registry:

helm show chart oci://registry-1.docker.io/apache/skywalking-banyandb-helm --version 0.7.0

An Error: ... not found means it is not published there. Cross-check the source release exists too: https://dist.apache.org/repos/dist/release/skywalking/banyandb-helm/.

Audit every dependency before tagging:

grep '^  version:' chart/skywalking/Chart.yaml

The dependency versions are the indented version: lines; the chart’s own version: starts at column 0. Do not anchor the search to the - name: line above it — two entries carry an alias: in between, including the BanyanDB one.

Checklist before running the scripts

  1. version: in chart/skywalking/Chart.yaml bumped, and the docs sweep done.
  2. dependencies: in chart/skywalking/Chart.yaml all resolve.
  3. docs/changes/changes.md has a finished ## $VERSION section.
  4. E2E tests green on the release commit.
  5. Both milestones tidy.
  6. The “Ready to release $VERSION” PR merged.

2. Add your GPG public key to Apache svn

  1. Log in to id.apache.org and submit your key fingerprint.
  2. Append your GPG public key to the SkyWalking KEYS file — PMC members only; ask a PMC member otherwise. Do not overwrite the existing content, append at the end.

The build signs with gpg --batch --yes, which will not prompt: the release key must be the default secret key in your keyring, with its passphrase available through the agent.

gpg --list-secret-keys --keyid-format=long

3. Build, verify, tag, upload and call the vote — release.sh

Run it from your own checkout. Linux and macOS both work — the build was verified end to end on each.

bash tools/releasing/release.sh --dry-run   # everything except the four writes
bash tools/releasing/release.sh

You do not need a clean tree, because the script does not build from your tree. It clones apache/skywalking-helm fresh into tools/releasing/skywalking-helm/ and does everything there. That is not tidiness: make release-src archives the working tree, not HEAD, so releasing from a working copy ships whatever untracked files happen to be sitting in it — editor state, an agent directory, a half-finished values file. Cloning removes the question. Your checkout is only read, for the default version.

Note that ignoring such a directory does not protect you — tar does not read .gitignore, so a gitignored directory is silently archived. That is why the clone is excluded in the Makefile and verify_artifacts inspects the finished tarball.

It asks for both versions before doing anything, defaulting from your checkout’s Chart.yaml:

=== Versions ===
  release version:  5.1.0   (from your checkout's chart/skywalking/Chart.yaml)
  next dev version: 5.2.0

  Are these correct? [y/N]

Answer anything but y to type them in. Both must be plain MAJOR.MINOR.PATCH — they end up in a git tag, an svn path and a branch name, and refusing anything else keeps shell metacharacters out of all three.

--dry-run still clones, builds, signs and verifies, and still runs the svn checkout and the next-version commit. It skips exactly four things: the tag push, the svn commit, the branch push and the PR.

The order matters

Stage What it does
resolve_versions asks for the release and next-dev versions, defaulting from your Chart.yaml
preflight refuses to start (see below)
clone_repo fresh clone into tools/releasing/skywalking-helm/; everything below runs there
build make clean then make release — six files in the clone
verify_artifacts signature, checksum, a real render, and an inspection of the source tarball
tag git tag -a v$VERSION and git push origin v$VERSION
upload_to_svn sparse checkout of dist/dev/skywalking, then svn add + svn commit
prepare_next_version rotates the changelog, bumps the chart, opens the next-version PR
vote_mail prints the mail, with the real checksums and commit hash filled in

clone_repo also refuses to continue unless master’s Chart.yaml already says the release version. This project tags master as it stands, so if the version is not already there then master is not ready — and setting it inside the clone would tag a commit that exists nowhere else.

The tag is pushed after the build and the artifact checks, deliberately. A tag pushed first survives a failed build, and preflight then refuses to re-run because v$VERSION exists — so the irreversible step comes last, and a failure leaves nothing on the remote to clean up.

Preflight refuses to start when:

  • any of helm, gpg, shasum, svn, git, make, tar, awk is missing. All of them are reported in one message — finding them one at a time costs one failed run per package;
  • helm is older than 3.8. The chart ships only as an OCI artifact, and helm push to an oci:// registry arrived in 3.8. Helm 4 is accepted: Chart.yaml is apiVersion: v2, which both majors read;
  • gpg holds no secret key. make release signs with gpg --batch, so without one the run would fail after building and packaging everything;
  • gh is not authenticated. It opens the next-version PR at the very end, so an unauthenticated gh would otherwise surface only after the vote candidate is already staged;
  • dist/dev/skywalking cannot be read — a network problem, or svn credentials that are not set up;
  • v$VERSION already exists on the remote, or dist/dev/skywalking/helm/$VERSION already does. The second catches a re-run after a partial upload, which would otherwise only surface at svn commit — after the build, the signing and the tag push.

The point of the capability checks is when they fail. A missing signing key or unusable svn credentials are both perfectly capable of stopping a release half-way through, with a tag already on the remote; preflight is the only place where stopping is free.

verify_artifacts checks, for each of the two artifacts, that the file and its .asc and .sha512 are present, that gpg --batch --verify passes and that shasum -a 512 -c passes. It then runs helm template over the packaged chart and requires at least one rendered kind: — a chart that lints but renders nothing is a valid chart. That render uses oap.storageType=elasticsearch with elasticsearch.enabled left at its default true, so it exercises the ECK path. Finally it lists the source tarball and fails if it contains the build clone, a .tgz, a charts/ directory or a Chart.lock.

The next-version PR

prepare_next_version runs after the candidate is staged, on a bump-to-$NEXT branch of the clone:

  • chart/skywalking/Chart.yaml moves to the next dev version — with sed, not yq, because yq rewrites the whole document and turns a one-line bump into a fifty-line reindent;
  • docs/changes/changes.md becomes docs/changes/changes-$VERSION.md, and a fresh changelog is rendered from docs/changes/changes.tpl;
  • docs/menu.yml gains the released version, inserted directly after Current Version so the in-progress changelog keeps the top of the menu and released versions stay newest-first.

Merge it once the vote thread is open. It cannot affect the artifacts under vote — those were built from the tag, before this branch existed.

Send the vote mail

The script prints the mail and stops; it sends nothing. Copy it, check the checksums and the commit hash it filled in, and send it to dev@skywalking.apache.org from your Apache address. Confirm the six files are visible at https://dist.apache.org/repos/dist/dev/skywalking/helm/$VERSION/ first.

Voting stays open for at least 72 hours.

4. Vote check

What a voter runs. Everything happens in a scratch directory, from the staged URL, never from the release manager’s working copy.

export VERSION=5.0.0
curl -O "https://dist.apache.org/repos/dist/dev/skywalking/helm/$VERSION/skywalking-helm-$VERSION-src.tgz{,.asc,.sha512}"
curl -O "https://dist.apache.org/repos/dist/dev/skywalking/helm/$VERSION/skywalking-helm-$VERSION.tgz{,.asc,.sha512}"
  1. Both artifacts are present, each with .asc and .sha512 — six files.

  2. Signatures.

    curl https://downloads.apache.org/skywalking/KEYS -o KEYS && gpg --import KEYS
    gpg --batch --verify skywalking-helm-$VERSION-src.tgz.asc skywalking-helm-$VERSION-src.tgz
    gpg --batch --verify skywalking-helm-$VERSION.tgz.asc     skywalking-helm-$VERSION.tgz
    
  3. Checksums.

    shasum -a 512 -c skywalking-helm-$VERSION-src.tgz.sha512
    shasum -a 512 -c skywalking-helm-$VERSION.tgz.sha512
    
  4. LICENSE and NOTICE are inside both tarballs — the chart tarball gets them from make prepare, which copies them in from the repository root just before packaging.

    tar tzf skywalking-helm-$VERSION-src.tgz | grep -E '\./(LICENSE|NOTICE)$'
    tar tzf skywalking-helm-$VERSION.tgz     | grep -E 'skywalking-helm/(LICENSE|NOTICE)$'
    
  5. Build from source. Extract the source tarball and package it; this needs network access, because helm dep up fetches the subcharts.

    mkdir src && tar xzf skywalking-helm-$VERSION-src.tgz -C src
    ( cd src && make package )      # keep the build in a subshell — see below
    

    Do not expect the resulting .tgz to checksum-match the voted one — helm package records file timestamps. Compare the file listing and the rendered output instead.

    Stay out of src/ for the steps below. make package writes its own skywalking-helm-$VERSION.tgz into src/, with exactly the name of the artifact you downloaded. If you cd src and stay there, steps 6 and 7 silently inspect your local rebuild instead of the artifact under vote — and a rebuild passes even when the staged tarball is wrong. Run them from the scratch directory, where the downloaded file is.

  6. The chart renders — both storage paths. helm lint and helm template both succeed on a chart that renders nothing, so look at the output, not the exit code. This chart has three required values, and no default backend: oap.storageType is null in values.yaml.

    BanyanDB is opt-in, and turning it on means turning Elasticsearch off:

    helm template sw skywalking-helm-$VERSION.tgz \
      --set oap.image.tag=11.0.0 \
      --set oap.storageType=banyandb \
      --set ui.image.tag=horizon-1.0.0 \
      --set elasticsearch.enabled=false \
      --set banyandb.enabled=true \
      --set banyandb.image.tag=0.11.0 > render-banyandb.yaml
    
    grep -c '^kind:' render-banyandb.yaml            # non-zero; 15 for 5.0.0
    grep -q '^kind: Deployment$' render-banyandb.yaml
    

    Elasticsearch is the default, and that is the render most users get. elasticsearch.enabled is true in values.yaml, so do not carry --set elasticsearch.enabled=false over from the first command — with it you get the first render minus BanyanDB (11 resources at 5.0.0) and no ECK resource whatsoever, which is what the storage-type flag alone buys you:

    helm template sw skywalking-helm-$VERSION.tgz \
      --set oap.image.tag=11.0.0 \
      --set oap.storageType=elasticsearch \
      --set ui.image.tag=horizon-1.0.0 > render-es.yaml
    
    grep -c '^kind:' render-es.yaml                              # non-zero; 34 for 5.0.0
    grep -q '^kind: Elasticsearch$' render-es.yaml               # the ECK cluster CR
    grep -q 'charts/eck-operator/templates/statefulset.yaml' render-es.yaml
    grep -q 'sw-elasticsearch-es-http:9200' render-es.yaml       # OAP wired to the ECK service
    

    The ^kind: Elasticsearch$ anchor matters: kind: Elasticsearch also appears indented inside the operator’s CRD schemas, so an unanchored grep passes on a render that contains no cluster. The three greps together are what “exercises ECK” means — the operator subchart, the Elasticsearch resource it reconciles, and the OAP deployment pointing at the -es-http service that ECK creates for it.

  7. The chart is stamped with the release version. The subcharts are vendored into the tarball, so their versions are readable without a registry:

    tar xzOf skywalking-helm-$VERSION.tgz skywalking-helm/Chart.yaml | grep -E '^version:'
    tar tzf skywalking-helm-$VERSION.tgz | grep -E '^skywalking-helm/charts/[^/]+/Chart.yaml$'
    tar xzOf skywalking-helm-$VERSION.tgz skywalking-helm/Chart.yaml | grep -E '^  version:'
    

    version: must be $VERSION. The third command prints the dependency versions actually baked into the package — four entries at 5.0.0, one per vendored subchart the second command lists. Note that helm package re-serializes Chart.yaml: keys come out alphabetized and the Apache header is gone from that one file inside the chart tarball. That is helm’s doing and is not a defect; the license-header check belongs to the source tarball.

  8. License headers across the source tarball (license-eye), and a functional smoke test if you have a cluster handy — Quick Start.

The chart on Docker Hub is not part of the vote. It does not exist yet at this point.

Vote result rules:

  1. PMC votes are +1 binding, everyone else +1 non-binding.

  2. Vote passes with at least 3 binding +1 and more +1 than -1, within 72 hours.

  3. Send the closing mail, listing the voters by name.

    [RESULT][VOTE] Release Apache SkyWalking Helm version $VERSION
    
    3 days passed, we've got ($NUMBER) +1 bindings:
    xxx
    xxx
    xxx
    ...
    (list names)
    
    I'll continue the release process.
    

5. Publish — release-passed.sh

PMC members only. Run it once the vote thread has three binding +1 and no -1.

bash tools/releasing/release-passed.sh 5.0.0 --dry-run
bash tools/releasing/release-passed.sh 5.0.0

The version is the argument here — this script never reads Chart.yaml, so it can publish a release from a checkout that has already moved on.

Every step is irreversible on shared infrastructure, so each asks first, and declining aborts the run — with the one exception marked below. That is deliberate: the steps are ordered and dependent, and saying no to the svn promotion and then carrying on would create a GitHub release, and publish the chart, for artifacts still sitting in the dev area. --dry-run takes every prompt as a no without aborting, so it walks the whole plan and does none of it.

Stage Prompt Declining
resolve_version confirm the version to publish
preflight fails if svn / gh / git are missing, if gh is not authenticated, if dist/release/skywalking cannot be read, or if dist/dev/skywalking/helm/$VERSION does not exist
promote_artifacts svn mv from dist/dev to dist/release aborts
remove_previous remove everything under release/helm/ other than $VERSION skips and continues — the one exception
github_release gh release create — this is what publishes the chart aborts
announce_mail prints the mail, sends nothing
remaining prints what is left by hand

gh auth status is checked in preflight rather than left to github_release, because github_release runs after promote_artifacts — and an svn mv into dist/release cannot be taken back. An unauthenticated gh has to stop the run before that, or not at all.

remove_previous is the exception because skipping it is survivable: dist/release is meant to hold only the current version, but a stale sibling breaks nothing. Declining prints remove them by hand before announcing, and the run continues. It lists what is there and asks rather than guessing a pattern, because that directory is not uniformly laid out — today 4.9.0 is a version directory while 4.8.0 sits as six loose files at the top level of helm/.

Old releases stay available from archive.apache.org; nothing extra to do for that. Wait for the mirrors before announcing:

curl -sI "https://downloads.apache.org/skywalking/helm/$VERSION/skywalking-helm-$VERSION-src.tgz" | head -1

The GitHub release is what publishes the chart

.github/workflows/publish-helm.yaml listens for release: types: [released], so github_release is the step that puts the chart on Docker Hub; make publish is the manual fallback only. The script runs:

gh release create "v$VERSION" --repo apache/skywalking-helm --verify-tag \
  --title "$VERSION" --notes "See .../blob/v$VERSION/docs/changes/changes.md"

--verify-tag is load-bearing: without it gh creates a missing tag from the default branch head, which is not necessarily the commit the PMC voted on. The release is a full release, never a draft or pre-release — the released event fires when a release is published as a full release (or when an existing pre-release is converted into one), and never for drafts. If the release already exists the script says so and moves on.

Before it pushes anything the workflow runs three hard guards, under a repository guard (github.repository == 'apache/skywalking-helm', so forks never publish):

Check Trips when Effect
Tag shape the release tag is not vMAJOR.MINOR.PATCH Fails the job. The tag is attacker-influenceable text that reaches a shell; only one shape is ever released.
Credentials DOCKERHUB_USER / DOCKERHUB_TOKEN are not available to the repository Fails the job. They are ASF org secrets; failing early beats an opaque unauthorized from the registry.
Version matches the tag version: in chart/skywalking/Chart.yaml ≠ the tag minus its leading v Fails the job. Publishing 5.0.0 from a v5.1.0 tag would be silent and unfixable once the tag is immutable.

It packages with make package (not bare helm package, so NOTICE and LICENSE are in the chart), re-checks that both files are inside the tarball, and pushes to oci://registry-1.docker.io/apache, where helm push appends the chart name — landing at apache/skywalking-helm:$VERSION.

Watch it and verify the result — this is not ceremony. Docker Hub currently holds apache/skywalking-helm tags 4.3.0 through 4.8.0 only: 4.9.0 was released but never reached the registry, which is the gap this workflow exists to close. Confirm yours landed:

gh run list --workflow publish-helm.yaml --repo apache/skywalking-helm --limit 3
helm show chart oci://registry-1.docker.io/apache/skywalking-helm --version "$VERSION"

A FetchReference ... not found means the chart is not there, whatever the workflow’s exit status said.

Pushes to master keep doing what they always did — a 0.0.0-<sha> snapshot to oci://ghcr.io/apache/skywalking-helm/skywalking-helm, documented in Where to Get the Chart.

What the script leaves for you

It prints this list at the end; the detail is here.

  1. Website, in apache/skywalking-website:
    • data/releases.yml — under SkyWalking Kubernetes Helm, replace the version block with $VERSION: the src link through https://www.apache.org/dyn/closer.cgi/skywalking/helm/$VERSION/… and the asc / sha512 links through https://downloads.apache.org/skywalking/helm/$VERSION/…. Set the release date.
    • data/docs.yml — the Kubernetes Helm entry. It still points at tags of the old skywalking-kubernetes repository; once the docs published from docs/menu.yml are wired into the site, add a version entry the way skywalking-swck does it — version: v$VERSION, link: /docs/skywalking-helm/v$VERSION/readme/, commitId: <tag sha> — and update Latest.
  2. The ANNOUNCE mail the script printed, to dev@skywalking.apache.org and announce@apache.org, from your Apache address, with the vote thread permalink filled in from lists.apache.org.
  3. Milestones — close $VERSION here and Helm - $VERSION on apache/skywalking, and open the next pair.
  4. The next development version — bump version: in chart/skywalking/Chart.yaml.

make publish — the manual fallback

publish: package
	helm push ${CHART_NAME}-${VERSION}.tgz oci://registry-1.docker.io/apache

It re-packages from your working tree and pushes to Docker Hub. Reach for it only when Actions is unavailable or the release workflow is broken — the GitHub release created by release-passed.sh is the normal path.

It has none of the workflow’s guards:

  • It does not check the chart version against any tag; it publishes whatever Chart.yaml says.
  • It does not check credentials first; you get the registry’s unauthorized instead.
  • It builds from your working copy, not from the tag — uncommitted local edits get published, and nothing ties the pushed chart to the voted artifact.

If you must use it: helm registry login registry-1.docker.io first (write access to the apache Docker Hub organization is required), run it from a pristine checkout of v$VERSION, and only after the vote has passed and the artifacts have moved to dist/release. Verify with helm show chart oci://registry-1.docker.io/apache/skywalking-helm --version $VERSION.


Makefile reference

The scripts in 3 and 5 call these targets. Nothing below is a step to run by hand during a release.

The version is read, never passed

CHART_DIR = chart/skywalking
VERSION = $(shell cat ${CHART_DIR}/Chart.yaml | grep '^version: ' | awk '{print $$2}')
CHART_NAME = $(shell cat ${CHART_DIR}/Chart.yaml | grep '^name: ' | awk '{print $$2}')

RELEASE_SRC = ${CHART_NAME}-${VERSION}-src

make release VERSION=… does not do what it looks like: a command-line assignment overrides the make variable but not the file helm package writes — that name comes from Chart.yaml — so the chart-package signing step and publish go looking for a tarball that does not exist (the source tarball is built under the overridden name, so only the chart half breaks). Bumping a release means editing the version: line in chart/skywalking/Chart.yaml and committing it. CHART_NAME comes from the chart’s name: field (skywalking-helm), not from the directory name (skywalking), so at chart version 5.0.0 the artifacts are skywalking-helm-5.0.0.tgz and skywalking-helm-5.0.0-src.tgz.

chart/skywalking is the only chart in this repository, and CHART_DIR has only ever pointed at it, so a release packages, signs and publishes exactly one chart.

TMPDIR defaults to /tmp and is the only variable declared with ?=, i.e. the only one meant to be overridden (make release TMPDIR=/var/tmp). The recipe shell is /bin/bash -eo pipefail.

Targets at a glance

Target Depends on Produces
prepare NOTICE + LICENSE copied into chart/skywalking/
package prepare skywalking-helm-<version>.tgz
clean nothing; deletes artifacts and resolved dependencies
release-src clean skywalking-helm-<version>-src.tgz
release release-src, package both tarballs, each with .asc and .sha512
publish package the chart pushed to Docker Hub as an OCI artifact

Do not use make -j: release-src starts by wiping the tree that package writes into.

prepare — the NOTICE/LICENSE copy dance

prepare:
	cp -R NOTICE ${CHART_DIR}/NOTICE
	cp -R LICENSE ${CHART_DIR}/LICENSE

NOTICE and LICENSE live at the repository root, but an Apache release artifact has to carry them inside the distributed tarball. helm package only picks up files under the chart directory, so they are copied in immediately before packaging and deleted immediately after — the working tree never keeps a second copy, and neither file is tracked under chart/skywalking/.

If a make package run dies partway through, those two copies are left behind. make clean removes them.

package

package: prepare
	helm dep up ${CHART_DIR}
	helm package ${CHART_DIR}
	rm -rf ${CHART_DIR}/NOTICE
	rm -rf ${CHART_DIR}/LICENSE

helm dep up resolves every entry in the dependencies: block of Chart.yamleck-operator, eck-elasticsearch, postgresql, skywalking-banyandb-helm — downloading each into chart/skywalking/charts/ and writing chart/skywalking/Chart.lock. Both are gitignored. helm package then rolls the chart directory, its vendored subcharts, and the just-copied NOTICE and LICENSE into skywalking-helm-<version>.tgz in the repository root, and the two copies are removed.

The subcharts are baked into the package. Whatever helm dep up resolved at package time is what users get.

clean

Deletes, in one rm invocation:

  • $(TMPDIR)/skywalking-helm-<version>-src.tgz
  • bin/
  • chart/skywalking/NOTICE, chart/skywalking/LICENSE
  • chart/skywalking/Chart.lock, chart/skywalking/charts/
  • skywalking-helm-<version>.tgz and its .asc / .sha512
  • skywalking-helm-<version>-src.tgz and its .asc / .sha512

One rm -rf with one list of operands. It used to repeat rm -rf on each backslash-continued line, which — there being no && between them — left those tokens sitting in the argument list of a single rm whose only flag was -f. GNU rm permutes arguments, so on Linux the trailing -rf still applied and -f swallowed the stray rm operands, and the target did what it read like. BSD rm — macOS — stops option parsing at the first operand, so -r never took effect: it failed with rm: bin/: is a directory, left bin/ and chart/skywalking/charts/ behind, and exited 1, which aborted make clean, make release-src and make release. The recipe is one rm -rf again and survives BSD rm. release.sh carried a Linux-only guard for as long as that recipe was broken; with the recipe fixed the guard was obsolete, and it has been removed. If you touch it, keep it a single rm -rf and re-read the whole thing rather than one line.

Because clean wipes charts/ and Chart.lock, the next package re-resolves dependencies from scratch.

release-src

release-src: clean
	tar -zcvf $(TMPDIR)/$(RELEASE_SRC).tgz \
	--exclude bin --exclude .git --exclude .idea \
	--exclude .gitignore --exclude .DS_Store --exclude .github \
	. && \
	mv $(TMPDIR)/$(RELEASE_SRC).tgz .

It archives the whole working directory — hence the clean prerequisite, which removes charts/, Chart.lock and this version’s .tgz files before the tar runs. The tar is built in $(TMPDIR) and only then moved into the repository root, so the archive never contains itself.

clean only knows the current $(VERSION): it deletes skywalking-helm-5.0.0*.tgz*, not skywalking-helm-4.9.0.tgz. A tarball left over from a previous release is not excluded by the tar either (the exclude list has no *.tgz), so it would ship as a binary inside the ASF source release. release.sh preflight refuses to start when one is present, which is the check that catches this.

tar . takes the working tree, not HEAD — which is why preflight also refuses a dirty tree. Run from a pristine checkout of the release commit: any untracked scratch file that is not in the exclude list ships inside the ASF source release.

release

release: release-src package
	gpg --batch --yes --armor --detach-sig $(RELEASE_SRC).tgz
	shasum -a 512 $(RELEASE_SRC).tgz > $(RELEASE_SRC).tgz.sha512
	gpg --batch --yes --armor --detach-sig $(CHART_NAME)-$(VERSION).tgz
	shasum -a 512 $(CHART_NAME)-$(VERSION).tgz > $(CHART_NAME)-$(VERSION).tgz.sha512

The full sequence, in order: cleanrelease-srcpreparepackage → sign and checksum. Both artifacts are signed and checksummed, leaving six files in the repository root:

skywalking-helm-5.0.0-src.tgz
skywalking-helm-5.0.0-src.tgz.asc
skywalking-helm-5.0.0-src.tgz.sha512
skywalking-helm-5.0.0.tgz
skywalking-helm-5.0.0.tgz.asc
skywalking-helm-5.0.0.tgz.sha512

Signing is armored and detached, and --batch --yes means GPG will not prompt.

publish

See make publish — the manual fallback.