aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.asciidoc4
-rw-r--r--build.config1
-rw-r--r--plugins/hex.mk336
-rw-r--r--test/Makefile2
-rw-r--r--test/plugin_hex.mk457
5 files changed, 799 insertions, 1 deletions
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index f0ff0e2..f237592 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -23,3 +23,7 @@
2020/06/18: Concuerror integration has been added. It is
currently minimal but usable. Experimentation
and feedback is welcome.
+
+2020/11/30: Support for publishing Hex releases and docs
+ has been added. It is currently experimental.
+ Feedback is more than welcome.
diff --git a/build.config b/build.config
index a0ab7a7..b363ef0 100644
--- a/build.config
+++ b/build.config
@@ -29,6 +29,7 @@ plugins/edoc
plugins/erlydtl
plugins/escript
plugins/eunit
+plugins/hex
plugins/proper
plugins/protobuffs
plugins/relx
diff --git a/plugins/hex.mk b/plugins/hex.mk
new file mode 100644
index 0000000..b0a5339
--- /dev/null
+++ b/plugins/hex.mk
@@ -0,0 +1,336 @@
+# Copyright (c) 2020, Loïc Hoguin <[email protected]>
+# This file is part of erlang.mk and subject to the terms of the ISC License.
+
+HEX_CORE_GIT ?= https://github.com/hexpm/hex_core
+HEX_CORE_COMMIT ?= v0.7.0
+
+PACKAGES += hex_core
+pkg_hex_core_name = hex_core
+pkg_hex_core_description = Reference implementation of Hex specifications
+pkg_hex_core_homepage = $(HEX_CORE_GIT)
+pkg_hex_core_fetch = git
+pkg_hex_core_repo = $(HEX_CORE_GIT)
+pkg_hex_core_commit = $(HEX_CORE_COMMIT)
+
+# We automatically depend on hex_core when the project isn't already.
+$(if $(filter hex_core,$(DEPS) $(BUILD_DEPS) $(DOC_DEPS) $(REL_DEPS) $(TEST_DEPS)),,\
+ $(eval $(call dep_target,hex_core)))
+
+hex-core: $(DEPS_DIR)/hex_core
+ $(verbose) if [ ! -e $(DEPS_DIR)/hex_core/ebin/dep_built ]; then \
+ $(MAKE) -C $(DEPS_DIR)/hex_core IS_DEP=1; \
+ touch $(DEPS_DIR)/hex_core/ebin/dep_built; \
+ fi
+
+# @todo This must also apply to fetching.
+HEX_CONFIG ?=
+
+define hex_config.erl
+ begin
+ Config0 = hex_core:default_config(),
+ Config0$(HEX_CONFIG)
+ end
+endef
+
+define hex_user_create.erl
+ {ok, _} = application:ensure_all_started(ssl),
+ {ok, _} = application:ensure_all_started(inets),
+ Config = $(hex_config.erl),
+ case hex_api_user:create(Config, <<"$(strip $1)">>, <<"$(strip $2)">>, <<"$(strip $3)">>) of
+ {ok, {201, _, #{<<"email">> := Email, <<"url">> := URL, <<"username">> := Username}}} ->
+ io:format("User ~s (~s) created at ~s~n"
+ "Please check your inbox for a confirmation email.~n"
+ "You must confirm before you are allowed to publish packages.~n",
+ [Username, Email, URL]),
+ halt(0);
+ {ok, {Status, _, Errors}} ->
+ io:format("Error ~b: ~0p~n", [Status, Errors]),
+ halt(80)
+ end
+endef
+
+# The $(info ) call inserts a new line after the password prompt.
+hex-user-create: hex-core
+ $(if $(HEX_USERNAME),,$(eval HEX_USERNAME := $(shell read -p "Username: " username; echo $$username)))
+ $(if $(HEX_PASSWORD),,$(eval HEX_PASSWORD := $(shell stty -echo; read -p "Password: " password; stty echo; echo $$password) $(info )))
+ $(if $(HEX_EMAIL),,$(eval HEX_EMAIL := $(shell read -p "Email: " email; echo $$email)))
+ $(gen_verbose) $(call erlang,$(call hex_user_create.erl,$(HEX_USERNAME),$(HEX_PASSWORD),$(HEX_EMAIL)))
+
+define hex_key_add.erl
+ {ok, _} = application:ensure_all_started(ssl),
+ {ok, _} = application:ensure_all_started(inets),
+ Config = $(hex_config.erl),
+ ConfigF = Config#{api_key => iolist_to_binary([<<"Basic ">>, base64:encode(<<"$(strip $1):$(strip $2)">>)])},
+ Permissions = [
+ case string:split(P, <<":">>) of
+ [D] -> #{domain => D};
+ [D, R] -> #{domain => D, resource => R}
+ end
+ || P <- string:split(<<"$(strip $4)">>, <<",">>, all)],
+ case hex_api_key:add(ConfigF, <<"$(strip $3)">>, Permissions) of
+ {ok, {201, _, #{<<"secret">> := Secret}}} ->
+ io:format("Key ~s created for user ~s~nSecret: ~s~n"
+ "Please store the secret in a secure location, such as a password store.~n"
+ "The secret will be requested for most Hex-related operations.~n",
+ [<<"$(strip $3)">>, <<"$(strip $1)">>, Secret]),
+ halt(0);
+ {ok, {Status, _, Errors}} ->
+ io:format("Error ~b: ~0p~n", [Status, Errors]),
+ halt(81)
+ end
+endef
+
+hex-key-add: hex-core
+ $(if $(HEX_USERNAME),,$(eval HEX_USERNAME := $(shell read -p "Username: " username; echo $$username)))
+ $(if $(HEX_PASSWORD),,$(eval HEX_PASSWORD := $(shell stty -echo; read -p "Password: " password; stty echo; echo $$password) $(info )))
+ $(gen_verbose) $(call erlang,$(call hex_key_add.erl,$(HEX_USERNAME),$(HEX_PASSWORD),\
+ $(if $(name),$(name),$(shell hostname)-erlang-mk),\
+ $(if $(perm),$(perm),api)))
+
+HEX_TARBALL_EXTRA_METADATA ?=
+
+# @todo Check that we can += files
+HEX_TARBALL_FILES ?= \
+ $(wildcard early-plugins.mk) \
+ $(wildcard ebin/$(PROJECT).app) \
+ $(wildcard ebin/$(PROJECT).appup) \
+ $(wildcard $(notdir $(ERLANG_MK_FILENAME))) \
+ $(sort $(call core_find,include/,*.hrl)) \
+ $(wildcard LICENSE*) \
+ $(wildcard Makefile) \
+ $(wildcard plugins.mk) \
+ $(sort $(call core_find,priv/,*)) \
+ $(wildcard README*) \
+ $(wildcard rebar.config) \
+ $(sort $(call core_find,src/,*))
+
+HEX_TARBALL_OUTPUT_FILE ?= $(ERLANG_MK_TMP)/$(PROJECT).tar
+
+# @todo Need to check for rebar.config and/or the absence of DEPS to know
+# whether a project will work with Rebar.
+#
+# @todo contributors licenses links in HEX_TARBALL_EXTRA_METADATA
+
+# In order to build the requirements metadata we look into DEPS.
+# We do not require that the project use Hex dependencies, however
+# Hex.pm does require that the package name and version numbers
+# correspond to a real Hex package.
+define hex_tarball_create.erl
+ Files0 = [$(call comma_list,$(patsubst %,"%",$(HEX_TARBALL_FILES)))],
+ Requirements0 = #{
+ $(foreach d,$(DEPS),
+ <<"$(if $(subst hex,,$(call query_fetch_method,$d)),$d,$(if $(word 3,$(dep_$d)),$(word 3,$(dep_$d)),$d))">> => #{
+ <<"app">> => <<"$d">>,
+ <<"optional">> => false,
+ <<"requirement">> => <<"$(call query_version,$d)">>
+ },)
+ $(if $(DEPS),dummy => dummy)
+ },
+ Requirements = maps:remove(dummy, Requirements0),
+ Metadata0 = #{
+ app => <<"$(strip $(PROJECT))">>,
+ build_tools => [<<"make">>, <<"rebar3">>],
+ description => <<"$(strip $(PROJECT_DESCRIPTION))">>,
+ files => [unicode:characters_to_binary(F) || F <- Files0],
+ name => <<"$(strip $(PROJECT))">>,
+ requirements => Requirements,
+ version => <<"$(strip $(PROJECT_VERSION))">>
+ },
+ Metadata = Metadata0$(HEX_TARBALL_EXTRA_METADATA),
+ Files = [case file:read_file(F) of
+ {ok, Bin} ->
+ {F, Bin};
+ {error, Reason} ->
+ io:format("Error trying to open file ~0p: ~0p~n", [F, Reason]),
+ halt(82)
+ end || F <- Files0],
+ case hex_tarball:create(Metadata, Files) of
+ {ok, #{tarball := Tarball}} ->
+ ok = file:write_file("$(strip $(HEX_TARBALL_OUTPUT_FILE))", Tarball),
+ halt(0);
+ {error, Reason} ->
+ io:format("Error ~0p~n", [Reason]),
+ halt(83)
+ end
+endef
+
+hex_tar_verbose_0 = @echo " TAR $(notdir $(ERLANG_MK_TMP))/$(@F)";
+hex_tar_verbose_2 = set -x;
+hex_tar_verbose = $(hex_tar_verbose_$(V))
+
+$(HEX_TARBALL_OUTPUT_FILE): hex-core app
+ $(hex_tar_verbose) $(call erlang,$(call hex_tarball_create.erl))
+
+hex-tarball-create: $(HEX_TARBALL_OUTPUT_FILE)
+
+define hex_release_publish_summary.erl
+ {ok, Tarball} = erl_tar:open("$(strip $(HEX_TARBALL_OUTPUT_FILE))", [read]),
+ ok = erl_tar:extract(Tarball, [{cwd, "$(ERLANG_MK_TMP)"}, {files, ["metadata.config"]}]),
+ {ok, Metadata} = file:consult("$(ERLANG_MK_TMP)/metadata.config"),
+ #{
+ <<"name">> := Name,
+ <<"version">> := Version,
+ <<"files">> := Files,
+ <<"requirements">> := Deps
+ } = maps:from_list(Metadata),
+ io:format("Publishing ~s ~s~n Dependencies:~n", [Name, Version]),
+ case Deps of
+ [] ->
+ io:format(" (none)~n");
+ _ ->
+ [begin
+ #{<<"app">> := DA, <<"requirement">> := DR} = maps:from_list(D),
+ io:format(" ~s ~s~n", [DA, DR])
+ end || {_, D} <- Deps]
+ end,
+ io:format(" Included files:~n"),
+ [io:format(" ~s~n", [F]) || F <- Files],
+ io:format("You may also review the contents of the tarball file.~n"
+ "Please enter your secret key to proceed.~n"),
+ halt(0)
+endef
+
+define hex_release_publish.erl
+ {ok, _} = application:ensure_all_started(ssl),
+ {ok, _} = application:ensure_all_started(inets),
+ Config = $(hex_config.erl),
+ ConfigF = Config#{api_key => <<"$(strip $1)">>},
+ {ok, Tarball} = file:read_file("$(strip $(HEX_TARBALL_OUTPUT_FILE))"),
+ case hex_api_release:publish(ConfigF, Tarball, [{replace, $2}]) of
+ {ok, {200, _, #{}}} ->
+ io:format("Release replaced~n"),
+ halt(0);
+ {ok, {201, _, #{}}} ->
+ io:format("Release published~n"),
+ halt(0);
+ {ok, {Status, _, Errors}} ->
+ io:format("Error ~b: ~0p~n", [Status, Errors]),
+ halt(84)
+ end
+endef
+
+hex-release-tarball: hex-core $(HEX_TARBALL_OUTPUT_FILE)
+ $(verbose) $(call erlang,$(call hex_release_publish_summary.erl))
+
+hex-release-publish: hex-core hex-release-tarball
+ $(if $(HEX_SECRET),,$(eval HEX_SECRET := $(shell stty -echo; read -p "Secret: " secret; stty echo; echo $$secret) $(info )))
+ $(gen_verbose) $(call erlang,$(call hex_release_publish.erl,$(HEX_SECRET),false))
+
+hex-release-replace: hex-core hex-release-tarball
+ $(if $(HEX_SECRET),,$(eval HEX_SECRET := $(shell stty -echo; read -p "Secret: " secret; stty echo; echo $$secret) $(info )))
+ $(gen_verbose) $(call erlang,$(call hex_release_publish.erl,$(HEX_SECRET),true))
+
+define hex_release_delete.erl
+ {ok, _} = application:ensure_all_started(ssl),
+ {ok, _} = application:ensure_all_started(inets),
+ Config = $(hex_config.erl),
+ ConfigF = Config#{api_key => <<"$(strip $1)">>},
+ case hex_api_release:delete(ConfigF, <<"$(strip $(PROJECT))">>, <<"$(strip $(PROJECT_VERSION))">>) of
+ {ok, {204, _, _}} ->
+ io:format("Release $(strip $(PROJECT_VERSION)) deleted~n"),
+ halt(0);
+ {ok, {Status, _, Errors}} ->
+ io:format("Error ~b: ~0p~n", [Status, Errors]),
+ halt(85)
+ end
+endef
+
+hex-release-delete: hex-core
+ $(if $(HEX_SECRET),,$(eval HEX_SECRET := $(shell stty -echo; read -p "Secret: " secret; stty echo; echo $$secret) $(info )))
+ $(gen_verbose) $(call erlang,$(call hex_release_delete.erl,$(HEX_SECRET)))
+
+define hex_release_retire.erl
+ {ok, _} = application:ensure_all_started(ssl),
+ {ok, _} = application:ensure_all_started(inets),
+ Config = $(hex_config.erl),
+ ConfigF = Config#{api_key => <<"$(strip $1)">>},
+ Params = #{<<"reason">> => <<"$(strip $3)">>, <<"message">> => <<"$(strip $4)">>},
+ case hex_api_release:retire(ConfigF, <<"$(strip $(PROJECT))">>, <<"$(strip $2)">>, Params) of
+ {ok, {204, _, _}} ->
+ io:format("Release $(strip $2) has been retired~n"),
+ halt(0);
+ {ok, {Status, _, Errors}} ->
+ io:format("Error ~b: ~0p~n", [Status, Errors]),
+ halt(86)
+ end
+endef
+
+hex-release-retire: hex-core
+ $(if $(HEX_SECRET),,$(eval HEX_SECRET := $(shell stty -echo; read -p "Secret: " secret; stty echo; echo $$secret) $(info )))
+ $(gen_verbose) $(call erlang,$(call hex_release_retire.erl,$(HEX_SECRET),\
+ $(if $(HEX_VERSION),$(HEX_VERSION),$(PROJECT_VERSION)),\
+ $(if $(HEX_REASON),$(HEX_REASON),invalid),\
+ $(HEX_MESSAGE)))
+
+define hex_release_unretire.erl
+ {ok, _} = application:ensure_all_started(ssl),
+ {ok, _} = application:ensure_all_started(inets),
+ Config = $(hex_config.erl),
+ ConfigF = Config#{api_key => <<"$(strip $1)">>},
+ case hex_api_release:unretire(ConfigF, <<"$(strip $(PROJECT))">>, <<"$(strip $2)">>) of
+ {ok, {204, _, _}} ->
+ io:format("Release $(strip $2) is not retired anymore~n"),
+ halt(0);
+ {ok, {Status, _, Errors}} ->
+ io:format("Error ~b: ~0p~n", [Status, Errors]),
+ halt(87)
+ end
+endef
+
+hex-release-unretire: hex-core
+ $(if $(HEX_SECRET),,$(eval HEX_SECRET := $(shell stty -echo; read -p "Secret: " secret; stty echo; echo $$secret) $(info )))
+ $(gen_verbose) $(call erlang,$(call hex_release_unretire.erl,$(HEX_SECRET),\
+ $(if $(HEX_VERSION),$(HEX_VERSION),$(PROJECT_VERSION))))
+
+HEX_DOCS_DOC_DIR ?= doc/
+HEX_DOCS_TARBALL_FILES ?= $(sort $(call core_find,$(HEX_DOCS_DOC_DIR),*))
+HEX_DOCS_TARBALL_OUTPUT_FILE ?= $(ERLANG_MK_TMP)/$(PROJECT)-docs.tar.gz
+
+$(HEX_DOCS_TARBALL_OUTPUT_FILE): hex-core app docs
+ $(hex_tar_verbose) tar czf $(HEX_DOCS_TARBALL_OUTPUT_FILE) -C $(HEX_DOCS_DOC_DIR) \
+ $(HEX_DOCS_TARBALL_FILES:$(HEX_DOCS_DOC_DIR)%=%)
+
+hex-docs-tarball-create: $(HEX_DOCS_TARBALL_OUTPUT_FILE)
+
+define hex_docs_publish.erl
+ {ok, _} = application:ensure_all_started(ssl),
+ {ok, _} = application:ensure_all_started(inets),
+ Config = $(hex_config.erl),
+ ConfigF = Config#{api_key => <<"$(strip $1)">>},
+ {ok, Tarball} = file:read_file("$(strip $(HEX_DOCS_TARBALL_OUTPUT_FILE))"),
+ case hex_api:post(ConfigF,
+ ["packages", "$(strip $(PROJECT))", "releases", "$(strip $(PROJECT_VERSION))", "docs"],
+ {"application/octet-stream", Tarball}) of
+ {ok, {Status, _, _}} when Status >= 200, Status < 300 ->
+ io:format("Docs published~n"),
+ halt(0);
+ {ok, {Status, _, Errors}} ->
+ io:format("Error ~b: ~0p~n", [Status, Errors]),
+ halt(88)
+ end
+endef
+
+hex-docs-publish: hex-core hex-docs-tarball-create
+ $(if $(HEX_SECRET),,$(eval HEX_SECRET := $(shell stty -echo; read -p "Secret: " secret; stty echo; echo $$secret) $(info )))
+ $(gen_verbose) $(call erlang,$(call hex_docs_publish.erl,$(HEX_SECRET)))
+
+define hex_docs_delete.erl
+ {ok, _} = application:ensure_all_started(ssl),
+ {ok, _} = application:ensure_all_started(inets),
+ Config = $(hex_config.erl),
+ ConfigF = Config#{api_key => <<"$(strip $1)">>},
+ case hex_api:delete(ConfigF,
+ ["packages", "$(strip $(PROJECT))", "releases", "$(strip $2)", "docs"]) of
+ {ok, {Status, _, _}} when Status >= 200, Status < 300 ->
+ io:format("Docs removed~n"),
+ halt(0);
+ {ok, {Status, _, Errors}} ->
+ io:format("Error ~b: ~0p~n", [Status, Errors]),
+ halt(89)
+ end
+endef
+
+hex-docs-delete: hex-core
+ $(if $(HEX_SECRET),,$(eval HEX_SECRET := $(shell stty -echo; read -p "Secret: " secret; stty echo; echo $$secret) $(info )))
+ $(gen_verbose) $(call erlang,$(call hex_docs_delete.erl,$(HEX_SECRET),\
+ $(if $(HEX_VERSION),$(HEX_VERSION),$(PROJECT_VERSION))))
diff --git a/test/Makefile b/test/Makefile
index 4a8b5e3..8d1a5e8 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -124,7 +124,7 @@ endef
all:: core
clean::
- $t rm -rf erl_crash.dump packages/ test_*/
+ $t rm -rf erl_crash.dump packages/ $(filter-out test_rebar_git/,$(wildcard test_*/))
init: clean
$i "Prefetch Rebar if necessary"
diff --git a/test/plugin_hex.mk b/test/plugin_hex.mk
new file mode 100644
index 0000000..66bf6fc
--- /dev/null
+++ b/test/plugin_hex.mk
@@ -0,0 +1,457 @@
+# Hex plugin.
+#
+# In order to run these tests, a local Hex.pm instance must
+# be started and available on port 4000, and the HEX=1 variable
+# must be set.
+
+HEX_TARGETS = $(call list_targets,hex)
+
+.PHONY: hex $(HEX_TARGETS)
+
+hex: $(HEX_TARGETS)
+
+ifeq ($(shell netcat -z localhost 4000 && echo ok),ok)
+hex-user-create: init
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Configure a local Hex provider"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_CONFIG\n#{api_url => <<\"http://localhost:4000/api\">>}\nendef\n"}' $(APP)/Makefile
+
+ $i "Create a Hex user"
+ $t $(MAKE) -C $(APP) hex-user-create HEX_USERNAME=$(APP) HEX_PASSWORD="1234567" HEX_EMAIL=$(APP)@noone.nope $v
+
+ $i "Check that the user exists"
+ $t curl -sf http://localhost:4000/api/users/$(APP) >/dev/null
+
+# @todo Fix this.
+#hex-user-create-password-with-dollar-sign: init
+#
+# $i "Bootstrap a new OTP application named $(APP)"
+# $t mkdir $(APP)/
+# $t cp ../erlang.mk $(APP)/
+# $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+#
+# $i "Configure a local Hex provider"
+# $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_CONFIG\n#{api_url => <<\"http://localhost:4000/api\">>}\nendef\n"}' $(APP)/Makefile
+#
+# $i "Create a Hex user"
+# $t $(MAKE) -C $(APP) hex-user-create HEX_USERNAME=$(APP) HEX_PASSWORD="123$$567" HEX_EMAIL=$(APP)@noone.nope $v
+#
+# $i "Check that the user exists"
+# $t curl --user "$(APP):123$$567" -sf http://localhost:4000/api/users/$(APP) >/dev/null
+
+# @todo Fix this.
+#hex-user-create-password-with-backslash: init
+#
+# $i "Bootstrap a new OTP application named $(APP)"
+# $t mkdir $(APP)/
+# $t cp ../erlang.mk $(APP)/
+# $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+#
+# $i "Configure a local Hex provider"
+# $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_CONFIG\n#{api_url => <<\"http://localhost:4000/api\">>}\nendef\n"}' $(APP)/Makefile
+#
+# $i "Create a Hex user"
+# $t $(MAKE) -C $(APP) hex-user-create HEX_USERNAME=$(APP) HEX_PASSWORD="123\\567" HEX_EMAIL=$(APP)@noone.nope $v
+#
+# $i "Check that the user exists"
+# $t curl --user "$(APP):123\\567" -sf http://localhost:4000/api/users/$(APP) >/dev/null
+
+hex-user-create-password-with-space: init
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Configure a local Hex provider"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_CONFIG\n#{api_url => <<\"http://localhost:4000/api\">>}\nendef\n"}' $(APP)/Makefile
+
+ $i "Create a Hex user"
+ $t $(MAKE) -C $(APP) hex-user-create HEX_USERNAME=$(APP) HEX_PASSWORD="123 567" HEX_EMAIL=$(APP)@noone.nope $v
+
+ $i "Check that the user exists"
+ $t curl --user "$(APP):123 567" -sf http://localhost:4000/api/users/$(APP) >/dev/null
+
+hex-key-add: init
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Configure a local Hex provider"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_CONFIG\n#{api_url => <<\"http://localhost:4000/api\">>}\nendef\n"}' $(APP)/Makefile
+
+ $i "Create a Hex user"
+ $t $(MAKE) -C $(APP) hex-user-create HEX_USERNAME=$(APP) HEX_PASSWORD="1234567" HEX_EMAIL=$(APP)@noone.nope $v
+
+ $i "Create a key for that user"
+ $t $(MAKE) -C $(APP) hex-key-add HEX_USERNAME=$(APP) HEX_PASSWORD="1234567" $v
+
+ $i "Check that the key exists"
+ $t curl --user $(APP):1234567 -sf http://localhost:4000/api/keys/$(shell hostname)-erlang-mk >/dev/null
+
+hex-tarball-create: init
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Create a release tarball"
+ $t $(MAKE) -C $(APP) hex-tarball-create $v
+
+ $i "Confirm the tarball contents can be extracted"
+ $t cd $(APP)/.erlang.mk/ && tar xf $(APP).tar
+
+ $i "Confirm the tarball contains a CHECKSUM file"
+ $t test -f $(APP)/.erlang.mk/CHECKSUM
+
+ $i "Confirm the tarball contains a VERSION file containing '3'"
+ $t cat $(APP)/.erlang.mk/VERSION | grep -q ^3$$
+
+ $i "Confirm the tarball contains a valid metadata.config file"
+ $t $(ERL) -eval " \
+ {ok, _} = file:consult(\"$(APP)/.erlang.mk/metadata.config\"), \
+ halt(0)"
+
+ $i "Confirm the tarball contains a contents.tar.gz file that can be extracted"
+ $t cd $(APP)/.erlang.mk/ && tar xf contents.tar.gz
+
+ $i "Confirm contents.tar.gz contains the expected files"
+ $t printf "%s\n" \
+ erlang.mk \
+ Makefile \
+ ebin/$(APP).app \
+ src/$(APP)_app.erl \
+ src/$(APP)_sup.erl | sort > $(APP)/.erlang.mk/EXPECT
+ $t cd $(APP)/.erlang.mk/ && tar tf contents.tar.gz | sort | diff EXPECT -
+
+hex-tarball-create-with-deps: init
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Add Cowlib to the list of dependencies"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "DEPS = cowlib\ndep_cowlib_commit = 2.10.1\n"}' $(APP)/Makefile
+
+ifdef LEGACY
+ $i "Add Cowlib to the applications key in the .app.src file"
+ $t perl -ni.bak -e 'print;if ($$.==7) {print "\t\tcowlib,\n"}' $(APP)/src/$(APP).app.src
+endif
+
+ $i "Create a release tarball"
+ $t $(MAKE) -C $(APP) hex-tarball-create $v
+
+ $i "Confirm the tarball contents can be extracted"
+ $t cd $(APP)/.erlang.mk/ && tar xf $(APP).tar
+
+ $i "Confirm the tarball contains a metadata.config file that lists Cowlib as requirement"
+ $t $(ERL) -eval " \
+ {ok, Metadata} = file:consult(\"$(APP)/.erlang.mk/metadata.config\"), \
+ {_, [{<<\"cowlib\">>, Cowlib}]} = lists:keyfind(<<\"requirements\">>, 1, Metadata), \
+ {_, <<\"cowlib\">>} = lists:keyfind(<<\"app\">>, 1, Cowlib), \
+ {_, false} = lists:keyfind(<<\"optional\">>, 1, Cowlib), \
+ {_, <<\"2.10.1\">>} = lists:keyfind(<<\"requirement\">>, 1, Cowlib), \
+ halt(0)"
+
+hex-release-publish: init
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Configure a local Hex provider"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_CONFIG\n#{api_url => <<\"http://localhost:4000/api\">>}\nendef\n"}' $(APP)/Makefile
+
+ $i "Add extra Hex metadata"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_TARBALL_EXTRA_METADATA\n#{licenses => [<<\"ISC\">>]}\nendef\n"}' $(APP)/Makefile
+
+ $i "Create a Hex user"
+ $t $(MAKE) -C $(APP) hex-user-create HEX_USERNAME=$(APP) HEX_PASSWORD="1234567" HEX_EMAIL=$(APP)@noone.nope $v
+
+ $i "Create a key for that user"
+ $t $(MAKE) -C $(APP) hex-key-add HEX_USERNAME=$(APP) HEX_PASSWORD="1234567" | grep ^Secret: | cut -f2 -d" " > $(APP)/hex.key
+
+ $i "Publish the release"
+ $t $(MAKE) -C $(APP) hex-release-publish HEX_SECRET=`cat $(APP)/hex.key` $v
+
+ $i "Check that the release exists"
+ $t curl -sf http://localhost:4000/api/packages/$(APP)/releases/0.1.0 >/dev/null
+
+hex-release-publish-with-deps: init
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Add Cowlib to the list of dependencies"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "DEPS = cowlib\ndep_cowlib_commit = 2.10.1\n"}' $(APP)/Makefile
+
+ifdef LEGACY
+ $i "Add Cowlib to the applications key in the .app.src file"
+ $t perl -ni.bak -e 'print;if ($$.==7) {print "\t\tcowlib,\n"}' $(APP)/src/$(APP).app.src
+endif
+
+ $i "Build the application"
+ $t $(MAKE) -C $(APP) $v
+
+ $i "Configure a local Hex provider for Cowlib"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_CONFIG\n#{api_url => <<\"http://localhost:4000/api\">>}\nendef\n"}' $(APP)/deps/cowlib/Makefile
+
+ $i "Configure a local Hex provider"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_CONFIG\n#{api_url => <<\"http://localhost:4000/api\">>}\nendef\n"}' $(APP)/Makefile
+
+ $i "Add extra Hex metadata"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_TARBALL_EXTRA_METADATA\n#{licenses => [<<\"ISC\">>]}\nendef\n"}' $(APP)/Makefile
+
+ $i "Create a Hex user"
+ $t $(MAKE) -C $(APP) hex-user-create HEX_USERNAME=$(APP) HEX_PASSWORD="1234567" HEX_EMAIL=$(APP)@noone.nope $v
+
+ $i "Create a key for that user"
+ $t $(MAKE) -C $(APP) hex-key-add HEX_USERNAME=$(APP) HEX_PASSWORD="1234567" | grep ^Secret: | cut -f2 -d" " > $(APP)/hex.key
+
+ $i "Publish the Cowlib release"
+ $t $(MAKE) -C $(APP)/deps/cowlib hex-release-publish HEX_SECRET=`cat $(APP)/hex.key` $v
+
+ $i "Publish the release"
+ $t $(MAKE) -C $(APP) hex-release-publish HEX_SECRET=`cat $(APP)/hex.key` $v
+
+ $i "Check that the release exists and includes Cowlib as requirement"
+ $t curl -sf http://localhost:4000/api/packages/$(APP)/releases/0.1.0 | grep -q cowlib
+
+hex-release-replace: init
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Configure a local Hex provider"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_CONFIG\n#{api_url => <<\"http://localhost:4000/api\">>}\nendef\n"}' $(APP)/Makefile
+
+ $i "Add extra Hex metadata"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_TARBALL_EXTRA_METADATA\n#{licenses => [<<\"ISC\">>]}\nendef\n"}' $(APP)/Makefile
+
+ $i "Create a Hex user"
+ $t $(MAKE) -C $(APP) hex-user-create HEX_USERNAME=$(APP) HEX_PASSWORD="1234567" HEX_EMAIL=$(APP)@noone.nope $v
+
+ $i "Create a key for that user"
+ $t $(MAKE) -C $(APP) hex-key-add HEX_USERNAME=$(APP) HEX_PASSWORD="1234567" | grep ^Secret: | cut -f2 -d" " > $(APP)/hex.key
+
+ $i "Publish the release"
+ $t $(MAKE) -C $(APP) hex-release-publish HEX_SECRET=`cat $(APP)/hex.key` $v
+
+ $i "Update the project description"
+ $t sed -i.bak s/"PROJECT_DESCRIPTION = New project"/"PROJECT_DESCRIPTION = Best project"/ $(APP)/Makefile
+
+ $i "Publish the release again, replacing the existing one"
+ $t $(MAKE) -C $(APP) hex-release-replace HEX_SECRET=`cat $(APP)/hex.key` $v
+
+ $i "Check that the release was replaced"
+ $t curl -sf http://localhost:4000/api/packages/$(APP) | grep -q "Best project"
+
+hex-release-delete: init
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Configure a local Hex provider"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_CONFIG\n#{api_url => <<\"http://localhost:4000/api\">>}\nendef\n"}' $(APP)/Makefile
+
+ $i "Add extra Hex metadata"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_TARBALL_EXTRA_METADATA\n#{licenses => [<<\"ISC\">>]}\nendef\n"}' $(APP)/Makefile
+
+ $i "Create a Hex user"
+ $t $(MAKE) -C $(APP) hex-user-create HEX_USERNAME=$(APP) HEX_PASSWORD="1234567" HEX_EMAIL=$(APP)@noone.nope $v
+
+ $i "Create a key for that user"
+ $t $(MAKE) -C $(APP) hex-key-add HEX_USERNAME=$(APP) HEX_PASSWORD="1234567" | grep ^Secret: | cut -f2 -d" " > $(APP)/hex.key
+
+ $i "Publish the release"
+ $t $(MAKE) -C $(APP) hex-release-publish HEX_SECRET=`cat $(APP)/hex.key` $v
+
+ $i "Delete the release"
+ $t $(MAKE) -C $(APP) hex-release-delete HEX_SECRET=`cat $(APP)/hex.key` $v
+
+ $i "Check that the release was deleted"
+ $t ! curl -sf http://localhost:4000/api/packages/$(APP)/releases/0.1.0 >/dev/null
+
+hex-release-retire: init
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Configure a local Hex provider"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_CONFIG\n#{api_url => <<\"http://localhost:4000/api\">>}\nendef\n"}' $(APP)/Makefile
+
+ $i "Add extra Hex metadata"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_TARBALL_EXTRA_METADATA\n#{licenses => [<<\"ISC\">>]}\nendef\n"}' $(APP)/Makefile
+
+ $i "Create a Hex user"
+ $t $(MAKE) -C $(APP) hex-user-create HEX_USERNAME=$(APP) HEX_PASSWORD="1234567" HEX_EMAIL=$(APP)@noone.nope $v
+
+ $i "Create a key for that user"
+ $t $(MAKE) -C $(APP) hex-key-add HEX_USERNAME=$(APP) HEX_PASSWORD="1234567" | grep ^Secret: | cut -f2 -d" " > $(APP)/hex.key
+
+ $i "Publish the release"
+ $t $(MAKE) -C $(APP) hex-release-publish HEX_SECRET=`cat $(APP)/hex.key` $v
+
+ $i "Retire the release"
+ $t $(MAKE) -C $(APP) hex-release-retire HEX_SECRET=`cat $(APP)/hex.key` $v
+
+ $i "Check that the release was retired"
+ $t ! curl -sf http://localhost:4000/api/packages/$(APP)/releases/0.1.0 | grep -q \"retirement\":null
+
+hex-release-unretire: init
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Configure a local Hex provider"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_CONFIG\n#{api_url => <<\"http://localhost:4000/api\">>}\nendef\n"}' $(APP)/Makefile
+
+ $i "Add extra Hex metadata"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_TARBALL_EXTRA_METADATA\n#{licenses => [<<\"ISC\">>]}\nendef\n"}' $(APP)/Makefile
+
+ $i "Create a Hex user"
+ $t $(MAKE) -C $(APP) hex-user-create HEX_USERNAME=$(APP) HEX_PASSWORD="1234567" HEX_EMAIL=$(APP)@noone.nope $v
+
+ $i "Create a key for that user"
+ $t $(MAKE) -C $(APP) hex-key-add HEX_USERNAME=$(APP) HEX_PASSWORD="1234567" | grep ^Secret: | cut -f2 -d" " > $(APP)/hex.key
+
+ $i "Publish the release"
+ $t $(MAKE) -C $(APP) hex-release-publish HEX_SECRET=`cat $(APP)/hex.key` $v
+
+ $i "Retire the release"
+ $t $(MAKE) -C $(APP) hex-release-retire HEX_SECRET=`cat $(APP)/hex.key` $v
+
+ $i "Unretire the release"
+ $t $(MAKE) -C $(APP) hex-release-unretire HEX_SECRET=`cat $(APP)/hex.key` $v
+
+ $i "Check that the release is no longer retired"
+ $t curl -sf http://localhost:4000/api/packages/$(APP)/releases/0.1.0 | grep -q \"retirement\":null
+
+hex-docs-tarball-create: init
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Generate a doc/overview.edoc file"
+ $t mkdir $(APP)/doc
+ $t printf "%s\n" \
+ "@author R. J. Hacker <[email protected]>" \
+ "@copyright 2007 R. J. Hacker" \
+ "@version 1.0.0" \
+ "@title Welcome to the 'frob' application!" \
+ "@doc 'frob' is a highly advanced frobnicator with low latency," > $(APP)/doc/overview.edoc
+
+ $i "Create a docs tarball"
+ $t $(MAKE) -C $(APP) hex-docs-tarball-create $v
+
+ $i "Confirm the tarball contents can be extracted"
+ $t cd $(APP)/.erlang.mk/ && tar xf $(APP)-docs.tar.gz
+
+ $i "Confirm the tarball contains the expected files"
+ $t printf "%s\n" \
+ edoc-info \
+ erlang.png \
+ index.html \
+ modules-frame.html \
+ overview-summary.html \
+ overview.edoc \
+ stylesheet.css \
+ $(APP)_app.html \
+ $(APP)_sup.html | sort > $(APP)/.erlang.mk/EXPECT
+ $t cd $(APP)/.erlang.mk/ && tar tf $(APP)-docs.tar.gz | sort | diff EXPECT -
+
+hex-docs-publish: init
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Generate a doc/overview.edoc file"
+ $t mkdir $(APP)/doc
+ $t printf "%s\n" \
+ "@author R. J. Hacker <[email protected]>" \
+ "@copyright 2007 R. J. Hacker" \
+ "@version 1.0.0" \
+ "@title Welcome to the 'frob' application!" \
+ "@doc 'frob' is a highly advanced frobnicator with low latency," > $(APP)/doc/overview.edoc
+
+ $i "Configure a local Hex provider"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_CONFIG\n#{api_url => <<\"http://localhost:4000/api\">>}\nendef\n"}' $(APP)/Makefile
+
+ $i "Add extra Hex metadata"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_TARBALL_EXTRA_METADATA\n#{licenses => [<<\"ISC\">>]}\nendef\n"}' $(APP)/Makefile
+
+ $i "Create a Hex user"
+ $t $(MAKE) -C $(APP) hex-user-create HEX_USERNAME=$(APP) HEX_PASSWORD="1234567" HEX_EMAIL=$(APP)@noone.nope $v
+
+ $i "Create a key for that user"
+ $t $(MAKE) -C $(APP) hex-key-add HEX_USERNAME=$(APP) HEX_PASSWORD="1234567" | grep ^Secret: | cut -f2 -d" " > $(APP)/hex.key
+
+ $i "Publish the release"
+ $t $(MAKE) -C $(APP) hex-release-publish HEX_SECRET=`cat $(APP)/hex.key` $v
+
+ $i "Publish the documentation for the release"
+ $t $(MAKE) -C $(APP) hex-docs-publish HEX_SECRET=`cat $(APP)/hex.key` $v
+
+# @todo hex-docs-publish when there are no docs
+
+hex-docs-delete: init
+
+ $i "Bootstrap a new OTP application named $(APP)"
+ $t mkdir $(APP)/
+ $t cp ../erlang.mk $(APP)/
+ $t $(MAKE) -C $(APP) -f erlang.mk bootstrap $v
+
+ $i "Generate a doc/overview.edoc file"
+ $t mkdir $(APP)/doc
+ $t printf "%s\n" \
+ "@author R. J. Hacker <[email protected]>" \
+ "@copyright 2007 R. J. Hacker" \
+ "@version 1.0.0" \
+ "@title Welcome to the 'frob' application!" \
+ "@doc 'frob' is a highly advanced frobnicator with low latency," > $(APP)/doc/overview.edoc
+
+ $i "Configure a local Hex provider"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_CONFIG\n#{api_url => <<\"http://localhost:4000/api\">>}\nendef\n"}' $(APP)/Makefile
+
+ $i "Add extra Hex metadata"
+ $t perl -ni.bak -e 'print;if ($$.==1) {print "define HEX_TARBALL_EXTRA_METADATA\n#{licenses => [<<\"ISC\">>]}\nendef\n"}' $(APP)/Makefile
+
+ $i "Create a Hex user"
+ $t $(MAKE) -C $(APP) hex-user-create HEX_USERNAME=$(APP) HEX_PASSWORD="1234567" HEX_EMAIL=$(APP)@noone.nope $v
+
+ $i "Create a key for that user"
+ $t $(MAKE) -C $(APP) hex-key-add HEX_USERNAME=$(APP) HEX_PASSWORD="1234567" | grep ^Secret: | cut -f2 -d" " > $(APP)/hex.key
+
+ $i "Publish the release"
+ $t $(MAKE) -C $(APP) hex-release-publish HEX_SECRET=`cat $(APP)/hex.key` $v
+
+ $i "Publish the documentation for the release"
+ $t $(MAKE) -C $(APP) hex-docs-publish HEX_SECRET=`cat $(APP)/hex.key` $v
+
+ $i "Delete the documentation for the release"
+ $t $(MAKE) -C $(APP) hex-docs-delete HEX_SECRET=`cat $(APP)/hex.key` $v
+endif