Cuz ew. What could be more ew? Not this really.
Clearly using update-source-version (bash) from a different lang
is better? 😜️
main
parent
cfba4685a0
commit
95dfa8b8cf
@ -0,0 +1 @@ |
||||
use nix |
@ -0,0 +1,4 @@ |
||||
# Used by "mix format" |
||||
[ |
||||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] |
||||
] |
@ -0,0 +1,32 @@ |
||||
# The directory Mix will write compiled artifacts to. |
||||
_build/ |
||||
|
||||
# If you run "mix test --cover", coverage assets end up here. |
||||
cover/ |
||||
|
||||
# The directory Mix downloads your dependencies sources to. |
||||
deps/ |
||||
|
||||
# Where third-party dependencies like ExDoc output generated docs. |
||||
doc/ |
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally. |
||||
.fetch |
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too. |
||||
erl_crash.dump |
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build"). |
||||
*.ez |
||||
|
||||
# Ignore package tarball (built via "mix hex.build"). |
||||
nixpkgs_github_update-*.tar |
||||
|
||||
# Ignore elixir_ls |
||||
.elixir_ls |
||||
|
||||
# mix escript.build result |
||||
nixpkgs_github_update |
||||
|
||||
# lockfile. only because this is nixpkgs. |
||||
mix.lock |
@ -0,0 +1,53 @@ |
||||
{ lib |
||||
, beamPackages |
||||
, makeWrapper |
||||
, common-updater-scripts |
||||
}: |
||||
|
||||
let |
||||
|
||||
poison_4 = beamPackages.buildMix { |
||||
name = "poison"; |
||||
version = "4.0.1"; |
||||
|
||||
src = beamPackages.fetchHex { |
||||
pkg = "poison"; |
||||
version = "4.0.1"; |
||||
sha256 = "098gdz7xzfmnjzgnnv80nl4h3zl8l9czqqd132vlnfabxbz3d25s"; |
||||
}; |
||||
}; |
||||
|
||||
|
||||
in |
||||
|
||||
beamPackages.buildMix { |
||||
name = "nixpkgs-github-update"; |
||||
version = "0.1.0"; |
||||
|
||||
src = lib.cleanSource ./.; |
||||
|
||||
nativeBuildInputs = [ |
||||
makeWrapper |
||||
]; |
||||
|
||||
beamDeps = with beamPackages; [ erlang poison_4 ]; |
||||
|
||||
buildPhase = '' |
||||
export HEX_OFFLINE=1 |
||||
export HEX_HOME=`pwd` |
||||
export MIX_ENV=prod |
||||
export MIX_NO_DEPS=1 |
||||
|
||||
mix escript.build --no-deps-check |
||||
''; |
||||
|
||||
installPhase = '' |
||||
mkdir -p $out/bin |
||||
cp nixpkgs_github_update $out/bin |
||||
''; |
||||
|
||||
postFixup = '' |
||||
wrapProgram $out/bin/nixpkgs_github_update \ |
||||
--prefix PATH : "${lib.makeBinPath [ common-updater-scripts ]}" |
||||
''; |
||||
} |
@ -0,0 +1,71 @@ |
||||
defmodule NixpkgsGitHubUpdate.CLI do |
||||
@moduledoc """ |
||||
Run updates on Nix Expressions that use fetchFromGitHub. |
||||
|
||||
Arguments the script accepts: |
||||
--attribute <attribute_path> |
||||
|
||||
Example usage: |
||||
``` |
||||
./nixpkgs_github_update --attribute "notes-up" |
||||
``` |
||||
""" |
||||
alias NixpkgsGitHubUpdate.{Nix, GitHubLatestVersion} |
||||
|
||||
def help do |
||||
IO.puts(""" |
||||
Run updates on Nix Expressions that use fetchFromGitHub. |
||||
|
||||
Arguments the script accepts: |
||||
--attribute <attribute_path> |
||||
|
||||
Example usage: |
||||
./nixpkgs_github_update --attribute "notes-up" |
||||
""") |
||||
end |
||||
|
||||
def main([]) do |
||||
help() |
||||
end |
||||
|
||||
def main(args) do |
||||
opts = parse_args(args) |
||||
|
||||
attribute = opts[:attribute] |
||||
|
||||
case Nix.attribute_exists?(attribute) do |
||||
true -> update(attribute) |
||||
_ -> exit("Requested attribute doesn't exist.") |
||||
end |
||||
end |
||||
|
||||
def parse_args(args) do |
||||
{options, _, _} = |
||||
args |
||||
|> OptionParser.parse(strict: [attribute: :string]) |
||||
|
||||
options |
||||
end |
||||
|
||||
def update(attribute) do |
||||
version = |
||||
Nix.get_owner_repo(attribute) |
||||
|> GitHubLatestVersion.fetch() |
||||
|> decode_response() |
||||
|> construct_version() |
||||
|
||||
Nix.update_source_version(attribute, version) |
||||
end |
||||
|
||||
def decode_response({:ok, response}), do: response |
||||
|
||||
def decode_response({:error, error}) do |
||||
IO.puts("Error getting latest release from GitHub: #{error["message"]}") |
||||
System.halt(2) |
||||
end |
||||
|
||||
def construct_version(response) do |
||||
Map.get(response, "tag_name") |
||||
|> String.trim_leading("v") |
||||
end |
||||
end |
@ -0,0 +1,31 @@ |
||||
defmodule NixpkgsGitHubUpdate.GitHubLatestVersion do |
||||
@user_agent 'httpc' |
||||
|
||||
def fetch({owner, repo}) do |
||||
endpoint = releases_endpoint(owner, repo) |
||||
|
||||
oauth_token = String.to_charlist("#{System.get_env("OAUTH_TOKEN")}") |
||||
|
||||
headers = %{ |
||||
'User-Agent' => @user_agent, |
||||
'Authorization' => 'token #{oauth_token}' |
||||
} |
||||
|
||||
:httpc.request(:get, {endpoint, Map.to_list(headers)}, [], []) |
||||
|> handle_response |
||||
end |
||||
|
||||
def releases_endpoint(owner, repo) do |
||||
'https://api.github.com/repos/#{owner}/#{repo}/releases/latest' |
||||
end |
||||
|
||||
def handle_response({_, {{_httpv, status_code, _}, _headers, response}}) do |
||||
{ |
||||
status_code |> check_for_error(), |
||||
response |> Poison.Parser.parse!(%{}) |
||||
} |
||||
end |
||||
|
||||
defp check_for_error(200), do: :ok |
||||
defp check_for_error(_), do: :error |
||||
end |
@ -0,0 +1,75 @@ |
||||
defmodule NixpkgsGitHubUpdate.Nix do |
||||
def executable do |
||||
nix = System.find_executable("nix") |
||||
|
||||
if nil === nix do |
||||
raise RuntimeError, message: "missing executable for 'nix'" |
||||
end |
||||
|
||||
nix |
||||
end |
||||
|
||||
def eval!(attribute) do |
||||
System.cmd( |
||||
executable(), |
||||
[ |
||||
"eval", |
||||
"--json", |
||||
attribute |
||||
], |
||||
stderr_to_stdout: true |
||||
) |
||||
|> handle_eval |
||||
end |
||||
|
||||
def handle_eval({eval_result, 0}) do |
||||
case eval_result do |
||||
"" -> eval_result |
||||
_ -> Poison.Parser.parse!(eval_result, %{}) |
||||
end |
||||
end |
||||
|
||||
def handle_eval({eval_result, _}) do |
||||
IO.puts("Error running nix eval: #{eval_result}") |
||||
end |
||||
|
||||
def attribute_exists?(attribute) do |
||||
eval!("(with import <nixpkgs> {}; lib.isDerivation #{attribute})") |
||||
end |
||||
|
||||
def update_source_version(attribute, version) do |
||||
System.cmd("update-source-version", [ |
||||
attribute, |
||||
version |
||||
]) |
||||
end |
||||
|
||||
def get_url_attr(attribute) do |
||||
case eval!("nixpkgs.#{attribute}.src.fetchSubmodules") do |
||||
true -> "url" |
||||
_ -> "urls" |
||||
end |
||||
end |
||||
|
||||
def get_owner_repo(attribute) do |
||||
url_attr = get_url_attr(attribute) |
||||
|
||||
eval!("nixpkgs.#{attribute}.src.#{url_attr}") |
||||
|> case do |
||||
# It's fetchFromGitHub if we got a list |
||||
[url | _] -> |
||||
URI.parse(url).path |
||||
|> String.split("/archive", trim: true) |
||||
|> List.first() |
||||
|> String.split("/", trim: true) |
||||
|
||||
# It's fetchgit if we got a plain string |
||||
url -> |
||||
URI.parse(url).path |
||||
|> String.split(".git", trim: true) |
||||
|> List.first() |
||||
|> String.split("/", trim: true) |
||||
end |
||||
|> List.to_tuple() |
||||
end |
||||
end |
@ -0,0 +1,28 @@ |
||||
defmodule NixpkgsGitHubUpdate.MixProject do |
||||
use Mix.Project |
||||
|
||||
def project do |
||||
[ |
||||
app: :nixpkgs_github_update, |
||||
version: "0.1.0", |
||||
elixir: "~> 1.9", |
||||
escript: [main_module: NixpkgsGitHubUpdate.CLI], |
||||
start_permanent: Mix.env() == :prod, |
||||
deps: deps() |
||||
] |
||||
end |
||||
|
||||
# Run "mix help compile.app" to learn about applications. |
||||
def application do |
||||
[ |
||||
extra_applications: [:logger, :inets, :ssl] |
||||
] |
||||
end |
||||
|
||||
# Run "mix help deps" to learn about dependencies. |
||||
defp deps do |
||||
[ |
||||
{:poison, "~> 4.0.1"} |
||||
] |
||||
end |
||||
end |
@ -0,0 +1,19 @@ |
||||
with import <nixpkgs> {}; |
||||
|
||||
let |
||||
inherit (lib) optional; |
||||
in |
||||
|
||||
mkShell rec { |
||||
name = "nixpkgs-github-update-shell"; |
||||
|
||||
buildInputs = [ |
||||
elixir |
||||
erlang |
||||
common-updater-scripts |
||||
] |
||||
++ optional stdenv.isLinux libnotify # For ExUnit Notifier on Linux. |
||||
++ optional stdenv.isLinux inotify-tools # For file_system on Linux. |
||||
; |
||||
|
||||
} |
@ -1,36 +1,6 @@ |
||||
{ runCommand |
||||
, nix |
||||
, bash |
||||
, git |
||||
, jq |
||||
, nix-prefetch-scripts |
||||
, coreutils |
||||
, common-updater-scripts |
||||
, gnugrep |
||||
, gnused |
||||
, curl |
||||
}: |
||||
{ nixpkgs-github-update }: |
||||
|
||||
{ repoName |
||||
, attrPath ? repoName |
||||
, versionPolicy ? "release" |
||||
}: |
||||
{ attrPath }: |
||||
|
||||
let |
||||
script = ./update.sh; |
||||
|
||||
updateScript = runCommand "update.sh" { |
||||
inherit bash git jq nix coreutils gnugrep gnused curl; |
||||
# These weren't being substituted |
||||
nix_prefetch_scripts = nix-prefetch-scripts; |
||||
common_updater_scripts = common-updater-scripts; |
||||
} '' |
||||
substituteAll ${script} $out |
||||
chmod +x $out |
||||
''; |
||||
|
||||
throwFlag = throw "${versionPolicy} is not a valid versionPolicy - Options are either 'release' or 'master' (defaults to release)."; |
||||
|
||||
versionFlag = { release = "-r"; master = "-m"; }.${versionPolicy} or throwFlag; |
||||
|
||||
in [ updateScript versionFlag repoName attrPath ] |
||||
[ "${nixpkgs-github-update}/bin/nixpkgs_github_update" "--attribute" attrPath ] |
||||
|
@ -1,236 +0,0 @@ |
||||
#!@bash@/bin/bash |
||||
PATH=@bash@/bin:@nix_prefetch_scripts@/bin:@common_updater_scripts@/bin:@git@/bin:@jq@/bin:@nix@/bin:@gnugrep@/bin:@gnused@/bin:@curl@/bin:$PATH |
||||
#!/usr/bin/env bash |
||||
|
||||
set -eu -o pipefail |
||||
|
||||
# |
||||
# ─── HOW TO USE ───────────────────────────────────────────────────────────────── |
||||
# |
||||
|
||||
function usage ( ) { |
||||
cat <<EOF |
||||
Usage: update.sh <repo_name> <attr> |
||||
EOF |
||||
} |
||||
|
||||
# |
||||
# ─── POINTS YOU IN THE RIGHT DIRECTION ────────────────────────────────────────── |
||||
# |
||||
|
||||
function usage_tip ( ) { |
||||
echo 'run `update.sh -h` for usage instructions' >&2 |
||||
exit 1 |
||||
} |
||||
|
||||
# |
||||
# ─── OPTIONS: RELEASE | MASTER ──────────────────────────────────────────────────── |
||||
# |
||||
|
||||
while getopts ":hrm" opt; do |
||||
case $opt in |
||||
r) |
||||
release=1 |
||||
master=0 |
||||
;; |
||||
m) |
||||
master=1 |
||||
release=0 |
||||
;; |
||||
h) |
||||
usage |
||||
exit |
||||
;; |
||||
?) |
||||
echo "Invalid option: -$OPTARG" >&2 |
||||
usage_tip |
||||
;; |
||||
esac |
||||
done |
||||
|
||||
shift $((OPTIND-1)) |
||||
|
||||
# |
||||
# ─── FAIL WITH MESSAGE AND NON-ZERO EXIT STATUS ───────────────────────────────── |
||||
# |
||||
|
||||
function fail ( ) { |
||||
echo "$1" >&2 |
||||
exit 1 |
||||
} |
||||
|
||||
# |
||||
# ─── UPDATES PACKAGE TO LATEST TAGGED RELEASE ─────────────────────────────── |
||||
# |
||||
|
||||
function update_to_latest_release ( ) { |
||||
repo_name="$1" |
||||
attr="$2" |
||||
|
||||
version=$(get_latest_tag "$repo_name") |
||||
fetch=$(fetch "$repo_name" "refs/tags/${version}") |
||||
sha256=$(get_hash "${fetch}") |
||||
|
||||
update-source-version "pantheon.$attr" "$version" "$sha256" |
||||
|
||||
nix_file=$(get_file_path $attr) |
||||
|
||||
if [ ! -f "$nix_file" ]; then |
||||
fail "Couldn't evaluate 'pantheon.$attr.meta.position' to locate the .nix file!" |
||||
fi |
||||
|
||||
correct_rev "$attr" "$nix_file" "version" |
||||
} |
||||
|
||||
# |
||||
# ─── UPDATES PACKAGE TO MASTER ────────────────────────────────────────────────── |
||||
# |
||||
|
||||
function update_to_master ( ) { |
||||
repo_name="$1" |
||||
attr="$2" |
||||
|
||||
fetch=$(fetch "$repo_name" "refs/heads/master") |
||||
|
||||
version=$(get_version "$fetch") |
||||
sha256=$(get_hash "$fetch") |
||||
proper_version=$(get_master_date "$fetch") |
||||
|
||||
update-source-version "pantheon.$attr" "$proper_version" "$sha256" |
||||
|
||||
nix_file=$(get_file_path $attr) |
||||
|
||||
if [ ! -f "$nix_file" ]; then |
||||
fail "Couldn't evaluate 'pantheon.$attr.meta.position' to locate the .nix file!" |
||||
fi |
||||
|
||||
correct_rev "$attr" "$nix_file" '"'$version'"' |
||||
} |
||||
|
||||
# |
||||
# ─── GETS THE LATEST TAGGED RELEASE NAME FROM GITHUB ───────────────────── |
||||
# |
||||
|
||||
function get_latest_tag ( ) { |
||||
repo_name="$1" |
||||
|
||||
OAUTH_TOKEN=$(printenv OAUTH_TOKEN) |
||||
|
||||
if [ -n "$OAUTH_TOKEN" ]; then |
||||
curl \ |
||||
--silent \ |
||||
--show-error \ |
||||
--fail \ |
||||
-X GET \ |
||||
--header "Authorization: token $OAUTH_TOKEN" \ |
||||
"https://api.github.com/repos/elementary/$repo_name/releases/latest" \ |
||||
| jq -r '.tag_name' |
||||
else |
||||
curl \ |
||||
--silent \ |
||||
--show-error \ |
||||
--fail \ |
||||
-X GET \ |
||||
"https://api.github.com/repos/elementary/$repo_name/releases/latest" \ |
||||
| jq -r '.tag_name' |
||||
fi |
||||
} |
||||
|
||||
# |
||||
# ─── FETCHES REPO AND RETURNS RELEVANT INFORMATION ────────────────── |
||||
# |
||||
|
||||
function fetch ( ) { |
||||
repo_name="$1" |
||||
version="$2" |
||||
|
||||
base_url="https://github.com/elementary" |
||||
full_url="$base_url/$repo_name" |
||||
|
||||
nix-prefetch-git --quiet --no-deepClone --url "$full_url" --rev "$version" |
||||
} |
||||
|
||||
# |
||||
# ─── PARSES GIT REVISION FROM FETCH ───────────────────────────────────────────── |
||||
# |
||||
|
||||
function get_version ( ) { |
||||
fetch_info="$1" |
||||
|
||||
echo "$fetch_info" | jq -r '.rev' |
||||
} |
||||
|
||||
# |
||||
# ─── PARSES HASH FROM FETCH ───────────────────────────────────────────────────── |
||||
# |
||||
|
||||
function get_hash ( ) { |
||||
fetch_info="$1" |
||||
|
||||
echo "$fetch_info" | jq -r '.sha256' |
||||
} |
||||
|
||||
# |
||||
# ─── PARSES DATE FROM FETCH AND NORMALIZES IT TO NIXPKGS STANDARD ─────────────── |
||||
# |
||||
|
||||
function get_master_date ( ) { |
||||
fetch_info="$1" |
||||
|
||||
full_date=$(echo "$fetch_info" | jq -r '.date') |
||||
short_date=$(date -d "$full_date" +"%Y-%m-%d") |
||||
|
||||
echo "unstable-$short_date" |
||||
} |
||||
|
||||
# |
||||
# ─── RETURN NIX EXPRESSION PATH ───────────────────────────────────────────────── |
||||
# |
||||
|
||||
function get_file_path () { |
||||
attr="$1" |
||||
|
||||
nix-instantiate --eval --strict -A "pantheon.$attr.meta.position" | sed -re 's/^"(.*):[0-9]+"$/\1/' |
||||
} |
||||
|
||||
# |
||||
# ─── CORRECTS REV VERSION ─────────────────────────────────────────────────────────── |
||||
# |
||||
|
||||
function correct_rev ( ) { |
||||
attr="$1" |
||||
nix_file="$2" |
||||
rev="$3" |
||||
|
||||
check_pattern1='^\s*rev\s*=\s*"[0-9a-f]{5,40}"' |
||||
check_pattern2='^\s*rev\s*=\s*version' |
||||
|
||||
replace_pattern1='/\brev\b\s*=/ s|\"[0-9a-f]{5,40}\"|'$rev'|' |
||||
replace_pattern2='/\brev\b\s*=/ s|version|'$rev'|' |
||||
|
||||
if [ $(grep -c -P "$check_pattern1" "$nix_file") = 1 ]; then |
||||
pattern="$replace_pattern1" |
||||
elif [ $(grep -c -P "$check_pattern2" "$nix_file") = 1 ]; then |
||||
pattern="$replace_pattern2" |
||||
else |
||||
fail "Couldn't figure out where out where to patch in the correct version in pantheon.$attr!" |
||||
fi |
||||
|
||||
sed -i.bak "$nix_file" -re "$pattern" |
||||
rm -f "$nix_file.bak" |
||||
} |
||||
|
||||
|
||||
# |
||||
# ─── WHETHER TO UPDATE TO RELEASE OR MASTER ────────────────────────────────── |
||||
# |
||||
|
||||
if [ $release = 1 ]; then |
||||
update_to_latest_release $1 $2 |
||||
elif [ $master = 1 ]; then |
||||
update_to_master $1 $2 |
||||
else |
||||
exit 1 |
||||
fi |
||||
|
||||
# ──────────────────────────────────────────────────────────────────────────────── |
Loading…
Reference in new issue