nandi/nimstaticpublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/nandi/nimstatic.git
git clone ssh://git@rickub.com/nandi/nimstatic.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

release.yml · 167 lines · 7.3 KBYAML Blame HistoryRaw
ci: build and attach release binaries on a v* tag 95124a2 nandi 10h ago1# Cut a release binary when a v* tag is pushed.
2#
3# nimstatic builds itself: a throwaway host build of the tool produces the
4# static one that ships, which means the release artifact is also the test that
5# the tool works on a clean machine.
6name: Release
7
8on:
9 push:
10 tags: ["v*"]
11 workflow_dispatch:
12 inputs:
13 tag:
ci: quote the dispatch input description, and bump to 0.1.3 691dd59 nandi 10h ago14 description: "Existing tag to rebuild; defaults to the newest v* tag"
ci: make the dispatch tag input optional 6a1e2aa nandi 10h ago15 required: false
ci: build and attach release binaries on a v* tag 95124a2 nandi 10h ago16
17permissions:
18 contents: write # required — a job is read-only unless it asks
19
20env:
21 NIM_VERSION: "2.2.4"
22 ZIG_VERSION: "0.15.1"
23
24jobs:
25 release:
26 runs-on: ubuntu-latest
27 steps:
28 - uses: actions/checkout@v4
29 with:
ci: resolve the release tag in one place 6da556b nandi 10h ago30 fetch-depth: 0 # tags, so a dispatch can find the latest one
31
32 # One place decides which tag is being released: the dispatch input, the
33 # tag that triggered the run, or — for a bare dispatch, which carries no
34 # inputs through the API — the newest v* tag. Anything else is a mistake
35 # worth stopping for, since the alternative is a release named after a
36 # branch.
37 - name: Resolve the tag
38 env:
39 INPUT_TAG: ${{ inputs.tag }}
40 run: |
41 set -euo pipefail
ci: resolve the tag without GITHUB_REF_TYPE or git a977b7e nandi 10h ago42 # Every variable here is read with a default: this runner does not
43 # set GITHUB_REF_TYPE, and under `set -u` one missing name is a dead
44 # job three steps before anything interesting happens.
45 REF="${GITHUB_REF:-}"
ci: resolve the release tag in one place 6da556b nandi 10h ago46 if [ -n "${INPUT_TAG:-}" ]; then
47 TAG="$INPUT_TAG"
48 else
ci: resolve the tag without GITHUB_REF_TYPE or git a977b7e nandi 10h ago49 case "$REF" in
50 refs/tags/*) TAG="${REF#refs/tags/}" ;;
51 *)
52 # A dispatch: no tag in the ref, so ask the API for the newest.
53 TAG=$(curl -sSfL -H "Authorization: Bearer $GITHUB_TOKEN" \
54 "$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/tags" \
55 | python3 -c "import json,sys; ts=[t['name'] for t in json.load(sys.stdin) if t['name'].startswith('v')]; print(ts[0] if ts else '')")
56 ;;
57 esac
ci: resolve the release tag in one place 6da556b nandi 10h ago58 fi
59 case "$TAG" in
60 v*) ;;
61 *) echo "refusing to release '$TAG': not a v* tag" >&2; exit 1 ;;
62 esac
ci: resolve the tag without GITHUB_REF_TYPE or git a977b7e nandi 10h ago63 # The runner hands a tag build the right tree already; a dispatch
64 # gets whatever branch it ran on, so move only when we can.
65 if [ -d .git ]; then
66 git checkout --detach "$TAG" 2>/dev/null || echo "note: building the checked-out tree, not $TAG"
67 fi
68 echo "releasing $TAG"
ci: resolve the release tag in one place 6da556b nandi 10h ago69 echo "TAG=$TAG" >> "$GITHUB_ENV"
ci: build and attach release binaries on a v* tag 95124a2 nandi 10h ago70
71 # Toolchains come straight from upstream tarballs rather than setup
72 # actions: two curls, pinned versions, nothing else to trust.
73 - name: Install Nim and zig
74 run: |
75 set -euo pipefail
76 mkdir -p "$HOME/toolchains"
77 curl -sSfL "https://nim-lang.org/download/nim-${NIM_VERSION}-linux_x64.tar.xz" \
78 | tar -xJ -C "$HOME/toolchains"
79 curl -sSfL "https://ziglang.org/download/${ZIG_VERSION}/zig-x86_64-linux-${ZIG_VERSION}.tar.xz" \
80 | tar -xJ -C "$HOME/toolchains"
81 echo "$HOME/toolchains/nim-${NIM_VERSION}/bin" >> "$GITHUB_PATH"
82 echo "$HOME/toolchains/zig-x86_64-linux-${ZIG_VERSION}" >> "$GITHUB_PATH"
83
84 - name: Versions
85 run: |
86 nim --version | head -1
87 zig version
88
89 # Alpine packages are cached so a re-run does not re-download them.
90 - uses: actions/cache@v4
91 with:
92 path: ~/.cache/nimstatic
93 key: nimstatic-alpine-${{ runner.os }}-v3.21
94
95 - name: Test
96 id: test
97 run: nim c -d:ssl --hints:off -r tests/test_nimstatic.nim
98
99 - name: Bootstrap nimstatic on the host
100 run: nim c -d:release -d:ssl --hints:off -o:nimstatic-host src/nimstatic.nim
101
102 - name: Build the static binary with itself
103 run: |
104 set -euo pipefail
ci: drop the file(1) check, and take the version from the tag input 63a7159 nandi 10h ago105 VERSION="${TAG#v}"
ci: build and attach release binaries on a v* tag 95124a2 nandi 10h ago106 NAME="nimstatic-${VERSION}-x86_64-linux"
107 ./nimstatic-host src/nimstatic.nim -o "$NAME" -- -d:ssl --passL:-s
ci: check staticness by reading the ELF, not by ldd 799d4ce nandi 10h ago108 # Neither file(1) nor ldd is on the runner image, and `ldd … | grep`
109 # fails silently when ldd is missing — the pipe eats the error and
110 # grep just finds nothing. Read the ELF program headers instead: a
111 # PT_INTERP entry (type 3) is what makes a binary dynamic.
112 python3 -c "import struct,sys;d=open(sys.argv[1],'rb').read();assert d[:4]==b'\x7fELF';off=struct.unpack_from('<Q',d,0x20)[0];esz=struct.unpack_from('<H',d,0x36)[0];n=struct.unpack_from('<H',d,0x38)[0];t=[struct.unpack_from('<I',d,off+i*esz)[0] for i in range(n)];sys.exit('dynamic: has PT_INTERP' if 3 in t else 0)" "$NAME"
ci: build and attach release binaries on a v* tag 95124a2 nandi 10h ago113 ./"$NAME" --help > /dev/null
114 xz -9e -k "$NAME"
115 sha256sum "$NAME" "$NAME.xz" > SHA256SUMS
116 cat SHA256SUMS
117 echo "NAME=$NAME" >> "$GITHUB_ENV"
118
119 # The release exists already (the tag was pushed, or it is being rebuilt),
120 # so this attaches assets to it rather than creating one. The upload host
121 # is whatever the API itself advertises in upload_url, which is the one
122 # value that cannot go stale.
123 # The release exists already (the tag was pushed, or it is being rebuilt),
124 # so this attaches assets to it rather than creating one. The upload host
125 # is whatever the API advertises in upload_url — the one value that
126 # cannot go stale.
127 - name: Attach the binaries to the release
128 run: |
129 set -euo pipefail
130 api() { curl -sSfL -H "Authorization: Bearer $GITHUB_TOKEN" \
131 -H "Accept: application/vnd.github+json" "$@"; }
132 field() { python3 -c "import json,sys; print(json.load(sys.stdin).get(sys.argv[1],''))" "$1"; }
133
134 if ! api "$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/releases/tags/$TAG" > release.json; then
135 api -X POST "$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/releases" \
136 -d "{\"tag_name\":\"$TAG\",\"name\":\"nimstatic $TAG\"}" > release.json
137 fi
138
ci: check staticness by reading the ELF, not by ldd 799d4ce nandi 10h ago139 # Prefer the upload_url the API advertises; fall back to the
140 # id-based path when this forge does not send one.
ci: build and attach release binaries on a v* tag 95124a2 nandi 10h ago141 upload_url=$(field upload_url < release.json | cut -d'{' -f1)
ci: check staticness by reading the ELF, not by ldd 799d4ce nandi 10h ago142 if [ -z "$upload_url" ]; then
143 release_id=$(field id < release.json)
144 [ -n "$release_id" ] || { echo "no release id in:"; cat release.json; exit 1; }
145 upload_url="$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/releases/$release_id/assets"
146 fi
ci: build and attach release binaries on a v* tag 95124a2 nandi 10h ago147 echo "uploading to $upload_url"
148
149 for asset in "$NAME" "$NAME.xz" SHA256SUMS; do
150 # Replace an asset of the same name, so a re-run is idempotent.
151 existing=$(python3 -c "import json,sys; print(next((a['url'] for a in (json.load(open('release.json')).get('assets') or []) if a['name']==sys.argv[1]),''))" "$asset")
152 if [ -n "$existing" ]; then
153 api -X DELETE "$existing" > /dev/null
154 fi
155 api -X POST "$upload_url?name=$asset" \
156 -H "Content-Type: application/octet-stream" \
157 --data-binary "@$asset" > /dev/null
158 echo "uploaded $asset"
159 done
160
161 - uses: actions/upload-artifact@v4
162 with:
163 name: nimstatic-x86_64-linux
164 path: |
165 nimstatic-*-x86_64-linux
166 nimstatic-*-x86_64-linux.xz
167 SHA256SUMS