Skip to content

Commit

Permalink
CI Setup (#4)
Browse files Browse the repository at this point in the history
* Create go.yml

* Test

* Allow to change output file name

* Optionally compress output

* Add utsname_arm64.go

* Add build script

* Cleanup

* Test

* Pass down whole environment

* Keep binary file and parallelize build

* Sequential build due to no noticeable improvement

* Add suffix

* Ignore .http files

* Debian build script

* Minors

* Add md5sums

* Automatically detect installation size

* Write config files

* Add util-linux as dependency

* Improve uninstall command

* Build dynamically linked binary on Arch

* Make executable

* Debian package building

* Minor

* Get rid of multiprocessing and cleanup

* Reusable env parser

* Refactor yml file and pass env to install command

* Minor fix

* Update go.yml

* Update go.yml

* Fix tag parsing

* Cleanup

* Test

* Undo test

* Rename

* Add test trigger

* Simplify

* Minor

* Fake tag

* Change prefix name so it appears on ls

* Rename final deb file

* Correct target directory

* Remove prefix directory after creating deb

* Write target architectures to file

* Add upload script

* Call upload script with the correct env

* Set Content-Type header

* Validate curl response status code

* cleanup
  • Loading branch information
maximumadmin authored Mar 19, 2021
1 parent e284959 commit 5ebbc60
Show file tree
Hide file tree
Showing 10 changed files with 516 additions and 18 deletions.
37 changes: 37 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Release

on:
create:
# GitHub Action will not get triggered for '*', so use 'v*' instead
tags:
- v*
# Only used for testing
# push:
# branches-ignore: [ master ]

jobs:

build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.16
- name: Test
run: make test
- name: Set environment variables
run: echo "CURRENT_TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
# run: |-
# echo "WARNING: using test tag"
# echo "CURRENT_TAG=v0.8.5" >> $GITHUB_ENV
- name: Build
run: ./scripts/build.py
- name: Create release and upload assets
run: ./scripts/upload.py $(cat targets.txt)
env:
REPO_OWNER: maximumadmin
REPO_NAME: zramd
GH_RELEASE_TOKEN: ${{ secrets.GH_RELEASE_TOKEN }}
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.python/
.vscode/
zramd.bin
dist/
*.http
79 changes: 63 additions & 16 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,37 +1,56 @@
SHELL := /bin/bash
MODULE := $(shell sed -nr 's/^module ([a-z\-]+)$$/\1/p' go.mod)
GO_FILE := src/$(MODULE).go
OUT_FILE := $(MODULE).bin
ifeq ($(output),)
OUT_FILE := dist/$(MODULE).bin
else
OUT_FILE := $(output)
endif

default:
@go version
@{\
set -e ;\
os_release_id=$$(grep -E '^ID=' /etc/os-release | sed 's/ID=//' || true) ;\
if [ "$$os_release_id" = "arch" ]; then \
make --no-print-directory release-dynamic ;\
else \
make --no-print-directory release-static ;\
fi ;\
}

start:
go run $(GO_FILE)

clean:
go clean
rm -f $(OUT_FILE)
rm -rf dist/*
rm -f "$(OUT_FILE)"

# Build development binary.
# Build development binary
build:
go build -v -o $(OUT_FILE) $(GO_FILE)
@ls -lh $(OUT_FILE)
@ls -lh "$(OUT_FILE)"

# Build statically linked production binary.
release: clean
# Build statically linked production binary
release-static:
@echo "Building static binary (GOARCH: $(GOARCH) GOARM: $(GOARM))..."
@{\
set -e ;\
if [ -z "$${skip_clean}" ]; then make --no-print-directory clean; fi ;\
export GOFLAGS="-a -trimpath -ldflags=-w -ldflags=-s" ;\
if [ "$${GOARCH}" != "arm" ]; then \
export GOFLAGS="$${GOFLAGS} -buildmode=pie" ;\
fi ;\
CGO_ENABLED=0 go build -o $(OUT_FILE) $(GO_FILE) ;\
CGO_ENABLED=0 go build -o "$(OUT_FILE)" $(GO_FILE) ;\
}
@ls -lh $(OUT_FILE)
@make --no-print-directory postbuild

# Build dinamically linked production binary.
release-dynamic: clean
# Build dinamically linked production binary
release-dynamic:
@echo "Building dynamic binary (GOARCH: $(GOARCH) GOARM: $(GOARM))..."
@{\
set -e ;\
if [ -z "$${skip_clean}" ]; then make --no-print-directory clean; fi ;\
export CGO_CPPFLAGS="$${CPPFLAGS}" ;\
export CGO_CFLAGS="$${CFLAGS}" ;\
export CGO_CXXFLAGS="$${CXXFLAGS}" ;\
Expand All @@ -40,22 +59,50 @@ release-dynamic: clean
if [ "$${GOARCH}" != "arm" ]; then \
export GOFLAGS="$${GOFLAGS} -buildmode=pie" ;\
fi ;\
go build -o $(OUT_FILE) $(GO_FILE) ;\
go build -o "$(OUT_FILE)" $(GO_FILE) ;\
}
@ls -lh $(OUT_FILE)
@make --no-print-directory postbuild

# Run unit tests on all packages.
postbuild:
@{\
set -e ;\
if [ ! -z "$${make_tgz}" ]; then \
tgz_file="$(OUT_FILE).tar.gz" ;\
echo "Creating \"$${tgz_file}\"..." ;\
tar -C "$$(dirname "$(OUT_FILE)")" \
-cz -f "$$tgz_file" \
"$$(basename "$(OUT_FILE)")" ;\
fi ;\
if [ ! -z "$${make_deb}" ]; then \
echo "Creating deb ($${DEB_ARCH}) file..." ;\
CONFIG_FILE=extra/debian.yml \
ARCH=$${DEB_ARCH} \
PREFIX="$${PREFIX}" \
BIN_FILE="$(OUT_FILE)" \
VERSION=$${VERSION} \
RELEASE=$${RELEASE} \
./scripts/mkdeb.py ;\
rm -rf "$${PREFIX}" ;\
fi ;\
}
@ls -lh "$(OUT_FILE)"*

# Run unit tests on all packages
test:
go test -v ./src/...

install:
install -Dm755 $(OUT_FILE) "$(PREFIX)/usr/bin/$(MODULE)"
install -Dm755 "$(OUT_FILE)" "$(PREFIX)/usr/bin/$(MODULE)"
install -Dm644 LICENSE -t "$(PREFIX)/usr/share/licenses/$(MODULE)/"
install -Dm644 extra/$(MODULE).default "$(PREFIX)/etc/default/$(MODULE)"
install -Dm644 extra/$(MODULE).service -t "$(PREFIX)/usr/lib/systemd/system/"

uninstall:
systemctl disable --now $(MODULE).service
@{\
if [ -f "$(PREFIX)/usr/lib/systemd/system/$(MODULE).service" ]; then \
systemctl disable --now $(MODULE).service ;\
fi ;\
}
rm -f "$(PREFIX)/usr/lib/systemd/system/$(MODULE).service"
rm -f "$(PREFIX)/etc/default/$(MODULE)"
rm -rf "$(PREFIX)/usr/share/licenses/$(MODULE)/"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ See also https://fedoraproject.org/wiki/Changes/SwapOnZRAM#Benefit_to_Fedora

* Install `go`, this depends on the distribution you are using e.g. for Ubuntu the command should be `sudo apt-get install golang`.
* Run `make release` to make a x86_64 build, to make an ARM build (i.e. for the Raspberry Pi) run `GOOS=linux GOARCH=arm GOARM=7 make release`
* A new executable called `zramd.bin` will be created in the current directory, now you can uninstall `go` if you like.
* A new executable called `zramd.bin` will be created under the `dist/` directory, now you can uninstall `go` if you like.
* Optionally on distributions using systemd, you can install `zramd` by just running `make install`, see below for additional installation methods.

## Installation
Expand Down
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"version": "0.1",
"words": [
"deinitialize",
"itertools",
"lsmod",
"mkswap",
"zram",
Expand Down
41 changes: 41 additions & 0 deletions extra/debian.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
control:
Package: zramd
Version: ${VERSION}-${RELEASE}
Architecture: ${ARCH}
Maintainer: maximumadmin
Priority: extra
Section: admin
Installed-Size: ${SIZE_KB}
Depends: util-linux
Suggests: earlyoom
Description: Automatically setup swap on zram ✨

# https://wiki.debian.org/MaintainerScripts
scripts:
postinst: |-
#!/bin/sh
if [ -d /run/systemd/system ]; then
deb-systemd-invoke enable --now zramd.service >/dev/null || true
fi
prerm: |-
#!/bin/sh
if [ -d /run/systemd/system ] && [ "$1" = remove ]; then
deb-systemd-invoke disable --now zramd.service >/dev/null || true
fi
postrm: |-
if [ -d /run/systemd/system ] && [ "$1" = remove ]; then
systemctl --system daemon-reload >/dev/null || true
fi
build:
install:
cmd: [make, install]
env:
PREFIX: ${PREFIX}
output: ${BIN_FILE}
# Additional arguments passed to dpkg-deb, see also
# https://manpages.debian.org/jessie/dpkg/dpkg-deb.1.en.html
args: [-Zgzip, -z9]
# Used to rename the final deb file so it does not end up with the same name
# as the root directory (PREFIX), env variables can be used here
rename: zramd_${ARCH}.deb
64 changes: 64 additions & 0 deletions scripts/build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/usr/bin/python3 -u

import os
import subprocess
import sys
from typing import Optional, Tuple

TARGETS = (
('arm', '6', 'armel'),
('arm', '7', 'armhf'),
('arm64', None, 'arm64'),
('amd64', None, 'amd64'),
)

# Parse tag names like v0.8.5 or v0.8.5-1
def parse_tag(tag: str) -> Tuple[str, str]:
version, release, *_ = [*tag.split('-'), '']
# Remove the leading 'v' from version
return (version[1:], release or '1')

def build(goarch: str, goarm: Optional[str], friendly_arch: str) -> int:
out_file = f"dist/zramd_{friendly_arch}"
prefix = f"dist/zramd_{friendly_arch}_root"
version, release = parse_tag(os.environ['CURRENT_TAG'])
proc = subprocess.run(
['make', f"output={out_file}", 'make_tgz=1', 'make_deb=1', 'skip_clean=1'],
env={
# Pass all environment variables, contains some Go variables
**os.environ,
# Set Go build-specific variables
'GOOS': 'linux',
'GOARCH': goarch,
**({'GOARM': goarm} if goarch == 'arm' else {}),
# Required to create a Debian package
'DEB_ARCH': friendly_arch,
'VERSION': version,
'RELEASE': release,
'PREFIX': prefix,
'BIN_FILE': out_file
}
)
return proc.returncode

def clean() -> int:
return subprocess.run(['make', 'clean'], env=os.environ).returncode

def main() -> int:
if (ret := clean()) != 0:
return ret

# Build all targets sequentially, building in parallel will have minimal or no
# benefit and would make logging messy
for target in TARGETS:
if (ret := build(*target)) != 0:
return ret

# Finally write the used architectures so we can use them at later steps
with open('targets.txt', 'w') as f:
f.write(','.join(row[2] for row in TARGETS))

return 0

if __name__ == '__main__':
sys.exit(main())
Loading

0 comments on commit 5ebbc60

Please sign in to comment.