Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 48 additions & 52 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,71 +1,67 @@
name: Build and Release
name: Release

on:
push:
tags:
- 'v*.*.*' # Matches tags like v1.0.0, v2.1.3, etc.
- 'v*.*.*' # Matches tags like v1.0.0, v2.1.3, v0.2.0-rc.1

permissions:
contents: write # create the release and upload its assets

jobs:
build:
release:
runs-on: ubuntu-latest

steps:
- name: Check out the repository
uses: actions/checkout@v3
uses: actions/checkout@v7
with:
fetch-depth: 0 # the tag check needs main, and git describe needs the tags

- name: Check that a release tag is on main
run: |
# A pre-release tag (for example v0.2.0-dev.1a2b3c4 from make
# dev-release) can come from any branch: /releases/latest never
# returns a pre-release, so installed CLIs do not update to it.
if [[ "$GITHUB_REF_NAME" == *-* ]]; then
echo "Pre-release tag $GITHUB_REF_NAME: any branch is allowed."
exit 0
fi
git fetch --no-tags origin main
if ! git merge-base --is-ancestor "$GITHUB_SHA" origin/main; then
echo "::error::Tag $GITHUB_REF_NAME is not on main. Release tags must be on the release branch."
exit 1
fi

- name: Set up Go
uses: actions/setup-go@v4
uses: actions/setup-go@v7
with:
go-version: '1.27'
check-latest: true

- name: Run build script
run: bash ./build.sh

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-artifacts
path: build/*.tar.gz

release:
needs: build
runs-on: ubuntu-latest

steps:
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: build-artifacts
path: build
- name: Run the checks
run: make check

- name: Create GitHub Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false
# Installed CLIs download fly-linux-<arch>.tar.gz and look for the binary
# fly-linux-<arch> in it. Do not change these asset names.
- name: Build the release archives
run: make release VERSION="$GITHUB_REF_NAME"

- name: Upload Release Assets for amd64
uses: actions/upload-release-asset@v1
- name: Create the GitHub release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: build/fly-linux-amd64.tar.gz
asset_name: fly-linux-amd64.tar.gz
asset_content_type: application/gzip

- name: Upload Release Assets for arm64
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: build/fly-linux-arm64.tar.gz
asset_name: fly-linux-arm64.tar.gz
asset_content_type: application/gzip
GH_TOKEN: ${{ github.token }}
run: |
# A pre-release (for example v0.2.0-rc.1) is not returned by
# /releases/latest, so installed CLIs do not update to it.
prerelease=()
if [[ "$GITHUB_REF_NAME" == *-* ]]; then
prerelease=(--prerelease)
fi
gh release create "$GITHUB_REF_NAME" \
build/fly-linux-amd64.tar.gz \
build/fly-linux-arm64.tar.gz \
build/checksums.txt \
--title "$GITHUB_REF_NAME" \
--generate-notes \
--verify-tag \
"${prerelease[@]}"
37 changes: 37 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: CI

on:
push:
branches: [develop, main]
# All pull requests: stacked pull requests target each other, not develop.
pull_request:

permissions:
contents: read

# A new push cancels the older run for the same branch or pull request.
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
check:
runs-on: ubuntu-latest

steps:
- name: Check out the repository
uses: actions/checkout@v7
with:
fetch-depth: 0 # git describe needs the tags for the version

- name: Set up Go
uses: actions/setup-go@v7
with:
go-version: '1.27'
check-latest: true

- name: Run the checks
run: make check

- name: Build the release archives
run: make release
30 changes: 28 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Developer commands for fly. Run "make help" for the list.
# Keep this file compatible with GNU Make 3.81, the version on macOS.

.PHONY: build test vet lint vuln fmt fmt-check check release clean help
.PHONY: build test vet lint vuln fmt fmt-check check release dev-version dev-release clean help

BINARY := fly
PKG := github.com/flywp/server-cli
Expand All @@ -16,6 +16,13 @@ LDFLAGS := -X $(PKG)/internal/version.Version=$(VERSION) \
-X $(PKG)/internal/version.CommitHash=$(COMMIT) \
-X $(PKG)/internal/version.BuildDate=$(BUILD_DATE)

# Dev pre-releases are named <next minor version>-dev.<short commit>, for
# example v0.2.0-dev.1a2b3c4. DEV_BASE defaults to the minor version after the
# latest release tag; override it, for example make dev-release DEV_BASE=v0.1.2.
DEV_BASE ?= $(shell latest=$$(git describe --tags --abbrev=0 --exclude '*-*' 2>/dev/null || echo v0.0.0); \
echo "$$latest" | awk -F. '{ sub(/^v/, "", $$1); printf "v%d.%d.0", $$1, $$2 + 1 }')
DEV_VERSION = $(DEV_BASE)-dev.$(shell git rev-parse --short=7 HEAD)

# Release platforms. Installed CLIs download fly-<os>-<arch>.tar.gz and look
# for the binary fly-<os>-<arch> in it, so do not change these names.
RELEASE_PLATFORMS := linux/amd64 linux/arm64
Expand Down Expand Up @@ -59,8 +66,27 @@ release: ## Build the static release archives and checksums.txt in build/
done
cd build && (command -v sha256sum >/dev/null 2>&1 && sha256sum *.tar.gz || shasum -a 256 *.tar.gz) > checksums.txt

dev-version: ## Print the dev pre-release version of HEAD
@echo $(DEV_VERSION)

# The Release workflow publishes the tag as a pre-release. A tag on a commit
# whose release workflow does not know pre-releases would become the latest
# release and reach every installed CLI, so dev-release refuses such commits.
dev-release: ## Tag HEAD as a dev pre-release and push the tag (CI publishes it)
@set -e; \
if [ -n "$$(git status --porcelain --untracked-files=no)" ]; then \
echo "Commit or stash your changes first: the pre-release is built from the commit."; exit 1; fi; \
if [ -z "$$(git branch -r --contains HEAD)" ]; then \
echo "Push this commit to a branch first."; exit 1; fi; \
if ! git show HEAD:.github/workflows/build.yml | grep -q -- '--prerelease'; then \
echo "The release workflow at this commit does not publish pre-releases. Do not tag it."; exit 1; fi; \
git tag -a "$(DEV_VERSION)" -m "Dev pre-release $(DEV_VERSION)"; \
git push origin "$(DEV_VERSION)"; \
echo "Pushed $(DEV_VERSION). The Release workflow publishes it as a pre-release:"; \
echo " https://github.com/flywp/server-cli/releases/tag/$(DEV_VERSION)"

clean: ## Remove bin/ and build/
rm -rf bin/ build/

help: ## Show the targets
@grep -E '^[a-z-]+:.*## ' $(MAKEFILE_LIST) | awk -F':.*## ' '{printf " %-10s %s\n", $$1, $$2}'
@grep -E '^[a-z-]+:.*## ' $(MAKEFILE_LIST) | awk -F':.*## ' '{printf " %-12s %s\n", $$1, $$2}'
39 changes: 38 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,50 @@ make build # builds bin/fly with the version from git
make test # go test ./... -race
make lint # golangci-lint (pinned version, built with the module's Go)
make vuln # govulncheck
make check # fmt-check, vet, lint, test and vuln: run this before each merge
make check # fmt-check, vet, lint, test and vuln (CI runs the same)
make release # static linux/amd64 and linux/arm64 archives + checksums.txt in build/
make help # lists all targets
```

`make release VERSION=v0.2.0` stamps a specific version. The release archives must keep the names `fly-linux-<arch>.tar.gz` with the binary `fly-linux-<arch>` inside: installed CLIs look for these names when they run `fly update`.

CI runs `make check` and `make release` on every pull request and on every push to `develop` and `main`.

### Releasing

`main` is the release branch. To publish a release, tag a commit on `main` and push the tag:

```bash
git tag -a v0.2.0 -m "v0.2.0"
git push origin v0.2.0
```

The Release workflow checks that the tag is on `main`, runs `make check`, builds the archives with `make release`, and creates the GitHub release with both archives and `checksums.txt`. A tag with a pre-release suffix, such as `v0.2.0-rc.1`, becomes a pre-release, so installed CLIs do not update to it.

### Dev pre-releases

To test a branch on real servers before it merges, publish a dev pre-release of its current commit:

```bash
make dev-version # prints the tag, for example v0.2.0-dev.1a2b3c4
make dev-release # tags the commit and pushes the tag; CI publishes the pre-release
```

The version is the next minor version after the latest release, plus the short commit hash (`DEV_BASE=v0.1.2` overrides the first part). Pre-release tags can come from any branch. `make dev-release` refuses uncommitted changes, commits that are not pushed, and commits whose release workflow would publish the tag as a full release.

`fly update` and `install.sh` only install the latest full release, so install a dev pre-release on a test server by hand:

```bash
tag=v0.2.0-dev.1a2b3c4 arch=amd64 # arch: amd64 or arm64 (uname -m: x86_64 or aarch64)
base=https://github.com/flywp/server-cli/releases/download/$tag
curl -fsSLO "$base/fly-linux-$arch.tar.gz" && curl -fsSLO "$base/checksums.txt"
sha256sum -c --ignore-missing checksums.txt
tar -xzf "fly-linux-$arch.tar.gz" && sudo install -m 0755 "fly-linux-$arch" /usr/local/bin/fly
fly version
```

To build the same version locally without publishing it, run `make release VERSION=$(make -s dev-version)`.

## License

This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
9 changes: 0 additions & 9 deletions build.sh

This file was deleted.

Loading