detached c161cd8

ci: add CI checks, GoReleaser release and AUR -bin/-git publishing

commit
c161cd8fe5d05e866b9f9c3a0558bb9957344da2
author
brice · · 2026-10-08 08:14 UTC
parent
3e5b69a
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
9 files · +475 -3
A .github/workflows/ci.yml +35 -0
@@ -0,0 +1,35 @@
1+name: CI
2+on:
3+ push:
4+ branches: [main]
5+ pull_request:
6+ # The release workflow runs these checks before it publishes.
7+ workflow_call:
8+concurrency:
9+ group: ci-${{ github.ref }}
10+ cancel-in-progress: true
11+jobs:
12+ # Arch matches the development system: Go and library versions are the
13+ # ones the package is built against.
14+ check:
15+ runs-on: ubuntu-latest
16+ container:
17+ image: archlinux:latest
18+ # An init process reaps killed children, as on a real session.
19+ options: --init
20+ steps:
21+ # The tests run without a compositor or a GPU (the GPU tests skip).
22+ # fontconfig and a font run the glyph tests; gcc is for the race detector.
23+ - run: >-
24+ pacman -Syu --noconfirm --needed
25+ git go make gcc fontconfig ttf-dejavu
26+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
27+ with:
28+ persist-credentials: false
29+ - run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
30+ - run: |
31+ go install honnef.co/go/tools/cmd/staticcheck@latest
32+ echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"
33+ - run: make check
34+ - run: make race
35+ - run: staticcheck ./...
@@ -0,0 +1,35 @@
1+name: CI
2+on:
3+ push:
4+ branches: [main]
5+ pull_request:
6+ # The release workflow runs these checks before it publishes.
7+ workflow_call:
8+concurrency:
9+ group: ci-${{ github.ref }}
10+ cancel-in-progress: true
11+jobs:
12+ # Arch matches the development system: Go and library versions are the
13+ # ones the package is built against.
14+ check:
15+ runs-on: ubuntu-latest
16+ container:
17+ image: archlinux:latest
18+ # An init process reaps killed children, as on a real session.
19+ options: --init
20+ steps:
21+ # The tests run without a compositor or a GPU (the GPU tests skip).
22+ # fontconfig and a font run the glyph tests; gcc is for the race detector.
23+ - run: >-
24+ pacman -Syu --noconfirm --needed
25+ git go make gcc fontconfig ttf-dejavu
26+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
27+ with:
28+ persist-credentials: false
29+ - run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
30+ - run: |
31+ go install honnef.co/go/tools/cmd/staticcheck@latest
32+ echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"
33+ - run: make check
34+ - run: make race
35+ - run: staticcheck ./...
A .github/workflows/release.yml +93 -0
@@ -0,0 +1,93 @@
1+name: Release
2+on:
3+ push:
4+ tags: ['v*']
5+permissions:
6+ contents: read
7+concurrency:
8+ group: release-${{ github.ref }}
9+ cancel-in-progress: false
10+jobs:
11+ check:
12+ uses: ./.github/workflows/ci.yml
13+
14+ release:
15+ needs: check
16+ runs-on: ubuntu-latest
17+ permissions:
18+ contents: write # create the release
19+ id-token: write # sign the provenance attestation
20+ attestations: write
21+ steps:
22+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
23+ with:
24+ fetch-depth: 0
25+ persist-credentials: false
26+ - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
27+ with:
28+ go-version-file: go.mod
29+ - uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3
30+ with:
31+ distribution: goreleaser
32+ version: '~> v2'
33+ args: release --clean
34+ env:
35+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
36+ - uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
37+ with:
38+ subject-path: |
39+ dist/*.tar.gz
40+ dist/checksums.txt
41+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
42+ with:
43+ name: aur-bin
44+ path: dist/aur/neferbar-bin.pkgbuild
45+ if-no-files-found: error
46+
47+ # makepkg must run on Arch as a non-root user. publish.sh builds each
48+ # package, verifies every source checksum, then pushes it.
49+ aur:
50+ needs: release
51+ runs-on: ubuntu-latest
52+ container:
53+ image: archlinux:latest
54+ strategy:
55+ fail-fast: false
56+ matrix:
57+ pkg: [neferbar-bin, neferbar-git]
58+ # Pre-releases (v0.2.0-rc1) stay off the AUR: pacman sorts 0.2.0.rc1
59+ # after 0.2.0, so the final release would not look like an upgrade.
60+ env:
61+ SKIP: ${{ contains(github.ref_name, '-') }}
62+ steps:
63+ - run: >-
64+ pacman -Syu --noconfirm --needed
65+ base-devel git openssh sudo
66+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
67+ with:
68+ persist-credentials: false
69+ - if: matrix.pkg == 'neferbar-bin' && env.SKIP != 'true'
70+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
71+ with:
72+ name: aur-bin
73+ path: aur-bin
74+ - name: Create the build user
75+ run: |
76+ useradd -m builder
77+ echo 'builder ALL=(root) NOPASSWD: /usr/bin/pacman' >/etc/sudoers.d/builder
78+ - name: Build, verify and publish ${{ matrix.pkg }}
79+ if: env.SKIP != 'true'
80+ env:
81+ AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
82+ AUR_USERNAME: ${{ secrets.AUR_USERNAME }}
83+ AUR_EMAIL: ${{ secrets.AUR_EMAIL }}
84+ PKG: ${{ matrix.pkg }}
85+ run: |
86+ if [ "$PKG" = neferbar-bin ]; then
87+ pkgbuild=aur-bin/neferbar-bin.pkgbuild
88+ else
89+ pkgbuild=packaging/aur/neferbar-git/PKGBUILD
90+ fi
91+ chmod -R a+rX "$GITHUB_WORKSPACE"
92+ sudo -u builder --preserve-env=AUR_SSH_PRIVATE_KEY,AUR_USERNAME,AUR_EMAIL \
93+ packaging/aur/publish.sh "$PKG" "$pkgbuild"
@@ -0,0 +1,93 @@
1+name: Release
2+on:
3+ push:
4+ tags: ['v*']
5+permissions:
6+ contents: read
7+concurrency:
8+ group: release-${{ github.ref }}
9+ cancel-in-progress: false
10+jobs:
11+ check:
12+ uses: ./.github/workflows/ci.yml
13+
14+ release:
15+ needs: check
16+ runs-on: ubuntu-latest
17+ permissions:
18+ contents: write # create the release
19+ id-token: write # sign the provenance attestation
20+ attestations: write
21+ steps:
22+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
23+ with:
24+ fetch-depth: 0
25+ persist-credentials: false
26+ - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
27+ with:
28+ go-version-file: go.mod
29+ - uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3
30+ with:
31+ distribution: goreleaser
32+ version: '~> v2'
33+ args: release --clean
34+ env:
35+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
36+ - uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
37+ with:
38+ subject-path: |
39+ dist/*.tar.gz
40+ dist/checksums.txt
41+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
42+ with:
43+ name: aur-bin
44+ path: dist/aur/neferbar-bin.pkgbuild
45+ if-no-files-found: error
46+
47+ # makepkg must run on Arch as a non-root user. publish.sh builds each
48+ # package, verifies every source checksum, then pushes it.
49+ aur:
50+ needs: release
51+ runs-on: ubuntu-latest
52+ container:
53+ image: archlinux:latest
54+ strategy:
55+ fail-fast: false
56+ matrix:
57+ pkg: [neferbar-bin, neferbar-git]
58+ # Pre-releases (v0.2.0-rc1) stay off the AUR: pacman sorts 0.2.0.rc1
59+ # after 0.2.0, so the final release would not look like an upgrade.
60+ env:
61+ SKIP: ${{ contains(github.ref_name, '-') }}
62+ steps:
63+ - run: >-
64+ pacman -Syu --noconfirm --needed
65+ base-devel git openssh sudo
66+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
67+ with:
68+ persist-credentials: false
69+ - if: matrix.pkg == 'neferbar-bin' && env.SKIP != 'true'
70+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
71+ with:
72+ name: aur-bin
73+ path: aur-bin
74+ - name: Create the build user
75+ run: |
76+ useradd -m builder
77+ echo 'builder ALL=(root) NOPASSWD: /usr/bin/pacman' >/etc/sudoers.d/builder
78+ - name: Build, verify and publish ${{ matrix.pkg }}
79+ if: env.SKIP != 'true'
80+ env:
81+ AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
82+ AUR_USERNAME: ${{ secrets.AUR_USERNAME }}
83+ AUR_EMAIL: ${{ secrets.AUR_EMAIL }}
84+ PKG: ${{ matrix.pkg }}
85+ run: |
86+ if [ "$PKG" = neferbar-bin ]; then
87+ pkgbuild=aur-bin/neferbar-bin.pkgbuild
88+ else
89+ pkgbuild=packaging/aur/neferbar-git/PKGBUILD
90+ fi
91+ chmod -R a+rX "$GITHUB_WORKSPACE"
92+ sudo -u builder --preserve-env=AUR_SSH_PRIVATE_KEY,AUR_USERNAME,AUR_EMAIL \
93+ packaging/aur/publish.sh "$PKG" "$pkgbuild"
M .gitignore +2 -0
@@ -1,2 +1,4 @@
11 .worktrees/
22 /neferbar
3+/bin/
4+/dist/
@@ -1,2 +1,4 @@
1 .worktrees/1 .worktrees/
2 /neferbar2 /neferbar
3+/bin/
4+/dist/
A .goreleaser.yaml +137 -0
@@ -0,0 +1,137 @@
1+# Builds the GitHub release for a pushed v* tag (.github/workflows/release.yml)
2+# and generates the neferbar-bin PKGBUILD. The workflow verifies that PKGBUILD
3+# with makepkg before it pushes it to the AUR, so GoReleaser never uploads it.
4+version: 2
5+
6+project_name: neferbar
7+
8+before:
9+ hooks:
10+ - go mod verify
11+
12+builds:
13+ - id: neferbar
14+ main: ./cmd/neferbar
15+ binary: neferbar
16+ env:
17+ - CGO_ENABLED=0
18+ goos: [linux]
19+ goarch: [amd64, arm64]
20+ flags:
21+ - -trimpath
22+ - -buildmode=pie
23+ ldflags:
24+ - -s -w -X main.version={{ .Version }}
25+ # Same inputs give the same binary.
26+ mod_timestamp: "{{ .CommitTimestamp }}"
27+
28+archives:
29+ - id: neferbar
30+ ids: [neferbar]
31+ name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
32+ formats: [tar.gz]
33+ # Everything the PKGBUILD package() installs, at the paths of the repo.
34+ files:
35+ - LICENSE
36+ - README.md
37+ - examples/**/*
38+
39+checksum:
40+ name_template: checksums.txt
41+ algorithm: sha256
42+
43+snapshot:
44+ version_template: "{{ incpatch .Version }}-next"
45+
46+git:
47+ tag_sort: -version:refname
48+
49+changelog:
50+ sort: asc
51+ use: github
52+ filters:
53+ exclude:
54+ - "^style(\\([^)]+\\))?:"
55+ - "^test(\\([^)]+\\))?:"
56+ groups:
57+ - title: Added
58+ regexp: "^feat(\\([^)]+\\))?!?:"
59+ order: 0
60+ - title: Fixed
61+ regexp: "^fix(\\([^)]+\\))?!?:"
62+ order: 1
63+ - title: Performance
64+ regexp: "^perf(\\([^)]+\\))?!?:"
65+ order: 2
66+ - title: Changed
67+ regexp: "^(refactor|build)(\\([^)]+\\))?!?:"
68+ order: 3
69+ - title: Documentation
70+ regexp: "^docs(\\([^)]+\\))?!?:"
71+ order: 4
72+ - title: Maintenance
73+ regexp: "^(chore|ci)(\\([^)]+\\))?!?:"
74+ order: 5
75+ - title: Other changes
76+ order: 999
77+
78+release:
79+ github:
80+ owner: bnema
81+ name: neferbar
82+ draft: false
83+ prerelease: auto
84+ mode: replace
85+ header: |
86+ ## neferbar {{ .Tag }}
87+
88+ ### Install on Arch Linux
89+
90+ ```sh
91+ paru -S neferbar-bin # this release, pre-built (x86_64, aarch64)
92+ paru -S neferbar-git # latest main, built from source
93+ ```
94+
95+ ### Install the pre-built archive
96+
97+ Linux amd64 and arm64. Replace `amd64` with `arm64` on ARM.
98+
99+ ```sh
100+ gh release download {{ .Tag }} -R bnema/neferbar -p 'neferbar_{{ .Version }}_linux_amd64.tar.gz' -p checksums.txt
101+ sha256sum -c --ignore-missing checksums.txt
102+ gh attestation verify neferbar_{{ .Version }}_linux_amd64.tar.gz -R bnema/neferbar
103+ ```
104+
105+ The archive holds the `neferbar` binary, the example configs and scripts, the README and the license. See the [README](https://github.com/bnema/neferbar#readme) for runtime dependencies.
106+ footer: |
107+ ---
108+
109+ **Full changelog**: https://github.com/bnema/neferbar/compare/{{ .PreviousTag }}...{{ .Tag }}
110+
111+aurs:
112+ - name: neferbar-bin
113+ ids: [neferbar]
114+ homepage: https://github.com/bnema/neferbar
115+ description: One-cell-high, terminal-style status bar for Wayland, driven by scripts
116+ maintainers:
117+ - "bnema <b at bnema dot dev>"
118+ license: MIT
119+ # The release workflow verifies and publishes the generated PKGBUILD.
120+ skip_upload: true
121+ provides: [neferbar]
122+ conflicts: [neferbar, neferbar-git]
123+ # Loaded at runtime (purego, no cgo): not seen by makepkg's library scan.
124+ # fontconfig provides fc-match, which finds the font files.
125+ depends:
126+ - glibc
127+ - fontconfig
128+ - libxkbcommon
129+ - vulkan-icd-loader
130+ - vulkan-driver
131+ optdepends:
132+ - "ttf-jetbrains-mono-nerd: default font, with the icons modules print"
133+ package: |-
134+ install -Dm755 ./neferbar "${pkgdir}/usr/bin/neferbar"
135+ install -Dm644 ./README.md "${pkgdir}/usr/share/doc/neferbar/README.md"
136+ cp -r ./examples "${pkgdir}/usr/share/doc/neferbar/examples"
137+ install -Dm644 ./LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
@@ -0,0 +1,137 @@
1+# Builds the GitHub release for a pushed v* tag (.github/workflows/release.yml)
2+# and generates the neferbar-bin PKGBUILD. The workflow verifies that PKGBUILD
3+# with makepkg before it pushes it to the AUR, so GoReleaser never uploads it.
4+version: 2
5+
6+project_name: neferbar
7+
8+before:
9+ hooks:
10+ - go mod verify
11+
12+builds:
13+ - id: neferbar
14+ main: ./cmd/neferbar
15+ binary: neferbar
16+ env:
17+ - CGO_ENABLED=0
18+ goos: [linux]
19+ goarch: [amd64, arm64]
20+ flags:
21+ - -trimpath
22+ - -buildmode=pie
23+ ldflags:
24+ - -s -w -X main.version={{ .Version }}
25+ # Same inputs give the same binary.
26+ mod_timestamp: "{{ .CommitTimestamp }}"
27+
28+archives:
29+ - id: neferbar
30+ ids: [neferbar]
31+ name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
32+ formats: [tar.gz]
33+ # Everything the PKGBUILD package() installs, at the paths of the repo.
34+ files:
35+ - LICENSE
36+ - README.md
37+ - examples/**/*
38+
39+checksum:
40+ name_template: checksums.txt
41+ algorithm: sha256
42+
43+snapshot:
44+ version_template: "{{ incpatch .Version }}-next"
45+
46+git:
47+ tag_sort: -version:refname
48+
49+changelog:
50+ sort: asc
51+ use: github
52+ filters:
53+ exclude:
54+ - "^style(\\([^)]+\\))?:"
55+ - "^test(\\([^)]+\\))?:"
56+ groups:
57+ - title: Added
58+ regexp: "^feat(\\([^)]+\\))?!?:"
59+ order: 0
60+ - title: Fixed
61+ regexp: "^fix(\\([^)]+\\))?!?:"
62+ order: 1
63+ - title: Performance
64+ regexp: "^perf(\\([^)]+\\))?!?:"
65+ order: 2
66+ - title: Changed
67+ regexp: "^(refactor|build)(\\([^)]+\\))?!?:"
68+ order: 3
69+ - title: Documentation
70+ regexp: "^docs(\\([^)]+\\))?!?:"
71+ order: 4
72+ - title: Maintenance
73+ regexp: "^(chore|ci)(\\([^)]+\\))?!?:"
74+ order: 5
75+ - title: Other changes
76+ order: 999
77+
78+release:
79+ github:
80+ owner: bnema
81+ name: neferbar
82+ draft: false
83+ prerelease: auto
84+ mode: replace
85+ header: |
86+ ## neferbar {{ .Tag }}
87+
88+ ### Install on Arch Linux
89+
90+ ```sh
91+ paru -S neferbar-bin # this release, pre-built (x86_64, aarch64)
92+ paru -S neferbar-git # latest main, built from source
93+ ```
94+
95+ ### Install the pre-built archive
96+
97+ Linux amd64 and arm64. Replace `amd64` with `arm64` on ARM.
98+
99+ ```sh
100+ gh release download {{ .Tag }} -R bnema/neferbar -p 'neferbar_{{ .Version }}_linux_amd64.tar.gz' -p checksums.txt
101+ sha256sum -c --ignore-missing checksums.txt
102+ gh attestation verify neferbar_{{ .Version }}_linux_amd64.tar.gz -R bnema/neferbar
103+ ```
104+
105+ The archive holds the `neferbar` binary, the example configs and scripts, the README and the license. See the [README](https://github.com/bnema/neferbar#readme) for runtime dependencies.
106+ footer: |
107+ ---
108+
109+ **Full changelog**: https://github.com/bnema/neferbar/compare/{{ .PreviousTag }}...{{ .Tag }}
110+
111+aurs:
112+ - name: neferbar-bin
113+ ids: [neferbar]
114+ homepage: https://github.com/bnema/neferbar
115+ description: One-cell-high, terminal-style status bar for Wayland, driven by scripts
116+ maintainers:
117+ - "bnema <b at bnema dot dev>"
118+ license: MIT
119+ # The release workflow verifies and publishes the generated PKGBUILD.
120+ skip_upload: true
121+ provides: [neferbar]
122+ conflicts: [neferbar, neferbar-git]
123+ # Loaded at runtime (purego, no cgo): not seen by makepkg's library scan.
124+ # fontconfig provides fc-match, which finds the font files.
125+ depends:
126+ - glibc
127+ - fontconfig
128+ - libxkbcommon
129+ - vulkan-icd-loader
130+ - vulkan-driver
131+ optdepends:
132+ - "ttf-jetbrains-mono-nerd: default font, with the icons modules print"
133+ package: |-
134+ install -Dm755 ./neferbar "${pkgdir}/usr/bin/neferbar"
135+ install -Dm644 ./README.md "${pkgdir}/usr/share/doc/neferbar/README.md"
136+ cp -r ./examples "${pkgdir}/usr/share/doc/neferbar/examples"
137+ install -Dm644 ./LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
M Makefile +37 -2
@@ -1,4 +1,39 @@
1-.PHONY: install
1+.PHONY: bin install build test vet race fmt-check mod-check check pkg
22
3+# Build a fresh binary.
4+bin:
5+ CGO_ENABLED=0 go build -o bin/neferbar ./cmd/neferbar
36 install:
4- go install ./cmd/neferbar
7+ CGO_ENABLED=0 go install ./cmd/neferbar
8+build:
9+ CGO_ENABLED=0 go build ./...
10+test:
11+ CGO_ENABLED=0 go test ./...
12+vet:
13+ CGO_ENABLED=0 go vet ./...
14+race:
15+ # cgo is enabled only for the race test binary.
16+ CGO_ENABLED=1 go test -race ./...
17+# Go sources must be gofmt-clean (lists the offending files and fails otherwise).
18+fmt-check:
19+ test -z "$$(gofmt -l ./internal ./cmd)" || { gofmt -l ./internal ./cmd >&2; exit 1; }
20+# go.mod and go.sum must be tidy (prints the diff and fails otherwise).
21+mod-check:
22+ go mod tidy -diff
23+check: fmt-check mod-check vet test
24+
25+# Arch package of the committed HEAD (packaging/arch/PKGBUILD). Go modules
26+# come from the module proxy in prepare(); the build itself runs offline.
27+# pacman-ordered version: <tag>.r<commits>.g<hash>, or 0.0.0 without a tag.
28+pkg: SHELL := bash
29+pkg: .SHELLFLAGS := -eo pipefail -c
30+pkg:
31+ @test -z "$$(git status --porcelain)" || echo "warning: uncommitted changes are not packaged" >&2
32+ v=$$(t=$$(git describe --tags --abbrev=0 2>/dev/null | sed 's/^v//; s/-/_/g'); \
33+ echo "$${t:-0.0.0}.r$$(git rev-list --count HEAD).g$$(git rev-parse --short HEAD)"); \
34+ d=$$(mktemp -d /tmp/neferbar-pkg.XXXXXX); trap 'rm -rf "$$d"' EXIT; \
35+ git archive --prefix=neferbar-$$v/ -o "$$d/neferbar-$$v.tar.gz" HEAD; \
36+ cp packaging/arch/PKGBUILD "$$d/"; \
37+ cd "$$d" && sed -i "s/^pkgver=.*/pkgver=$$v/; s/^sha256sums=.*/sha256sums=('$$(sha256sum *.tar.gz | cut -d' ' -f1)')/" PKGBUILD; \
38+ makepkg -f --noconfirm; mkdir -p $(CURDIR)/dist; rm -f $(CURDIR)/dist/neferbar-*.pkg.tar.zst; mv *.pkg.tar.zst $(CURDIR)/dist/
39+ @ls dist/*.pkg.tar.zst
@@ -1,4 +1,39 @@
1-.PHONY: install1+.PHONY: bin install build test vet race fmt-check mod-check check pkg
2 2
3+# Build a fresh binary.
4+bin:
5+ CGO_ENABLED=0 go build -o bin/neferbar ./cmd/neferbar
3 install:6 install:
4- go install ./cmd/neferbar7+ CGO_ENABLED=0 go install ./cmd/neferbar
8+build:
9+ CGO_ENABLED=0 go build ./...
10+test:
11+ CGO_ENABLED=0 go test ./...
12+vet:
13+ CGO_ENABLED=0 go vet ./...
14+race:
15+ # cgo is enabled only for the race test binary.
16+ CGO_ENABLED=1 go test -race ./...
17+# Go sources must be gofmt-clean (lists the offending files and fails otherwise).
18+fmt-check:
19+ test -z "$$(gofmt -l ./internal ./cmd)" || { gofmt -l ./internal ./cmd >&2; exit 1; }
20+# go.mod and go.sum must be tidy (prints the diff and fails otherwise).
21+mod-check:
22+ go mod tidy -diff
23+check: fmt-check mod-check vet test
24+
25+# Arch package of the committed HEAD (packaging/arch/PKGBUILD). Go modules
26+# come from the module proxy in prepare(); the build itself runs offline.
27+# pacman-ordered version: <tag>.r<commits>.g<hash>, or 0.0.0 without a tag.
28+pkg: SHELL := bash
29+pkg: .SHELLFLAGS := -eo pipefail -c
30+pkg:
31+ @test -z "$$(git status --porcelain)" || echo "warning: uncommitted changes are not packaged" >&2
32+ v=$$(t=$$(git describe --tags --abbrev=0 2>/dev/null | sed 's/^v//; s/-/_/g'); \
33+ echo "$${t:-0.0.0}.r$$(git rev-list --count HEAD).g$$(git rev-parse --short HEAD)"); \
34+ d=$$(mktemp -d /tmp/neferbar-pkg.XXXXXX); trap 'rm -rf "$$d"' EXIT; \
35+ git archive --prefix=neferbar-$$v/ -o "$$d/neferbar-$$v.tar.gz" HEAD; \
36+ cp packaging/arch/PKGBUILD "$$d/"; \
37+ cd "$$d" && sed -i "s/^pkgver=.*/pkgver=$$v/; s/^sha256sums=.*/sha256sums=('$$(sha256sum *.tar.gz | cut -d' ' -f1)')/" PKGBUILD; \
38+ makepkg -f --noconfirm; mkdir -p $(CURDIR)/dist; rm -f $(CURDIR)/dist/neferbar-*.pkg.tar.zst; mv *.pkg.tar.zst $(CURDIR)/dist/
39+ @ls dist/*.pkg.tar.zst
M README.md +12 -1
@@ -15,13 +15,24 @@ It needs a compositor with `wlr-layer-shell`, such as Sway, Hyprland, Niri, Rive
1515
1616 ## Install
1717
18-You need Go 1.27, a Vulkan 1.3 GPU driver, and a [Nerd Font](https://www.nerdfonts.com/).
18+You need a Vulkan 1.3 GPU driver and a [Nerd Font](https://www.nerdfonts.com/).
19+
20+On Arch Linux:
21+
22+```sh
23+paru -S neferbar-bin # latest release, pre-built
24+paru -S neferbar-git # latest main, built from source
25+```
26+
27+From source, with Go 1.27:
1928
2029 ```sh
2130 go build -o neferbar ./cmd/neferbar
2231 ./neferbar
2332 ```
2433
34+`neferbar version` prints the installed version. The packages put the example configs and scripts in `/usr/share/doc/neferbar/examples`.
35+
2536 Start it from your compositor's autostart. For NeferWL:
2637
2738 ```
@@ -15,13 +15,24 @@ It needs a compositor with `wlr-layer-shell`, such as Sway, Hyprland, Niri, Rive
15 15
16 ## Install16 ## Install
17 17
18-You need Go 1.27, a Vulkan 1.3 GPU driver, and a [Nerd Font](https://www.nerdfonts.com/).18+You need a Vulkan 1.3 GPU driver and a [Nerd Font](https://www.nerdfonts.com/).
19+
20+On Arch Linux:
21+
22+```sh
23+paru -S neferbar-bin # latest release, pre-built
24+paru -S neferbar-git # latest main, built from source
25+```
26+
27+From source, with Go 1.27:
19 28
20 ```sh29 ```sh
21 go build -o neferbar ./cmd/neferbar30 go build -o neferbar ./cmd/neferbar
22 ./neferbar31 ./neferbar
23 ```32 ```
24 33
34+`neferbar version` prints the installed version. The packages put the example configs and scripts in `/usr/share/doc/neferbar/examples`.
35+
25 Start it from your compositor's autostart. For NeferWL:36 Start it from your compositor's autostart. For NeferWL:
26 37
27 ```38 ```
A packaging/arch/PKGBUILD +41 -0
@@ -0,0 +1,41 @@
1+# Built by `make pkg` at the repo root, from `git archive HEAD`.
2+pkgname=neferbar
3+pkgver=0.0.0
4+pkgrel=1
5+pkgdesc='One-cell-high, terminal-style status bar for Wayland, driven by scripts'
6+arch=('x86_64' 'aarch64')
7+url='https://github.com/bnema/neferbar'
8+license=('MIT')
9+# Loaded at runtime (purego, no cgo): not seen by makepkg's library scan.
10+# fontconfig provides fc-match, which finds the font files.
11+depends=('glibc' 'fontconfig' 'libxkbcommon' 'vulkan-icd-loader' 'vulkan-driver')
12+makedepends=('go>=2:1.27')
13+optdepends=('ttf-jetbrains-mono-nerd: default font, with the icons modules print')
14+source=("$pkgname-$pkgver.tar.gz")
15+sha256sums=('SKIP')
16+
17+prepare() {
18+ cd "$pkgname-$pkgver"
19+ export GOPATH="$srcdir/gopath" GOFLAGS='-mod=readonly -modcacherw' GOWORK=off GOTOOLCHAIN=local
20+ go mod download
21+ go mod vendor
22+}
23+
24+build() {
25+ cd "$pkgname-$pkgver"
26+ export CGO_ENABLED=0 GOFLAGS='-mod=vendor -trimpath -buildvcs=false -buildmode=pie' GOPROXY=off GOWORK=off GOTOOLCHAIN=local
27+ go build -ldflags "-X main.version=$pkgver" -o neferbar ./cmd/neferbar
28+}
29+
30+check() {
31+ cd "$pkgname-$pkgver"
32+ ./neferbar version
33+}
34+
35+package() {
36+ cd "$pkgname-$pkgver"
37+ install -Dm755 neferbar "$pkgdir/usr/bin/neferbar"
38+ install -Dm644 README.md "$pkgdir/usr/share/doc/neferbar/README.md"
39+ cp -r examples "$pkgdir/usr/share/doc/neferbar/examples"
40+ install -Dm644 LICENSE "$pkgdir/usr/share/licenses/neferbar/LICENSE"
41+}
@@ -0,0 +1,41 @@
1+# Built by `make pkg` at the repo root, from `git archive HEAD`.
2+pkgname=neferbar
3+pkgver=0.0.0
4+pkgrel=1
5+pkgdesc='One-cell-high, terminal-style status bar for Wayland, driven by scripts'
6+arch=('x86_64' 'aarch64')
7+url='https://github.com/bnema/neferbar'
8+license=('MIT')
9+# Loaded at runtime (purego, no cgo): not seen by makepkg's library scan.
10+# fontconfig provides fc-match, which finds the font files.
11+depends=('glibc' 'fontconfig' 'libxkbcommon' 'vulkan-icd-loader' 'vulkan-driver')
12+makedepends=('go>=2:1.27')
13+optdepends=('ttf-jetbrains-mono-nerd: default font, with the icons modules print')
14+source=("$pkgname-$pkgver.tar.gz")
15+sha256sums=('SKIP')
16+
17+prepare() {
18+ cd "$pkgname-$pkgver"
19+ export GOPATH="$srcdir/gopath" GOFLAGS='-mod=readonly -modcacherw' GOWORK=off GOTOOLCHAIN=local
20+ go mod download
21+ go mod vendor
22+}
23+
24+build() {
25+ cd "$pkgname-$pkgver"
26+ export CGO_ENABLED=0 GOFLAGS='-mod=vendor -trimpath -buildvcs=false -buildmode=pie' GOPROXY=off GOWORK=off GOTOOLCHAIN=local
27+ go build -ldflags "-X main.version=$pkgver" -o neferbar ./cmd/neferbar
28+}
29+
30+check() {
31+ cd "$pkgname-$pkgver"
32+ ./neferbar version
33+}
34+
35+package() {
36+ cd "$pkgname-$pkgver"
37+ install -Dm755 neferbar "$pkgdir/usr/bin/neferbar"
38+ install -Dm644 README.md "$pkgdir/usr/share/doc/neferbar/README.md"
39+ cp -r examples "$pkgdir/usr/share/doc/neferbar/examples"
40+ install -Dm644 LICENSE "$pkgdir/usr/share/licenses/neferbar/LICENSE"
41+}
A packaging/aur/neferbar-git/PKGBUILD +52 -0
@@ -0,0 +1,52 @@
1+# Maintainer: bnema <b at bnema dot dev>
2+# The release workflow sets pkgver and publishes this file to the AUR on every
3+# release tag, so the AUR version never falls behind the latest tag.
4+pkgname=neferbar-git
5+pkgver=0.0.0.r0.g0000000
6+pkgrel=1
7+pkgdesc='One-cell-high, terminal-style status bar for Wayland, driven by scripts (git version)'
8+arch=('x86_64' 'aarch64')
9+url='https://github.com/bnema/neferbar'
10+license=('MIT')
11+# Loaded at runtime (purego, no cgo): not seen by makepkg's library scan.
12+# fontconfig provides fc-match, which finds the font files.
13+depends=('glibc' 'fontconfig' 'libxkbcommon' 'vulkan-icd-loader' 'vulkan-driver')
14+makedepends=('go>=2:1.27' 'git')
15+optdepends=('ttf-jetbrains-mono-nerd: default font, with the icons modules print')
16+provides=('neferbar')
17+conflicts=('neferbar' 'neferbar-bin')
18+source=('git+https://github.com/bnema/neferbar.git')
19+sha256sums=('SKIP')
20+
21+pkgver() {
22+ cd neferbar
23+ # v0.2.0-5-gabc1234 -> 0.2.0.r5.gabc1234. Pre-release tags (v0.3.0-rc1)
24+ # are skipped: pacman sorts 0.3.0.rc1 after 0.3.0.
25+ git describe --long --tags --abbrev=7 --exclude='*-*' | sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g'
26+}
27+
28+prepare() {
29+ cd neferbar
30+ export GOPATH="$srcdir/gopath" GOFLAGS='-mod=readonly -modcacherw' GOTOOLCHAIN=local
31+ go mod download
32+}
33+
34+build() {
35+ cd neferbar
36+ export GOPATH="$srcdir/gopath" CGO_ENABLED=0 GOTOOLCHAIN=local GOPROXY=off
37+ export GOFLAGS='-mod=readonly -modcacherw -trimpath -buildvcs=false -buildmode=pie'
38+ go build -ldflags "-X main.version=$pkgver" -o neferbar ./cmd/neferbar
39+}
40+
41+check() {
42+ cd neferbar
43+ ./neferbar version
44+}
45+
46+package() {
47+ cd neferbar
48+ install -Dm755 neferbar "$pkgdir/usr/bin/neferbar"
49+ install -Dm644 README.md "$pkgdir/usr/share/doc/neferbar/README.md"
50+ cp -r examples "$pkgdir/usr/share/doc/neferbar/examples"
51+ install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
52+}
@@ -0,0 +1,52 @@
1+# Maintainer: bnema <b at bnema dot dev>
2+# The release workflow sets pkgver and publishes this file to the AUR on every
3+# release tag, so the AUR version never falls behind the latest tag.
4+pkgname=neferbar-git
5+pkgver=0.0.0.r0.g0000000
6+pkgrel=1
7+pkgdesc='One-cell-high, terminal-style status bar for Wayland, driven by scripts (git version)'
8+arch=('x86_64' 'aarch64')
9+url='https://github.com/bnema/neferbar'
10+license=('MIT')
11+# Loaded at runtime (purego, no cgo): not seen by makepkg's library scan.
12+# fontconfig provides fc-match, which finds the font files.
13+depends=('glibc' 'fontconfig' 'libxkbcommon' 'vulkan-icd-loader' 'vulkan-driver')
14+makedepends=('go>=2:1.27' 'git')
15+optdepends=('ttf-jetbrains-mono-nerd: default font, with the icons modules print')
16+provides=('neferbar')
17+conflicts=('neferbar' 'neferbar-bin')
18+source=('git+https://github.com/bnema/neferbar.git')
19+sha256sums=('SKIP')
20+
21+pkgver() {
22+ cd neferbar
23+ # v0.2.0-5-gabc1234 -> 0.2.0.r5.gabc1234. Pre-release tags (v0.3.0-rc1)
24+ # are skipped: pacman sorts 0.3.0.rc1 after 0.3.0.
25+ git describe --long --tags --abbrev=7 --exclude='*-*' | sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g'
26+}
27+
28+prepare() {
29+ cd neferbar
30+ export GOPATH="$srcdir/gopath" GOFLAGS='-mod=readonly -modcacherw' GOTOOLCHAIN=local
31+ go mod download
32+}
33+
34+build() {
35+ cd neferbar
36+ export GOPATH="$srcdir/gopath" CGO_ENABLED=0 GOTOOLCHAIN=local GOPROXY=off
37+ export GOFLAGS='-mod=readonly -modcacherw -trimpath -buildvcs=false -buildmode=pie'
38+ go build -ldflags "-X main.version=$pkgver" -o neferbar ./cmd/neferbar
39+}
40+
41+check() {
42+ cd neferbar
43+ ./neferbar version
44+}
45+
46+package() {
47+ cd neferbar
48+ install -Dm755 neferbar "$pkgdir/usr/bin/neferbar"
49+ install -Dm644 README.md "$pkgdir/usr/share/doc/neferbar/README.md"
50+ cp -r examples "$pkgdir/usr/share/doc/neferbar/examples"
51+ install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
52+}
A packaging/aur/publish.sh +66 -0
@@ -0,0 +1,66 @@
1+#!/usr/bin/env bash
2+# Builds an AUR package with makepkg, then pushes its PKGBUILD and .SRCINFO.
3+# makepkg downloads every source and checks its sha256sum, so a PKGBUILD that
4+# does not build, or does not match its release assets, is never published.
5+#
6+# Usage: publish.sh <pkgname> <PKGBUILD>
7+# Env: AUR_SSH_PRIVATE_KEY, AUR_USERNAME, AUR_EMAIL
8+# DRY_RUN=1 builds and prints the files without pushing.
9+# Runs as a non-root user that may run pacman through sudo (makepkg -s).
10+set -euo pipefail
11+CARCH=$(uname -m)
12+
13+pkgname=$1
14+work=$(mktemp -d)
15+trap 'rm -rf "$work"' EXIT
16+cp "$2" "$work/PKGBUILD"
17+cd "$work"
18+
19+makepkg --syncdeps --force --noconfirm
20+# A -git pkgver() rewrites pkgver in PKGBUILD; .SRCINFO must match it.
21+makepkg --printsrcinfo >.SRCINFO
22+pkgver=$(sed -n 's/^\tpkgver = //p' .SRCINFO)
23+
24+# makepkg only fetches the sources of this machine's arch: check the others too.
25+while read -r arch; do
26+ if [[ $arch == "$CARCH" ]] || ! grep -q "^source_$arch=" PKGBUILD; then
27+ continue
28+ fi
29+ { cat /etc/makepkg.conf; echo "CARCH=$arch"; } >"makepkg-$arch.conf"
30+ makepkg --config "makepkg-$arch.conf" --verifysource --noconfirm
31+done < <(sed -n 's/^\tarch = //p' .SRCINFO)
32+
33+# pacman versions use _ where the tag has - (0.2.0-rc1 -> 0.2.0_rc1).
34+got=$("pkg/$pkgname/usr/bin/neferbar" version)
35+if [[ $got != "$pkgver" && $got != "${pkgver//_/-}" ]]; then
36+ echo "packaged neferbar reports version $got, want $pkgver" >&2
37+ exit 1
38+fi
39+
40+if [[ ${DRY_RUN:-} == 1 ]]; then
41+ cat PKGBUILD .SRCINFO
42+ exit 0
43+fi
44+
45+ssh_dir=$HOME/.ssh
46+key=$ssh_dir/aur
47+install -d -m 700 "$ssh_dir"
48+(umask 077 && printf '%s\n' "$AUR_SSH_PRIVATE_KEY" >"$key")
49+# Pinned host key. Fingerprint SHA256:RFzBCUItH9LZS0cKB5UE6ceAYhBD5C8GeOBip8Z11+4
50+# is published on https://aur.archlinux.org.
51+echo 'aur.archlinux.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEuBKrPzbawxA/k2g6NcyV5jmqwJ2s+zpgZGZ7tpLIcN' >"$ssh_dir/known_hosts"
52+export GIT_SSH_COMMAND="ssh -i $key -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile=$ssh_dir/known_hosts"
53+
54+git clone "ssh://aur@aur.archlinux.org/$pkgname.git" aur
55+cp PKGBUILD .SRCINFO aur/
56+cd aur
57+git add PKGBUILD .SRCINFO
58+if git diff --cached --quiet; then
59+ echo "$pkgname $pkgver is already on the AUR"
60+ exit 0
61+fi
62+# Commits are signed with the AUR SSH key.
63+git -c user.name="$AUR_USERNAME" -c user.email="$AUR_EMAIL" \
64+ -c gpg.format=ssh -c user.signingkey="$key" \
65+ commit -S -m "Update to $pkgver"
66+git push origin HEAD:master
@@ -0,0 +1,66 @@
1+#!/usr/bin/env bash
2+# Builds an AUR package with makepkg, then pushes its PKGBUILD and .SRCINFO.
3+# makepkg downloads every source and checks its sha256sum, so a PKGBUILD that
4+# does not build, or does not match its release assets, is never published.
5+#
6+# Usage: publish.sh <pkgname> <PKGBUILD>
7+# Env: AUR_SSH_PRIVATE_KEY, AUR_USERNAME, AUR_EMAIL
8+# DRY_RUN=1 builds and prints the files without pushing.
9+# Runs as a non-root user that may run pacman through sudo (makepkg -s).
10+set -euo pipefail
11+CARCH=$(uname -m)
12+
13+pkgname=$1
14+work=$(mktemp -d)
15+trap 'rm -rf "$work"' EXIT
16+cp "$2" "$work/PKGBUILD"
17+cd "$work"
18+
19+makepkg --syncdeps --force --noconfirm
20+# A -git pkgver() rewrites pkgver in PKGBUILD; .SRCINFO must match it.
21+makepkg --printsrcinfo >.SRCINFO
22+pkgver=$(sed -n 's/^\tpkgver = //p' .SRCINFO)
23+
24+# makepkg only fetches the sources of this machine's arch: check the others too.
25+while read -r arch; do
26+ if [[ $arch == "$CARCH" ]] || ! grep -q "^source_$arch=" PKGBUILD; then
27+ continue
28+ fi
29+ { cat /etc/makepkg.conf; echo "CARCH=$arch"; } >"makepkg-$arch.conf"
30+ makepkg --config "makepkg-$arch.conf" --verifysource --noconfirm
31+done < <(sed -n 's/^\tarch = //p' .SRCINFO)
32+
33+# pacman versions use _ where the tag has - (0.2.0-rc1 -> 0.2.0_rc1).
34+got=$("pkg/$pkgname/usr/bin/neferbar" version)
35+if [[ $got != "$pkgver" && $got != "${pkgver//_/-}" ]]; then
36+ echo "packaged neferbar reports version $got, want $pkgver" >&2
37+ exit 1
38+fi
39+
40+if [[ ${DRY_RUN:-} == 1 ]]; then
41+ cat PKGBUILD .SRCINFO
42+ exit 0
43+fi
44+
45+ssh_dir=$HOME/.ssh
46+key=$ssh_dir/aur
47+install -d -m 700 "$ssh_dir"
48+(umask 077 && printf '%s\n' "$AUR_SSH_PRIVATE_KEY" >"$key")
49+# Pinned host key. Fingerprint SHA256:RFzBCUItH9LZS0cKB5UE6ceAYhBD5C8GeOBip8Z11+4
50+# is published on https://aur.archlinux.org.
51+echo 'aur.archlinux.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEuBKrPzbawxA/k2g6NcyV5jmqwJ2s+zpgZGZ7tpLIcN' >"$ssh_dir/known_hosts"
52+export GIT_SSH_COMMAND="ssh -i $key -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile=$ssh_dir/known_hosts"
53+
54+git clone "ssh://aur@aur.archlinux.org/$pkgname.git" aur
55+cp PKGBUILD .SRCINFO aur/
56+cd aur
57+git add PKGBUILD .SRCINFO
58+if git diff --cached --quiet; then
59+ echo "$pkgname $pkgver is already on the AUR"
60+ exit 0
61+fi
62+# Commits are signed with the AUR SSH key.
63+git -c user.name="$AUR_USERNAME" -c user.email="$AUR_EMAIL" \
64+ -c gpg.format=ssh -c user.signingkey="$key" \
65+ commit -S -m "Update to $pkgver"
66+git push origin HEAD:master

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 5

Tags 4

↑↓ moveenter openesc close