Repository navigation
Cachix release script #111
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
640989c
Version bump
RaoulSchaffranek 90e961b
Added script for pushing to the nix caches
RaoulSchaffranek c3e090a
Version bump
RaoulSchaffranek 58dfd69
Merge main
RaoulSchaffranek 8369efb
Rename tokens for readability
RaoulSchaffranek caec8c7
Fix version lookup
RaoulSchaffranek 6055463
Version bump
RaoulSchaffranek File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,199 @@ | ||
| #!/usr/bin/env bash | ||
| # | ||
| # Interactive, local replacement for the former `release.yml` / `update.yml` GitHub workflows. | ||
| # | ||
| # Everything is built from the local checkout. As with any flake, Nix ignores untracked files. | ||
| # | ||
| # Steps (each one asks for confirmation before running): | ||
| # 1. Create GitHub release `v<package/version>` targeting HEAD. | ||
| # 2. Build `kontrol-node` and push its full build closure to the `k-framework` Cachix cache. | ||
| # 3. Publish and pin `kontrol-node` in the `k-framework-binary` Cachix cache (what `kup install` uses). | ||
| # | ||
| # Steps 1 and 3 reference HEAD on GitHub, so they are skipped unless the working tree is clean and | ||
| # HEAD is pushed. Step 2 also runs on uncommitted changes. | ||
| # | ||
| # Credentials are read from the environment, or prompted for (input hidden) when missing: | ||
| # GH_TOKEN GitHub token for `gh` (only needed if `gh auth status` fails) | ||
| # CACHIX_SOURCE_TOKEN Cachix auth token for `k-framework` | ||
| # CACHIX_BINARY_TOKEN Cachix auth token for `k-framework-binary` | ||
| # | ||
| # Do NOT run this script with `bash -x`: tracing would print the credentials. | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| REPO="runtimeverification/kontrol-node" | ||
| PACKAGE="${PACKAGE:-kontrol-node}" | ||
| KEEP_DAYS="${KEEP_DAYS:-180}" | ||
| SOURCE_CACHE="k-framework" | ||
| BINARY_CACHE="k-framework-binary" | ||
|
|
||
| usage() { | ||
| cat <<EOF | ||
| usage: $0 [--yes] | ||
|
|
||
| Builds and publishes the local checkout. | ||
|
|
||
| --yes Run all steps without asking for confirmation. | ||
|
|
||
| Environment: GH_TOKEN, CACHIX_SOURCE_TOKEN, CACHIX_BINARY_TOKEN, | ||
| PACKAGE (default: kontrol-node), KEEP_DAYS (default: 180). | ||
| EOF | ||
| } | ||
|
|
||
| notif() { echo -e "\033[1;34m==\033[0m $*" >&2 ; } | ||
| warn() { echo -e "\033[1;33m[WARN]\033[0m $*" >&2 ; } | ||
| fatal() { echo -e "\033[1;31m[FATAL]\033[0m $*" >&2 ; exit 1 ; } | ||
|
|
||
| ASSUME_YES=false | ||
|
|
||
| confirm() { | ||
| local prompt="$1" answer | ||
| if ${ASSUME_YES}; then return 0; fi | ||
| read -rp "${prompt} [Y/n] " answer </dev/tty | ||
| [[ -z "${answer}" || "${answer}" =~ ^[Yy] ]] | ||
| } | ||
|
|
||
| # Sets the shell variable named $1 from the environment or a hidden prompt. It is deliberately | ||
| # not exported: callers hand it only to the single command that needs it. | ||
| require_secret() { | ||
| local var="$1" description="$2" value | ||
| if [[ -n "${!var:-}" ]]; then | ||
| notif "Using ${var} from environment." | ||
| return | ||
| fi | ||
| read -rsp "${description} (${var}): " value </dev/tty | ||
| echo >&2 | ||
| [[ -n "${value}" ]] || fatal "${var} must not be empty." | ||
| printf -v "${var}" '%s' "${value}" | ||
| } | ||
|
|
||
| nix_() { nix --extra-experimental-features 'nix-command flakes' "$@" ; } | ||
|
|
||
| # Puts tool $1 on PATH, building flake $2 if it is not installed. | ||
| ensure_tool() { | ||
| local tool="$1" flake="$2" out | ||
| command -v "${tool}" &>/dev/null && return | ||
| notif "${tool} not found, building ${flake} ..." | ||
| out="$(nix_ build "${flake}" --no-link --print-out-paths | head -n1)" | ||
| export PATH="${out}/bin:${PATH}" | ||
| } | ||
|
|
||
| # --- Steps ------------------------------------------------------------------------------------ | ||
|
|
||
| step_github_release() { | ||
| if ! gh auth status &>/dev/null; then | ||
| require_secret GH_TOKEN "GitHub token" | ||
| fi | ||
| local existing | ||
| if existing="$(GH_TOKEN="${GH_TOKEN:-}" gh release view "${TAG}" --repo "${REPO}" --json tagName --jq .tagName 2>/dev/null)"; then | ||
| warn "Release ${existing} already exists at HEAD, skipping." | ||
| return | ||
| fi | ||
| GH_TOKEN="${GH_TOKEN:-}" gh release create "${TAG}" --repo "${REPO}" --target "${REV}" --title "${TAG}" --notes '' | ||
| notif "Created release ${TAG}." | ||
| } | ||
|
|
||
| step_source_cache() { | ||
| require_secret CACHIX_SOURCE_TOKEN "Cachix token for ${SOURCE_CACHE}" | ||
| ensure_tool cachix nixpkgs#cachix | ||
| notif "Building ${FLAKE_REF} ..." | ||
| nix_ build "${FLAKE_REF}" --no-link --print-build-logs | ||
| local drv | ||
| drv="$(nix_ path-info --derivation "${FLAKE_REF}")" | ||
| notif "Pushing build closure of ${drv} to ${SOURCE_CACHE} ..." | ||
| nix-store --query --requisites --include-outputs "${drv}" \ | ||
| | CACHIX_AUTH_TOKEN="${CACHIX_SOURCE_TOKEN}" cachix push "${SOURCE_CACHE}" | ||
| } | ||
|
|
||
| step_binary_cache() { | ||
| require_secret CACHIX_BINARY_TOKEN "Cachix token for ${BINARY_CACHE}" | ||
| ensure_tool cachix nixpkgs#cachix | ||
| ensure_tool kup github:runtimeverification/kup | ||
| # kup builds the local directory and pins the result under `github:<origin>/<HEAD>#<package>`. | ||
| notif "Publishing ${FLAKE_REF} to ${BINARY_CACHE} (keep ${KEEP_DAYS} days) ..." | ||
| CACHIX_AUTH_TOKEN="${CACHIX_BINARY_TOKEN}" kup publish --keep-days "${KEEP_DAYS}" "${BINARY_CACHE}" "${FLAKE_REF}" | ||
| } | ||
|
|
||
| # --- Main ------------------------------------------------------------------------------------- | ||
|
|
||
| while [[ $# -gt 0 ]]; do | ||
| case "$1" in | ||
| --yes|-y) ASSUME_YES=true ; shift ;; | ||
| -h|--help) usage ; exit 0 ;; | ||
| *) usage ; fatal "Unknown argument: $1" ;; | ||
| esac | ||
| done | ||
|
|
||
| for tool in git gh nix nix-store; do | ||
| command -v "${tool}" &>/dev/null || fatal "Required tool not found: ${tool}" | ||
| done | ||
|
|
||
| cd "$(git rev-parse --show-toplevel)" | ||
|
|
||
| notif "Fetching origin ..." | ||
| git fetch --quiet origin | ||
|
|
||
| REV="$(git rev-parse HEAD)" | ||
| VERSION="$(tr -d '[:space:]' < package/version)" | ||
| TAG="v${VERSION}" | ||
| FLAKE_REF="${PWD}#${PACKAGE}" | ||
| SYSTEM="$(nix_ eval --impure --raw --expr builtins.currentSystem)" | ||
|
|
||
| DIRTY=false | ||
| STATE="clean" | ||
| if [[ -n "$(git status --porcelain --untracked-files=no)" ]]; then | ||
| DIRTY=true | ||
| STATE="uncommitted changes (included in the build)" | ||
| fi | ||
| PUSHED=true | ||
| if [[ -z "$(git branch --remotes --contains "${REV}")" ]]; then | ||
| PUSHED=false | ||
| STATE="${STATE}, HEAD not pushed" | ||
| fi | ||
|
|
||
| # Consumers resolve a version through its tag, so publishing any commit other than the tagged one | ||
| # under this version would be inconsistent. An annotated tag's commit is its peeled `^{}` entry. | ||
| TAG_REV="$(git ls-remote --tags origin \ | ||
| | awk -v ref="refs/tags/${TAG}" '$2 == ref {c = $1} $2 == ref "^{}" {p = $1} END {print (p ? p : c)}')" | ||
| if [[ -z "${TAG_REV}" ]]; then | ||
| TAG_STATE="new" | ||
| elif [[ "${TAG_REV}" == "${REV}" ]]; then | ||
| TAG_STATE="exists at HEAD" | ||
| else | ||
| fatal "Tag ${TAG} already points at ${TAG_REV}, not HEAD (${REV}). Bump package/version or check out ${TAG}." | ||
| fi | ||
|
|
||
| cat >&2 <<EOF | ||
|
|
||
| Commit: ${REV} | ||
| $(git log -1 --format='%s (%an, %ad)' --date=short "${REV}") | ||
| State: ${STATE} | ||
| Version: ${VERSION} (tag ${TAG}: ${TAG_STATE}) | ||
| Package: ${FLAKE_REF} | ||
| System: ${SYSTEM} (only this system's binaries are cached; run on other machines for more) | ||
|
|
||
| EOF | ||
| confirm "Continue with this release?" || fatal "Aborted." | ||
|
|
||
| # <function>|<needs a clean, pushed HEAD>|<title> | ||
| STEPS=( | ||
| "step_github_release|true|Create GitHub release ${TAG}" | ||
| "step_source_cache|false|Push build closure to the ${SOURCE_CACHE} cache" | ||
| "step_binary_cache|true|Publish ${PACKAGE} to the ${BINARY_CACHE} cache (kup)" | ||
| ) | ||
|
|
||
| for entry in "${STEPS[@]}"; do | ||
| IFS='|' read -r fn needs_published title <<< "${entry}" | ||
| echo >&2 | ||
| if ${needs_published} && { ${DIRTY} || ! ${PUSHED}; }; then | ||
| warn "Skipped: ${title} (needs a clean working tree with HEAD pushed to GitHub)" | ||
| elif confirm "${title}?"; then | ||
| notif "${title}" | ||
| "${fn}" | ||
| else | ||
| warn "Skipped: ${title}" | ||
| fi | ||
| done | ||
|
|
||
| echo >&2 | ||
| notif "Done." |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| 0.1.61 | ||
| 0.1.62 | ||
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,4 +5,4 @@ | |
| if TYPE_CHECKING: | ||
| from typing import Final | ||
|
|
||
| VERSION: Final = '0.1.60' | ||
| VERSION: Final = '0.1.62' | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.