nandi/nimstaticpublic Fork 0
691dd59a10e84ce7bc35498991c3e60b5ce9f91c
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.

ci: quote the dispatch input description, and bump to 0.1.3 691dd59 · on 691dd59a10e84ce7bc35498991c3e60b5ce9f91c · nandi · 10h ago
release.yml · 144 lines · 5.6 KBYAML Blame HistoryRaw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# Cut a release binary when a v* tag is pushed.
#
# nimstatic builds itself: a throwaway host build of the tool produces the
# static one that ships, which means the release artifact is also the test that
# the tool works on a clean machine.
name: Release

on:
  push:
    tags: ["v*"]
  workflow_dispatch:
    inputs:
      tag:
        description: "Existing tag to rebuild; defaults to the newest v* tag"
        required: false

permissions:
  contents: write        # required — a job is read-only unless it asks

env:
  NIM_VERSION: "2.2.4"
  ZIG_VERSION: "0.15.1"

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0     # tags, so a dispatch can find the latest one

      # One place decides which tag is being released: the dispatch input, the
      # tag that triggered the run, or — for a bare dispatch, which carries no
      # inputs through the API — the newest v* tag. Anything else is a mistake
      # worth stopping for, since the alternative is a release named after a
      # branch.
      - name: Resolve the tag
        env:
          INPUT_TAG: ${{ inputs.tag }}
        run: |
          set -euo pipefail
          if [ -n "${INPUT_TAG:-}" ]; then
            TAG="$INPUT_TAG"
          elif [ "$GITHUB_REF_TYPE" = tag ]; then
            TAG="$GITHUB_REF_NAME"
          else
            TAG=$(git tag --list 'v*' --sort=-v:refname | head -1)
          fi
          case "$TAG" in
            v*) ;;
            *) echo "refusing to release '$TAG': not a v* tag" >&2; exit 1 ;;
          esac
          git checkout --detach "$TAG"
          echo "releasing $TAG at $(git rev-parse --short HEAD)"
          echo "TAG=$TAG" >> "$GITHUB_ENV"

      # Toolchains come straight from upstream tarballs rather than setup
      # actions: two curls, pinned versions, nothing else to trust.
      - name: Install Nim and zig
        run: |
          set -euo pipefail
          mkdir -p "$HOME/toolchains"
          curl -sSfL "https://nim-lang.org/download/nim-${NIM_VERSION}-linux_x64.tar.xz" \
            | tar -xJ -C "$HOME/toolchains"
          curl -sSfL "https://ziglang.org/download/${ZIG_VERSION}/zig-x86_64-linux-${ZIG_VERSION}.tar.xz" \
            | tar -xJ -C "$HOME/toolchains"
          echo "$HOME/toolchains/nim-${NIM_VERSION}/bin" >> "$GITHUB_PATH"
          echo "$HOME/toolchains/zig-x86_64-linux-${ZIG_VERSION}" >> "$GITHUB_PATH"

      - name: Versions
        run: |
          nim --version | head -1
          zig version

      # Alpine packages are cached so a re-run does not re-download them.
      - uses: actions/cache@v4
        with:
          path: ~/.cache/nimstatic
          key: nimstatic-alpine-${{ runner.os }}-v3.21

      - name: Test
        id: test
        run: nim c -d:ssl --hints:off -r tests/test_nimstatic.nim

      - name: Bootstrap nimstatic on the host
        run: nim c -d:release -d:ssl --hints:off -o:nimstatic-host src/nimstatic.nim

      - name: Build the static binary with itself
        run: |
          set -euo pipefail
          VERSION="${TAG#v}"
          NAME="nimstatic-${VERSION}-x86_64-linux"
          ./nimstatic-host src/nimstatic.nim -o "$NAME" -- -d:ssl --passL:-s
          # `file` is not on the runner image; ldd answers the only question
          # that matters, and running it proves the thing actually starts.
          ldd "$NAME" 2>&1 | grep -q "not a dynamic executable"
          ./"$NAME" --help > /dev/null
          xz -9e -k "$NAME"
          sha256sum "$NAME" "$NAME.xz" > SHA256SUMS
          cat SHA256SUMS
          echo "NAME=$NAME" >> "$GITHUB_ENV"

      # The release exists already (the tag was pushed, or it is being rebuilt),
      # so this attaches assets to it rather than creating one. The upload host
      # is whatever the API itself advertises in upload_url, which is the one
      # value that cannot go stale.
      # The release exists already (the tag was pushed, or it is being rebuilt),
      # so this attaches assets to it rather than creating one. The upload host
      # is whatever the API advertises in upload_url — the one value that
      # cannot go stale.
      - name: Attach the binaries to the release
        run: |
          set -euo pipefail
          api() { curl -sSfL -H "Authorization: Bearer $GITHUB_TOKEN" \
                       -H "Accept: application/vnd.github+json" "$@"; }
          field() { python3 -c "import json,sys; print(json.load(sys.stdin).get(sys.argv[1],''))" "$1"; }

          if ! api "$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/releases/tags/$TAG" > release.json; then
            api -X POST "$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/releases" \
                -d "{\"tag_name\":\"$TAG\",\"name\":\"nimstatic $TAG\"}" > release.json
          fi

          upload_url=$(field upload_url < release.json | cut -d'{' -f1)
          echo "uploading to $upload_url"

          for asset in "$NAME" "$NAME.xz" SHA256SUMS; do
            # Replace an asset of the same name, so a re-run is idempotent.
            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")
            if [ -n "$existing" ]; then
              api -X DELETE "$existing" > /dev/null
            fi
            api -X POST "$upload_url?name=$asset" \
                -H "Content-Type: application/octet-stream" \
                --data-binary "@$asset" > /dev/null
            echo "uploaded $asset"
          done

      - uses: actions/upload-artifact@v4
        with:
          name: nimstatic-x86_64-linux
          path: |
            nimstatic-*-x86_64-linux
            nimstatic-*-x86_64-linux.xz
            SHA256SUMS