Repository navigation
app: start gives the launcher a port of its own, never the shared 308… #1
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| # Publishing a tag is what publishes a release. A tag cannot exist without its binaries, | |
| # because the build is what attaches them. | |
| # | |
| # TWO ARTIFACTS, ON PURPOSE, and they are separate things: | |
| # | |
| # vncode-<ver>-<os>-<arch> the Rust app: one small binary per platform. This is the | |
| # only per-OS artefact anywhere in the project. | |
| # vncode-web-<ver> the node/JS half: the pack and the launcher scripts, the | |
| # SAME bytes on every platform, built once. It runs on its | |
| # own - scripts/run-web.* needs no vncode binary at all - | |
| # and the app above is a front door that calls it. | |
| on: | |
| push: | |
| tags: ['v*'] | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: 'Existing tag to build and attach binaries to' | |
| required: true | |
| permissions: | |
| contents: write | |
| env: | |
| CARGO_TERM_COLOR: always | |
| STEM: vncode | |
| GH_REPO: ${{ github.repository }} | |
| jobs: | |
| # A tag is a promise that the commit it names was checked on three platforms. The gate | |
| # calls the same workflow a pull request runs rather than a copy of it, so the two cannot | |
| # drift: a red check stops the release here, before a draft exists to be published. | |
| gate: | |
| name: Gate | |
| uses: ./.github/workflows/ci.yml | |
| permissions: | |
| contents: read | |
| # Create the release once, as a draft. It becomes visible only after every archive and | |
| # SHA256SUMS.txt are attached, so a half-finished release cannot be installed. | |
| prepare: | |
| name: Prepare release | |
| needs: gate | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Create the draft release if it does not exist | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| TAG="${{ github.event.inputs.tag || github.ref_name }}" | |
| gh release view "$TAG" >/dev/null 2>&1 || \ | |
| gh release create "$TAG" --draft --title "${STEM} ${TAG}" --generate-notes | |
| # ---- the Rust app: one binary per OS ------------------------------------- | |
| build: | |
| name: ${{ matrix.target }} | |
| needs: prepare | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 45 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| # A STATIC CRT, so the Windows binary needs no redistributable: this app is one | |
| # file somebody drops in a folder, and "install the VC++ runtime first" is the | |
| # kind of requirement that makes a small app not worth installing. | |
| - os: windows-latest | |
| target: x86_64-pc-windows-msvc | |
| os_name: windows | |
| arch: x86_64 | |
| ext: zip | |
| rustflags: '-C target-feature=+crt-static' | |
| # 22.04 rather than `latest`, for the glibc floor: a binary built on 24.04 does | |
| # not run on a distribution released before it. | |
| - os: ubuntu-22.04 | |
| target: x86_64-unknown-linux-gnu | |
| os_name: linux | |
| arch: x86_64 | |
| ext: tar.gz | |
| rustflags: '' | |
| - os: macos-latest | |
| target: aarch64-apple-darwin | |
| os_name: macos | |
| arch: aarch64 | |
| ext: tar.gz | |
| rustflags: '' | |
| steps: | |
| # No third-party actions anywhere in this workflow: the repository's Actions policy | |
| # is `local_only`, so a marketplace action is refused at startup. git, rustc/cargo | |
| # and gh are already on the runner image. | |
| - name: Checkout | |
| shell: bash | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| REF: ${{ github.event.inputs.tag || github.ref }} | |
| run: | | |
| git init -q . | |
| git remote add origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" | |
| git fetch -q --depth 1 origin "$REF" | |
| git checkout -q FETCH_HEAD | |
| - name: Toolchain | |
| shell: bash | |
| env: | |
| TARGET: ${{ matrix.target }} | |
| run: | | |
| rustc --version | |
| # A no-op when the target is the runner's own, which it is for all three legs. | |
| rustup target add "$TARGET" | |
| # No GUI toolkit and no web engine to link, which is why this workflow has no | |
| # `apt-get` step: the app draws nothing. | |
| - name: Build | |
| working-directory: app | |
| env: | |
| RUSTFLAGS: ${{ matrix.rustflags }} | |
| run: cargo build --release --locked -p vn-shell --target ${{ matrix.target }} | |
| - name: Package | |
| shell: bash | |
| run: | | |
| TAG="${{ github.event.inputs.tag || github.ref_name }}" | |
| VERSION="${TAG#v}" | |
| NAME="${STEM}-${VERSION}-${{ matrix.os_name }}-${{ matrix.arch }}" | |
| ROOT="${STEM}-${VERSION}" | |
| BIN="app/target/${{ matrix.target }}/release/vncode" | |
| mkdir -p "dist/${ROOT}" | |
| if [ "${{ matrix.os_name }}" = "windows" ]; then | |
| cp "${BIN}.exe" "dist/${ROOT}/" | |
| cp README.md LICENSE "dist/${ROOT}/" | |
| cp "app/README.md" "dist/${ROOT}/APP-README.md" | |
| # bsdtar writes forward-slash entries; the GNU tar in Git Bash does not make a | |
| # zip at all, so the Windows bsdtar is called explicitly. | |
| "/c/Windows/System32/tar.exe" -a -c -f "dist/${NAME}.zip" -C dist "${ROOT}" | |
| else | |
| cp "${BIN}" "dist/${ROOT}/" | |
| cp README.md LICENSE "dist/${ROOT}/" | |
| cp "app/README.md" "dist/${ROOT}/APP-README.md" | |
| chmod +x "dist/${ROOT}/vncode" | |
| (cd dist && tar -czf "${NAME}.tar.gz" "${ROOT}") | |
| fi | |
| cp "dist/${NAME}.${{ matrix.ext }}" . | |
| echo "ASSET=${NAME}.${{ matrix.ext }}" >> "$GITHUB_ENV" | |
| - name: Upload | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| TAG="${{ github.event.inputs.tag || github.ref_name }}" | |
| gh release upload "$TAG" "$ASSET" --clobber | |
| # ---- the node/JS half: built once, because it is the same bytes everywhere ---- | |
| web: | |
| name: Web half (node/JS) | |
| needs: prepare | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout | |
| shell: bash | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| REF: ${{ github.event.inputs.tag || github.ref }} | |
| run: | | |
| git init -q . | |
| git remote add origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" | |
| git fetch -q --depth 1 origin "$REF" | |
| git checkout -q FETCH_HEAD | |
| # No node setup step: this job only PACKAGES the JS, and the one thing it runs | |
| # (`run-web.sh -Help`) needs no interpreter at all. | |
| # The web half must work WITHOUT the app, so it is proved that way: the launcher | |
| # answers its own -Help, the installer answers its own -Help, and neither touches a | |
| # profile while doing it. | |
| - name: It runs on its own | |
| shell: bash | |
| run: | | |
| sh scripts/run-web.sh -Help > /dev/null | |
| echo "run-web.sh -Help: ok" | |
| - name: Package | |
| shell: bash | |
| run: | | |
| TAG="${{ github.event.inputs.tag || github.ref_name }}" | |
| VERSION="${TAG#v}" | |
| NAME="${STEM}-web-${VERSION}" | |
| ROOT="${STEM}-web" | |
| mkdir -p "dist/${ROOT}" | |
| # The pack, the launchers and the pin: everything the browser half needs on a | |
| # machine that has Node.js. The Rust app is NOT in here. | |
| cp -R packages scripts "dist/${ROOT}/" | |
| cp .dsh-version.json package.json README.md LICENSE SECURITY.md ARCHITECTURE.md \ | |
| "dist/${ROOT}/" | |
| cp -R docs "dist/${ROOT}/" | |
| # Build output that a checkout may be carrying is not content. | |
| rm -rf "dist/${ROOT}/scripts/checks/.tmp" | |
| find "dist/${ROOT}" -name '*.log' -delete | |
| (cd dist && tar -czf "${NAME}.tar.gz" "${ROOT}") | |
| cp "dist/${NAME}.tar.gz" . | |
| echo "ASSET=${NAME}.tar.gz" >> "$GITHUB_ENV" | |
| - name: Upload | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| TAG="${{ github.event.inputs.tag || github.ref_name }}" | |
| gh release upload "$TAG" "$ASSET" --clobber | |
| checksums: | |
| name: SHA256SUMS.txt | |
| needs: [build, web] | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| # A checksum file computed before the last upload is a lie, so this job waits for | |
| # every artefact and re-downloads what was actually published. | |
| - name: Collect and publish SHA256SUMS.txt | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| TAG="${{ github.event.inputs.tag || github.ref_name }}" | |
| mkdir -p assets | |
| gh release download "$TAG" --pattern '*' --dir assets | |
| rm -f assets/SHA256SUMS.txt | |
| (cd assets && sha256sum ./* > SHA256SUMS.txt) | |
| gh release upload "$TAG" assets/SHA256SUMS.txt --clobber | |
| publish: | |
| name: Publish | |
| needs: checksums | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Publish the release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| TAG="${{ github.event.inputs.tag || github.ref_name }}" | |
| gh release edit "$TAG" --draft=false |