50 | {% endblock %}
51 |
--------------------------------------------------------------------------------
/docs/source/_themes/sphinx_rtd_theme/sphinx_rtd_theme/static/js/theme.js:
--------------------------------------------------------------------------------
1 | $( document ).ready(function() {
2 | // Shift nav in mobile when clicking the menu.
3 | $(document).on('click', "[data-toggle='wy-nav-top']", function() {
4 | $("[data-toggle='wy-nav-shift']").toggleClass("shift");
5 | $("[data-toggle='rst-versions']").toggleClass("shift");
6 | });
7 | // Close menu when you click a link.
8 | $(document).on('click', ".wy-menu-vertical .current ul li a", function() {
9 | $("[data-toggle='wy-nav-shift']").removeClass("shift");
10 | $("[data-toggle='rst-versions']").toggleClass("shift");
11 | });
12 | $(document).on('click', "[data-toggle='rst-current-version']", function() {
13 | $("[data-toggle='rst-versions']").toggleClass("shift-up");
14 | });
15 | // Make tables responsive
16 | $("table.docutils:not(.field-list)").wrap("");
17 | });
18 |
19 | window.SphinxRtdTheme = (function (jquery) {
20 | var stickyNav = (function () {
21 | var navBar,
22 | win,
23 | stickyNavCssClass = 'stickynav',
24 | applyStickNav = function () {
25 | if (navBar.height() <= win.height()) {
26 | navBar.addClass(stickyNavCssClass);
27 | } else {
28 | navBar.removeClass(stickyNavCssClass);
29 | }
30 | },
31 | enable = function () {
32 | applyStickNav();
33 | win.on('resize', applyStickNav);
34 | },
35 | init = function () {
36 | navBar = jquery('nav.wy-nav-side:first');
37 | win = jquery(window);
38 | };
39 | jquery(init);
40 | return {
41 | enable : enable
42 | };
43 | }());
44 | return {
45 | StickyNav : stickyNav
46 | };
47 | }($));
48 |
--------------------------------------------------------------------------------
/test/fixtures/example_app/priv/sample.txt:
--------------------------------------------------------------------------------
1 | The Chiss were governed by an oligarchy of extended Ruling Families from House Palace, located in the city of Csaplar. Each clan with the families was headed by leaders known as Aristocra who wore particular colors to indicate their clan and family loyalties. Standard and day-to-day decisions were made by a democratically elected parliamentary body from each of the 28 colonies. Issues were siphoned up through the parliament to a cabinet of appointed governors, and then to the ruling families, where a decision made by the parliament and/or cabinet could be approved for action. Each of the extended ruling families was responsible for a set of government affairs to manage: House Sabosen was responsible for social issues such as justice, health, and education; House Inrokini was responsible for industry and science; House Csapla was responsible for colonial affairs, agriculture and redistribution of resources; and House Nuruodo was responsible for military and foreign affairs. The Csapla's redistribution of resources amongst the Chiss colonies and Csilla was particularly important, given the collectivist-socialist economic system of the Chiss, and led to their relative position at the head of the families, with the others acting in an advisory role. House Nuruodo would be ranked as second, considering the importance of warfare on Chiss society.
2 |
3 | Each family was equally represented in the Chiss government, although they went to great lengths to ensure that family identity was eliminated wherever possible. The leaders of the Chiss did not use names, but instead wore colorful robes to distinguish themselves. This helped ensure that decisions were reached in a fair and equitable method. Although the four extended ruling families were not known to face power struggles, five lesser clans often vied for greater authority and power, such as House Chaf, which was considered the fifth ruling family.
4 |
5 | The vast financial holdings of the Chiss kept their supply lines running and also provided them access to a number of independent shipyards which they used to keep their vessels on constant patrol. It was through such methods that the Chiss maintained a poacher base at the Etyyy hunting grounds on Kashyyyk.
6 |
--------------------------------------------------------------------------------
/doc/css/elixir.css:
--------------------------------------------------------------------------------
1 | .hljs {
2 | overflow-x: auto;
3 | color: #333;
4 | padding: 0.5em;
5 | border: #ffe0bb dotted 1px;
6 | background: #fffde8;
7 | display: block;
8 | -webkit-text-size-adjust: none;
9 | }
10 |
11 | .hljs-comment,
12 | .diff .hljs-header,
13 | .hljs-javadoc {
14 | color: #998;
15 | font-style: italic;
16 | }
17 |
18 | .hljs-keyword,
19 | .css .rule .hljs-keyword,
20 | .hljs-winutils,
21 | .nginx .hljs-title,
22 | .hljs-subst,
23 | .hljs-request,
24 | .hljs-status {
25 | color: #333;
26 | font-weight: bold;
27 | }
28 |
29 | .hljs-number,
30 | .hljs-hexcolor,
31 | .ruby .hljs-constant {
32 | color: #008080;
33 | }
34 |
35 | .hljs-string,
36 | .hljs-tag .hljs-value,
37 | .hljs-phpdoc,
38 | .hljs-dartdoc,
39 | .tex .hljs-formula {
40 | color: #d14;
41 | }
42 |
43 | .hljs-title,
44 | .hljs-id,
45 | .scss .hljs-preprocessor {
46 | color: #900;
47 | font-weight: bold;
48 | }
49 |
50 | .hljs-list .hljs-keyword,
51 | .hljs-subst {
52 | font-weight: normal;
53 | }
54 |
55 | .hljs-class .hljs-title,
56 | .hljs-type,
57 | .vhdl .hljs-literal,
58 | .tex .hljs-command {
59 | color: #445588;
60 | font-weight: bold;
61 | }
62 |
63 | .hljs-tag,
64 | .hljs-tag .hljs-title,
65 | .hljs-rules .hljs-property,
66 | .django .hljs-tag .hljs-keyword {
67 | color: #000080;
68 | font-weight: normal;
69 | }
70 |
71 | .hljs-attribute,
72 | .hljs-variable,
73 | .lisp .hljs-body {
74 | color: #008080;
75 | }
76 |
77 | .hljs-regexp {
78 | color: #009926;
79 | }
80 |
81 | .hljs-symbol,
82 | .ruby .hljs-symbol .hljs-string,
83 | .lisp .hljs-keyword,
84 | .clojure .hljs-keyword,
85 | .scheme .hljs-keyword,
86 | .tex .hljs-special,
87 | .hljs-prompt {
88 | color: #990073;
89 | }
90 |
91 | .hljs-built_in {
92 | color: #0086b3;
93 | }
94 |
95 | .hljs-preprocessor,
96 | .hljs-pragma,
97 | .hljs-pi,
98 | .hljs-doctype,
99 | .hljs-shebang,
100 | .hljs-cdata {
101 | color: #999;
102 | font-weight: bold;
103 | }
104 |
105 | .hljs-deletion {
106 | background: #fdd;
107 | }
108 |
109 | .hljs-addition {
110 | background: #dfd;
111 | }
112 |
113 | .diff .hljs-change {
114 | background: #0086b3;
115 | }
116 |
117 | .hljs-chunk {
118 | color: #aaa;
119 | }
120 |
--------------------------------------------------------------------------------
/doc/ReleaseManager.Config.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ReleaseManager.Config
5 |
6 |
7 |
8 |
12 |
13 |
14 |
15 |
16 |
20 |
21 |
22 |
23 |
26 |
27 |
28 |
name: The name of your application
47 | version: The version of your application
48 | dev?: Is this release being built in dev mode
49 | env: The mix environment the app should be build for
50 | erl: The binary containing all options to pass to erl
51 | upgrade?: Is this release an upgrade?
52 | verbosity: The verbosity level, one of [silent|quiet|normal|verbose]
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/test/appups_test.exs:
--------------------------------------------------------------------------------
1 | defmodule AppupsTest do
2 | use ExUnit.Case, async: true
3 |
4 | import PathHelpers
5 | import ReleaseManager.Utils, only: [write_term: 2]
6 |
7 | @v1_path fixture_path("beams/v1")
8 | @v2_path fixture_path("beams/v2")
9 | @v1_app_path Path.join(@v1_path, "ebin/test.app")
10 | @v2_app_path Path.join(@v2_path, "ebin/test.app")
11 |
12 | setup do
13 | @v1_app_path |> write_term(v1_app)
14 | @v2_app_path |> write_term(v2_app)
15 |
16 | on_exit fn ->
17 | if @v1_app_path |> File.exists? do
18 | @v1_app_path |> File.rm!
19 | end
20 | if @v2_app_path |> File.exists? do
21 | @v2_app_path |> File.rm!
22 | end
23 | end
24 |
25 | :ok
26 | end
27 |
28 | test "generates valid .appup file" do
29 | {:ok, appup} = ReleaseManager.Appups.make(:test, "0.0.1", "0.0.2", @v1_path, @v2_path)
30 | assert appup == expected_appup
31 | end
32 |
33 | defp v1_app do
34 | {:application,:test,
35 | [{:registered,[]},
36 | {:description,'test'},
37 | {:mod,{:"Elixir.Test",[]}},
38 | {:applications,[:stdlib,:kernel,:elixir]},
39 | {:vsn,'0.0.1'},
40 | {:modules,[:"Elixir.Test",:"Elixir.Test.Server",
41 | :"Elixir.Test.Supervisor"]}]}
42 | end
43 |
44 | defp v2_app do
45 | {:application,:test,
46 | [{:registered,[]},
47 | {:description,'test'},
48 | {:mod,{:"Elixir.Test",[]}},
49 | {:applications,[:exirc]},
50 | {:vsn,'0.0.2'},
51 | {:modules,[:"Elixir.Test",:"Elixir.Test.Server",
52 | :"Elixir.Test.Supervisor"]}]}
53 | end
54 |
55 | defp expected_appup do
56 | {'0.0.2',
57 | [{'0.0.1',
58 | [{:load_module,Test},
59 | {:update,Test.Server,:infinity,
60 | {:advanced,[]},
61 | :brutal_purge,:brutal_purge,[]},
62 | {:update,Test.Supervisor,:supervisor}]}],
63 | [{'0.0.1',
64 | [{:update,Test.Supervisor,:supervisor},
65 | {:update,Test.Server,:infinity,
66 | {:advanced,[]},
67 | :brutal_purge,:brutal_purge,[]},
68 | {:load_module,:"Elixir.Test"}]}]}
69 | end
70 | end
71 |
--------------------------------------------------------------------------------
/docs/source/_themes/sphinx_rtd_theme/sass/_theme_badge.sass:
--------------------------------------------------------------------------------
1 | .rst-versions
2 | position: fixed
3 | bottom: 0
4 | left: 0
5 | width: $nav-desktop-width
6 | color: $section-background-color
7 | background: darken($menu-background-color, 8%)
8 | border-top: solid 10px $menu-background-color
9 | font-family: $base-font-family
10 | z-index: $z-index-tray
11 | a
12 | color: $link_color
13 | text-decoration: none
14 | .rst-badge-small
15 | display: none
16 | .rst-current-version
17 | padding: $base-line-height / 2
18 | background-color: darken($menu-background-color, 5%)
19 | display: block
20 | text-align: right
21 | font-size: 90%
22 | cursor: pointer
23 | color: $green
24 | +clearfix
25 | .fa
26 | color: $section-background-color
27 | .fa-book
28 | float: left
29 | .icon-book
30 | float: left
31 | &.rst-out-of-date
32 | background-color: $red
33 | color: $white
34 | &.rst-active-old-version
35 | background-color: $yellow
36 | color: $black
37 | &.shift-up .rst-other-versions
38 | display: block
39 | .rst-other-versions
40 | font-size: 90%
41 | padding: $base-line-height / 2
42 | color: $text-medium
43 | display: none
44 | hr
45 | display: block
46 | height: 1px
47 | border: 0
48 | margin: 20px 0
49 | padding: 0
50 | border-top: solid 1px lighten($menu-background-color, 5%)
51 | dd
52 | display: inline-block
53 | margin: 0
54 | a
55 | display: inline-block
56 | padding: $base-line-height / 4
57 | color: $section-background-color
58 | &.rst-badge
59 | width: auto
60 | bottom: 20px
61 | right: 20px
62 | left: auto
63 | border: none
64 | max-width: $nav-desktop-width
65 | .icon-book
66 | float: none
67 | .fa-book
68 | float: none
69 | &.shift-up .rst-current-version
70 | text-align: right
71 | .fa-book
72 | float: left
73 | .icon-book
74 | float: left
75 | .rst-current-version
76 | width: auto
77 | height: 30px
78 | line-height: 30px
79 | padding: 0 $base-line-height / 4
80 | display: block
81 | text-align: center
82 |
83 | +media($tablet)
84 | .rst-versions
85 | width: 85%
86 | display: none
87 | &.shift
88 | display: block
89 | img
90 | width: 100%
91 | height: auto
92 |
93 |
94 |
--------------------------------------------------------------------------------
/lib/exrm/plugins/conform.ex:
--------------------------------------------------------------------------------
1 | defmodule ReleaseManager.Plugin.Conform do
2 | @name "conform"
3 | @shortdoc "Generates a .conf for your release"
4 | @moduledoc """
5 | Generates a .conf for your release
6 |
7 | This plugin ensures that your application has a .schema.exs
8 | and .conf file for setting up configuration via the `conform`
9 | library. This .conf file then offers a simplified interface
10 | for sysadmins and other deployment staff for easily configuring
11 | your release in production.
12 | """
13 |
14 | use ReleaseManager.Plugin
15 | alias ReleaseManager.Config
16 | alias ReleaseManager.Utils
17 |
18 | def before_release(%Config{name: app, version: version}) do
19 | empty_schema = Conform.Schema.empty
20 | relx_conf_path = Utils.rel_file_dest_path("relx.config")
21 | schema_dest = Utils.rel_file_dest_path("#{app}.schema.exs")
22 | conf_src = Path.join([File.cwd!, "config", "#{app}.conf"])
23 |
24 | debug "Conform: Loading schema..."
25 | # Get top-level schema...
26 | schema = app |> String.to_atom |> Conform.Schema.read!
27 | # Get schemas from all dependencies
28 | dep_schemas = Conform.Schema.coalesce
29 | # Merge together
30 | merged = Conform.Schema.merge(dep_schemas, schema)
31 | # If the merged schema is non-empty, save the schema to config/{app}.schema.exs
32 | continue? = cond do
33 | merged == empty_schema ->
34 | warn "Conform: No schema found, conform will not be packaged in this release!"
35 | false
36 | true ->
37 | Conform.Schema.write_quoted(merged, schema_dest)
38 | info "Conform: Schema succesfully loaded!"
39 | true
40 | end
41 |
42 | if continue? do
43 | # Define overlays for relx.config
44 | overlays = [{:copy, '#{schema_dest}', 'releases/#{version}/#{app}.schema.exs'}]
45 | overlays = case File.exists?(conf_src) do
46 | true ->
47 | [{:copy, '#{conf_src}', 'releases/#{version}/#{app}.conf'}|overlays]
48 | false ->
49 | overlays
50 | end
51 |
52 | # Generate escript for release
53 | debug "Conform: Generating escript.."
54 | escript_path = Mix.Task.run("conform.release")
55 | overlays = [{:copy, escript_path |> String.to_char_list, 'bin/conform'}|overlays]
56 |
57 | # Add .conf, .schema.exs, and escript to relx.config as overlays
58 | debug "Conform: Adding overlays to relx.config..."
59 | relx_config = relx_conf_path |> Utils.read_terms
60 | updated = Utils.merge(relx_config, [overlay: overlays])
61 |
62 | # Persist relx.config
63 | Utils.write_terms(relx_conf_path, updated)
64 |
65 | info "Conform: Done!"
66 | end
67 | end
68 |
69 | def after_release(_), do: nil
70 | def after_cleanup(_), do: nil
71 |
72 | end
73 |
--------------------------------------------------------------------------------
/lib/mix/tasks/release.plugins.ex:
--------------------------------------------------------------------------------
1 | defmodule Mix.Tasks.Release.Plugins do
2 | @moduledoc """
3 | View information about active release plugins
4 |
5 | ## Examples
6 |
7 | # View all active plugins
8 | mix release.plugins
9 |
10 | # View detailed info about a plugin, if available
11 | mix release.plugins
12 |
13 | """
14 | @shortdoc "View information about active release plugins"
15 |
16 | use Mix.Task
17 | import ReleaseManager.Utils
18 |
19 | def run(args) do
20 | args |> parse_args |> do_run
21 | end
22 |
23 | defp do_run([action: :list]) do
24 | plugins = get_plugins
25 | for plugin <- plugins do
26 | name = get_name(plugin)
27 | shortdoc = get_shortdoc(plugin)
28 | IO.puts String.ljust(name, 30) <> " # " <> shortdoc
29 | end
30 | end
31 | defp do_run([action: :details, plugin: plugin]) do
32 | plugin |> get_plugin |> display_plugin_long
33 | end
34 |
35 | defp get_plugins, do: ReleaseManager.Plugin.load_all
36 |
37 | defp get_plugin(plugin) do
38 | plugin_name = plugin |> String.downcase
39 | result = ReleaseManager.Plugin.load_all |> Enum.find(fn module ->
40 | module_name = module |> Atom.to_string |> String.downcase
41 | given_name = get_name(module) |> String.downcase
42 | cond do
43 | module_name |> String.contains?(plugin_name) -> true
44 | given_name |> String.contains?(plugin_name) -> true
45 | true -> false
46 | end
47 | end)
48 | case result do
49 | nil ->
50 | notice "No plugin by that name could be found!"
51 | abort!
52 | _ ->
53 | result
54 | end
55 | end
56 |
57 | defp display_plugin_long(plugin) do
58 | name = get_name(plugin)
59 | moduledoc = get_moduledoc(plugin)
60 | if IO.ANSI.enabled? do
61 | opts = [width: 80]
62 | IO.ANSI.Docs.print_heading("#{name}", opts)
63 | IO.ANSI.Docs.print(moduledoc, opts)
64 | else
65 | IO.puts "# #{name}\n"
66 | IO.puts moduledoc
67 | end
68 | end
69 |
70 | defp get_name(plugin) do
71 | default = plugin |> Atom.to_string |> String.replace(~r/.*\./, "") |> String.downcase
72 | get_plugin_info(plugin, :name, default)
73 | end
74 | defp get_shortdoc(plugin), do: get_plugin_info(plugin, :shortdoc, "No description available.")
75 | defp get_moduledoc(plugin), do: get_plugin_info(plugin, :moduledoc, "No additional details available.")
76 |
77 | defp get_plugin_info(plugin, type, default) when is_atom(plugin) and is_atom(type) do
78 | case plugin.__info__(:attributes) |> List.keyfind(type, 0) do
79 | {^type, [value]} -> value
80 | nil -> default
81 | end
82 | end
83 |
84 | defp parse_args(args) do
85 | case OptionParser.parse(args) do
86 | {_, [], _} -> [action: :list]
87 | {_, [plugin], _} -> [action: :details, plugin: plugin]
88 | {_, _, _} ->
89 | error "Invalid arguments for `mix release.plugins`!"
90 | abort!
91 | end
92 | end
93 |
94 | end
95 |
--------------------------------------------------------------------------------
/test/utils_test.exs:
--------------------------------------------------------------------------------
1 | defmodule UtilsTest do
2 | use ExUnit.Case, async: true
3 |
4 | import PathHelpers
5 |
6 | alias ReleaseManager.Utils
7 |
8 | @example_app_path fixture_path("example_app")
9 | @old_path fixture_path("configs/old_relx.config")
10 | @new_path fixture_path("configs/new_relx.config")
11 | @expected_path fixture_path("configs/merged_relx.config")
12 |
13 | defmacrop with_app(body) do
14 | quote do
15 | cwd = File.cwd!
16 | File.cd! @example_app_path
17 | unquote(body)
18 | File.cd! cwd
19 | end
20 | end
21 |
22 | test "can merge two relx.config files" do
23 | old = @old_path |> Utils.read_terms
24 | new = @new_path |> Utils.read_terms
25 | expected = @expected_path |> Utils.read_terms
26 |
27 | merged = Utils.merge(old, new)
28 |
29 | assert expected == merged
30 | end
31 |
32 | test "can read terms from string" do
33 | config = @expected_path |> File.read!
34 | expected = @expected_path |> Utils.read_terms
35 | terms = Utils.string_to_terms(config)
36 |
37 | assert expected == terms
38 | end
39 |
40 | test "can run a function in a specific Mix environment" do
41 | execution_env = Utils.with_env :prod, fn -> Mix.env end
42 | assert :prod = execution_env
43 | end
44 |
45 | test "can load the current project configuration for a given environment" do
46 | with_app do
47 | [test: config] = Utils.load_config(:prod)
48 | assert List.keymember?(config, :foo, 0)
49 | end
50 | end
51 |
52 | test "can invoke mix to perform a task for a given environment" do
53 | with_app do
54 | assert :ok = Utils.mix("clean", :prod)
55 | end
56 | end
57 |
58 | test "can get the current elixir library path" do
59 | path = Path.join([Utils.get_elixir_path, "bin", "elixir"])
60 | {result, _} = System.cmd(path, ["--version"])
61 | version = result |> String.strip(?\n)
62 | assert "Elixir #{System.version}" == version
63 | end
64 |
65 | @tag :expensive
66 | @tag timeout: 60000 # 60s
67 | test "can build a release and boot it up" do
68 | with_app do
69 | # Build release
70 | assert :ok = Utils.mix("compile", :dev)
71 | assert :ok = Utils.mix("release", :dev)
72 | assert [{"test", "0.0.1"}] == Utils.get_releases("test")
73 | # Boot it, ping it, and shut it down
74 | bin_path = Path.join([File.cwd!, "rel", "test", "bin", "test"])
75 | assert {_, 0} = System.cmd(bin_path, ["start"])
76 | :timer.sleep(1000) # Required, since starting up takes a sec
77 | assert {"pong\n", 0} = System.cmd(bin_path, ["ping"])
78 | assert {"ok\n", 0} = System.cmd(bin_path, ["stop"])
79 | end
80 | end
81 |
82 | test "can compare semver versions" do
83 | assert ["1.0.10"|_] = Utils.sort_versions(["1.0.1", "1.0.2", "1.0.9", "1.0.10"])
84 | end
85 |
86 | test "can compare non-semver versions" do
87 | assert ["1.3", "1.2", "1.1"] = Utils.sort_versions(["1.1", "1.3", "1.2"])
88 | end
89 |
90 | end
91 |
--------------------------------------------------------------------------------
/docs/source/_themes/sphinx_rtd_theme/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 |
3 | // load all grunt tasks
4 | require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
5 |
6 | grunt.initConfig({
7 | open : {
8 | dev: {
9 | path: 'http://localhost:1919'
10 | }
11 | },
12 |
13 | connect: {
14 | server: {
15 | options: {
16 | port: 1919,
17 | base: '../../../build',
18 | livereload: 1919
19 | }
20 | }
21 | },
22 | copy: {
23 | fonts: {
24 | files: [
25 | // includes files within path
26 | {expand: true, flatten: true, src: ['bower_components/font-awesome/fonts/*'], dest: 'sphinx_rtd_theme/static/fonts/', filter: 'isFile'}
27 | ]
28 | }
29 | },
30 |
31 | sass: {
32 | dev: {
33 | options: {
34 | style: 'expanded',
35 | loadPath: ['bower_components/bourbon/app/assets/stylesheets', 'bower_components/neat/app/assets/stylesheets', 'bower_components/font-awesome/scss', 'bower_components/wyrm/sass']
36 | },
37 | files: [{
38 | expand: true,
39 | cwd: 'sass',
40 | src: ['*.sass'],
41 | dest: 'sphinx_rtd_theme/static/css',
42 | ext: '.css'
43 | }]
44 | },
45 | build: {
46 | options: {
47 | style: 'compressed',
48 | loadPath: ['bower_components/bourbon/app/assets/stylesheets', 'bower_components/neat/app/assets/stylesheets', 'bower_components/font-awesome/scss', 'bower_components/wyrm/sass']
49 | },
50 | files: [{
51 | expand: true,
52 | cwd: 'sass',
53 | src: ['*.sass'],
54 | dest: 'sphinx_rtd_theme/static/css',
55 | ext: '.css'
56 | }]
57 | }
58 | },
59 |
60 | exec: {
61 | bower_update: {
62 | cmd: 'bower update'
63 | },
64 | build_sphinx: {
65 | cmd: 'sphinx-build ../../../source ../../../build'
66 | }
67 | },
68 | clean: {
69 | options: {force: true},
70 | build: ["../../../build"],
71 | fonts: ["sphinx_rtd_theme/static/fonts"]
72 | },
73 |
74 | watch: {
75 | /* Compile sass changes into theme directory */
76 | sass: {
77 | files: ['sass/*.sass', 'bower_components/**/*.sass'],
78 | tasks: ['sass:dev']
79 | },
80 | /* Changes in theme dir rebuild sphinx */
81 | sphinx: {
82 | files: ['sphinx_rtd_theme/**/*', '../../../**/*.rst', '../../../**/*.py'],
83 | tasks: ['clean:build','exec:build_sphinx']
84 | },
85 | /* live-reload the demo_docs if sphinx re-builds */
86 | livereload: {
87 | files: ['../../../build/**/*'],
88 | options: { livereload: 1919 }
89 | }
90 | }
91 |
92 | });
93 |
94 | grunt.loadNpmTasks('grunt-exec');
95 | grunt.loadNpmTasks('grunt-contrib-connect');
96 | grunt.loadNpmTasks('grunt-contrib-watch');
97 | grunt.loadNpmTasks('grunt-contrib-sass');
98 | grunt.loadNpmTasks('grunt-contrib-clean');
99 | grunt.loadNpmTasks('grunt-contrib-copy');
100 | grunt.loadNpmTasks('grunt-open');
101 |
102 | grunt.registerTask('fonts', ['clean:fonts','copy:fonts']);
103 | grunt.registerTask('default', ['exec:bower_update','clean:build','sass:build','exec:build_sphinx']);
104 | grunt.registerTask('watch', ['exec:bower_update','clean:build','sass:dev','exec:build_sphinx','connect','open','watch']);
105 | }
106 |
107 |
--------------------------------------------------------------------------------
/doc/Mix.Tasks.Release.Plugins.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Mix.Tasks.Release.Plugins
5 |
6 |
7 |
8 |
12 |
13 |
14 |
15 |
16 |
20 |
21 |
22 |
23 |
26 |
27 |
28 |
This module provides helper functions for the mix release and
96 | mix release.clean tasks
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
--------------------------------------------------------------------------------
/lib/exrm/plugin.ex:
--------------------------------------------------------------------------------
1 | defmodule ReleaseManager.Plugin do
2 | @moduledoc """
3 | This module provide a simple way to add additional steps to
4 | the release task.
5 |
6 | You can define your own plugins using the sample definition below. Note that
7 | the module namespace must be nested under `ReleaseManager.Plugin.*`.
8 |
9 | defmodule ReleaseManager.Plugin.Hello do
10 | use ReleaseManager.Plugin
11 |
12 | def before_release(%Config{} = config) do
13 | info "This is executed just prior to compiling the release"
14 | end
15 |
16 | def after_release(%Config{} = config) do
17 | info "This is executed just after compiling the release"
18 | end
19 |
20 | def after_cleanup(_args) do
21 | info "This is executed just after running cleanup"
22 | end
23 | end
24 |
25 | A couple things are imported or aliased for you. Those things are:
26 |
27 | - The ReleaseManager.Config struct is aliased for you to just Config
28 | - `debug/1`, `info/1`, `warn/1`, `notice/1`, and `error/1` are imported for you.
29 | These should be used to do any output for the user.
30 |
31 | `before_release/1` and `after_release/1` are required callbacks, and will each be passed a
32 | `Config` struct, containing the configuration for the release task. You can choose
33 | to return the config struct modified or unmodified, or not at all. In the former case,
34 | any modifications you made will be passed on to the remaining plugins and the final
35 | release task. The required callback `after_cleanup/1` is passed the command line arguments.
36 | The return value is not used.
37 |
38 | All plugins are executed just prior, and just after compiling the release, as the name of
39 | the callbacks reflect. The `before_release/1` callback is called after some internal tasks,
40 | such as generating the sys.config and others.
41 | """
42 | use Behaviour
43 |
44 | @doc """
45 | A plugin needs to implement `before_release/1`, and `after_release/1`
46 | both of which receive a %ReleaseManager.Config struct
47 | """
48 | defcallback before_release(ReleaseManager.Config.t) :: any
49 | defcallback after_release(ReleaseManager.Config.t) :: any
50 |
51 | @doc false
52 | defmacro __using__(_opts) do
53 | quote do
54 | @behaviour ReleaseManager.Plugin
55 | alias ReleaseManager.Config
56 | import ReleaseManager.Utils, only: [debug: 1, info: 1, warn: 1, notice: 1, error: 1]
57 |
58 | Module.register_attribute __MODULE__, :name, accumulate: false, persist: true
59 | Module.register_attribute __MODULE__, :moduledoc, accumulate: false, persist: true
60 | Module.register_attribute __MODULE__, :shortdoc, accumulate: false, persist: true
61 | end
62 | end
63 |
64 | @doc """
65 | Loads all plugins in all code paths.
66 | """
67 | @spec load_all() :: [] | [atom]
68 | def load_all, do: load_plugins(:code.get_path)
69 |
70 | @doc """
71 | Loads all plugins in the given `paths`.
72 | """
73 | @spec load_plugins([binary]) :: [] | [atom]
74 | def load_plugins(paths) do
75 | Enum.reduce(paths, [], fn(path, matches) ->
76 | {:ok, files} = :erl_prim_loader.list_dir(path)
77 | Enum.reduce(files, matches, &match_plugins/2)
78 | end)
79 | end
80 |
81 | @re_pattern Regex.re_pattern(~r/Elixir\.ReleaseManager\.Plugin\..*\.beam$/)
82 |
83 | @spec match_plugins(char_list, [atom]) :: [atom]
84 | defp match_plugins(filename, modules) do
85 | if :re.run(filename, @re_pattern, [capture: :none]) == :match do
86 | mod = :filename.rootname(filename, '.beam') |> List.to_atom
87 | if Code.ensure_loaded?(mod), do: [mod | modules], else: modules
88 | else
89 | modules
90 | end
91 | end
92 | end
93 |
--------------------------------------------------------------------------------
/doc/ReleaseManager.Appups.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ReleaseManager.Appups
5 |
6 |
7 |
8 |
12 |
13 |
14 |
15 |
16 |
20 |
21 |
22 |
23 |
26 |
27 |
28 |
Generate a .appup for the given application, start version, and upgrade version.
86 |
## Parameter information
87 | application: the application name as an atom
88 | v1: the start version, such as "0.0.1"
89 | v2: the upgrade version, such as "0.0.2"
90 | v1_path: the path to the v1 artifacts (rel/<app>/lib/<app>-0.0.1)
91 | v2_path: the path to the v2 artifacts (_build/prod/lib/<app>)
# Build a release using defaults
51 | mix release
52 |
53 | # Pass args to erlexec when running the release
54 | mix release --erl="-env TZ UTC"
55 |
56 | # Enable dev mode. Make changes, compile using MIX_ENV=prod
57 | # and execute your release again to pick up the changes
58 | mix release --dev
59 |
60 | # Set the verbosity level
61 | mix release --verbosity=[silent|quiet|normal|verbose]
62 |
You may pass any number of arguments as needed. Make sure you pass arguments
63 | using --key=value, not --key value, as the args may be interpreted incorrectly
64 | otherwise.
# Cleans the release for the current version of the project
51 | mix release.clean
52 |
53 | # Remove all files generated by exrm, including releases
54 | mix release.clean --implode
55 |
56 | # Implode, but do not confirm (DANGEROUS)
57 | mix release.clean --implode --no-confirm
This plugin ensures that your application has a .schema.exs
50 | and .conf file for setting up configuration via the conform
51 | library. This .conf file then offers a simplified interface
52 | for sysadmins and other deployment staff for easily configuring
53 | your release in production.
This module provide a simple way to add additional steps to
53 | the release task.
54 |
You can define your own plugins using the sample definition below. Note that
55 | the module namespace must be nested under ReleaseManager.Plugin.*.
56 |
defmodule ReleaseManager.Plugin.Hello do
57 | use ReleaseManager.Plugin
58 |
59 | def before_release(%Config{} = config) do
60 | info "This is executed just prior to compiling the release"
61 | end
62 |
63 | def after_release(%Config{} = config) do
64 | info "This is executed just after compiling the release"
65 | end
66 |
67 | def after_cleanup(_args) do
68 | info "This is executed just after running cleanup"
69 | end
70 | end
71 |
A couple things are imported or aliased for you. Those things are:
72 |
73 |
The ReleaseManager.Config struct is aliased for you to just Config
74 |
75 |
debug/1, info/1, warn/1, notice/1, and error/1 are imported for you.
76 | These should be used to do any output for the user.
77 |
78 |
79 |
before_release/1 and after_release/1 are required callbacks, and will each be passed a
80 | Config struct, containing the configuration for the release task. You can choose
81 | to return the config struct modified or unmodified, or not at all. In the former case,
82 | any modifications you made will be passed on to the remaining plugins and the final
83 | release task. The required callback after_cleanup/1 is passed the command line arguments.
84 | The return value is not used.
85 |
All plugins are executed just prior, and just after compiling the release, as the name of
86 | the callbacks reflect. The before_release/1 callback is called after some internal tasks,
87 | such as generating the sys.config and others.
A plugin needs to implement before_release/1, and after_release/1
216 | both of which receive a %ReleaseManager.Config struct
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
--------------------------------------------------------------------------------
/docs/source/_themes/sphinx_rtd_theme/sass/_theme_layout.sass:
--------------------------------------------------------------------------------
1 | .wy-affix
2 | position: fixed
3 | top: $gutter
4 |
5 | .wy-menu
6 | a:hover
7 | text-decoration: none
8 |
9 | .wy-menu-horiz
10 | +clearfix
11 | ul, li
12 | display: inline-block
13 | li:hover
14 | background: rgba(255,255,255,.1)
15 | li
16 | &.divide-left
17 | border-left: solid 1px hsl(0, 0%, 25%)
18 | &.divide-right
19 | border-right: solid 1px hsl(0, 0%, 25%)
20 | a
21 | height: $base-font-size * 2
22 | display: inline-block
23 | line-height: $base-font-size * 2
24 | padding: 0 $base-font-size
25 |
26 | .wy-menu-vertical
27 | header
28 | height: $base-font-size * 2
29 | display: inline-block
30 | line-height: $base-font-size * 2
31 | padding: 0 $gutter
32 | display: block
33 | font-weight: bold
34 | text-transform: uppercase
35 | font-size: 80%
36 | color: $menu-logo-color
37 | white-space: nowrap
38 |
39 | ul
40 | margin-bottom: 0
41 | li
42 | &.divide-top
43 | border-top: solid 1px hsl(0, 0%, 25%)
44 | &.divide-bottom
45 | border-bottom: solid 1px hsl(0, 0%, 25%)
46 | &.current
47 | background: darken($section-background-color, 10%)
48 | a
49 | color: $text-medium
50 | border-right: solid 1px darken($section-background-color, 20%)
51 | padding: $gutter / 4 $gutter * 1.5
52 | &:hover
53 | background: darken($section-background-color, 15%)
54 | // On state for the first level
55 | li.on a, li.current > a
56 | color: $text-color
57 | padding: $gutter / 4 $gutter
58 | font-weight: bold
59 | position: relative
60 | background: $section-background-color
61 | border: none
62 | border-bottom: solid 1px darken($section-background-color, 20%)
63 | border-top: solid 1px darken($section-background-color, 20%)
64 | padding-left: $gutter -4px
65 | +font-smooth
66 | &:hover
67 | background: $section-background-color
68 | // This is the on state for pages beyond second level
69 | li.toctree-l2.current > a
70 | background: darken($section-background-color, 20%)
71 | padding: $gutter / 4 $gutter * 1.5
72 | li.current ul
73 | display: block
74 | li ul
75 | margin-bottom: 0
76 | display: none
77 | .local-toc
78 | li ul
79 | display: block
80 | li ul li a
81 | margin-bottom: 0
82 | color: $text-light
83 | font-weight: normal
84 | a
85 | display: inline-block
86 | line-height: 18px
87 | padding: $gutter / 4 $gutter
88 | display: block
89 | position: relative
90 | font-size: 90%
91 | color: $text-light
92 | &:hover
93 | background-color: lighten($menu-background-color, 10%)
94 | cursor: pointer
95 | &:active
96 | background-color: $menu-logo-color
97 | cursor: pointer
98 | color: $white
99 |
100 | .wy-side-nav-search
101 | z-index: $z-index-popover
102 | background-color: $link-color
103 | text-align: center
104 | padding: $gutter / 2
105 | display: block
106 | color: $section-background-color
107 | margin-bottom: $gutter / 2
108 | input[type=text]
109 | width: 100%
110 | border-radius: 50px
111 | padding: 6px 12px
112 | border-color: darken($link-color, 5%)
113 | img
114 | display: block
115 | margin: auto auto $gutter / 2 auto
116 | height: 45px
117 | width: 45px
118 | background-color: $menu-logo-color
119 | padding: 5px
120 | border-radius: 100%
121 | > a, .wy-dropdown > a
122 | color: $section-background-color
123 | font-size: 100%
124 | font-weight: bold
125 | display: inline-block
126 | padding: $base-line-height / 6 $base-line-height / 4
127 | margin-bottom: $gutter / 2
128 | +font-smooth
129 | &:hover
130 | background: rgba(255,255,255,.1)
131 |
132 | .wy-nav .wy-menu-vertical
133 | header
134 | color: $link-color
135 | a
136 | color: $text-light
137 | &:hover
138 | background-color: $link-color
139 | color: $white
140 |
141 | [data-menu-wrap]
142 | +transition(all .2s ease-in)
143 | position: absolute
144 | opacity: 1
145 | width: 100%
146 | opacity: 0
147 | &.move-center
148 | left: 0
149 | right: auto
150 | opacity: 1
151 | &.move-left
152 | right: auto
153 | left: -100%
154 | opacity: 0
155 | &.move-right
156 | right: -100%
157 | left: auto
158 | opacity: 0
159 |
160 |
161 | .wy-body-for-nav
162 | background: left repeat-y $section-background-color
163 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxOERBMTRGRDBFMUUxMUUzODUwMkJCOThDMEVFNURFMCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxOERBMTRGRTBFMUUxMUUzODUwMkJCOThDMEVFNURFMCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjE4REExNEZCMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjE4REExNEZDMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+EwrlwAAAAA5JREFUeNpiMDU0BAgwAAE2AJgB9BnaAAAAAElFTkSuQmCC)
164 | background-size: $nav-desktop-width 1px
165 |
166 | .wy-grid-for-nav
167 | position: absolute
168 | width: 100%
169 | height: 100%
170 |
171 | .wy-nav-side
172 | position: absolute
173 | top: 0
174 | left: 0
175 | width: $nav-desktop-width
176 | overflow: hidden
177 | min-height: 100%
178 | background: $menu-background-color
179 | z-index: $z-index-popover
180 |
181 | .wy-nav-top
182 | display: none
183 | background: $link-color
184 | color: $white
185 | padding: $gutter / 4 $gutter / 2
186 | position: relative
187 | line-height: 50px
188 | text-align: center
189 | font-size: 100%
190 | +clearfix
191 | a
192 | color: $white
193 | font-weight: bold
194 | +font-smooth
195 | img
196 | margin-right: $base-line-height / 2
197 | height: 45px
198 | width: 45px
199 | background-color: $menu-logo-color
200 | padding: 5px
201 | border-radius: 100%
202 | i
203 | font-size: 30px
204 | float: left
205 | cursor: pointer
206 |
207 | .wy-nav-content-wrap
208 | margin-left: $nav-desktop-width
209 | background: $section-background-color
210 | min-height: 100%
211 |
212 | .wy-nav-content
213 | padding: $gutter $gutter * 2
214 | height: 100%
215 | max-width: 800px
216 | margin: auto
217 |
218 | .wy-body-mask
219 | position: fixed
220 | width: 100%
221 | height: 100%
222 | background: rgba(0,0,0,.2)
223 | display: none
224 | z-index: $z-index-modal - 1
225 | &.on
226 | display: block
227 | footer
228 | color: $gray-light
229 | p
230 | margin-bottom: $base-line-height / 2
231 |
232 | .rst-footer-buttons
233 | +clearfix
234 |
235 | #search-results
236 | .search li
237 | margin-bottom: $base-line-height
238 | border-bottom: solid 1px $table_border_color
239 | padding-bottom: $base-line-height
240 | .search li:first-child
241 | border-top: solid 1px $table_border_color
242 | padding-top: $base-line-height
243 | .search li a
244 | font-size: 120%
245 | margin-bottom: $base-line-height / 2
246 | display: inline-block
247 | .context
248 | color: $text-medium
249 | font-size: 90%
250 |
251 |
252 | +media($tablet)
253 | .wy-body-for-nav
254 | background: $section-background-color
255 | .wy-nav-top
256 | display: block
257 | .wy-nav-side
258 | @if $nav-desktop-position == left
259 | left: -$nav-desktop-width
260 | @else
261 | right: -$nav-desktop-width
262 | &.shift
263 | width: 85%
264 | left: 0
265 | .wy-nav-content-wrap
266 | margin-left: 0
267 | .wy-nav-content
268 | padding: $gutter
269 | &.shift
270 | position: fixed
271 | min-width: 100%
272 | left: 85%
273 | top: 0
274 | height: 100%
275 | overflow: hidden
276 |
277 | +media($desktop-wider)
278 | .wy-nav-content-wrap
279 | background: rgba(0,0,0,.05)
280 | .wy-nav-content
281 | margin: 0
282 | background: $section-background-color
283 |
284 | @media print
285 | .rst-versions, footer, .wy-nav-side
286 | display: none
287 | .wy-nav-content-wrap
288 | margin-left: 0
289 |
290 | nav.stickynav
291 | position: fixed
292 | top: 0
293 |
--------------------------------------------------------------------------------
/docs/source/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # exrm documentation build configuration file, created by
4 | # sphinx-quickstart on Wed Jul 30 01:12:51 2014.
5 | #
6 | # This file is execfile()d with the current directory set to its
7 | # containing dir.
8 | #
9 | # Note that not all possible configuration values are present in this
10 | # autogenerated file.
11 | #
12 | # All configuration values have a default; values that are commented out
13 | # serve to show the default.
14 |
15 | import sys
16 | import os
17 |
18 | # Determine whether to use local sphinx theme, or theme on RTD
19 | on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
20 | if not on_rtd: # only import and set the theme if we're building docs locally
21 | import sphinx_rtd_theme
22 | html_theme = 'sphinx_rtd_theme'
23 | html_theme_path = ['_themes/sphinx_rtd_theme']
24 |
25 | # If extensions (or modules to document with autodoc) are in another directory,
26 | # add these directories to sys.path here. If the directory is relative to the
27 | # documentation root, use os.path.abspath to make it absolute, like shown here.
28 | #sys.path.insert(0, os.path.abspath('.'))
29 |
30 | # -- General configuration ------------------------------------------------
31 |
32 | # If your documentation needs a minimal Sphinx version, state it here.
33 | #needs_sphinx = '1.0'
34 |
35 | # Add any Sphinx extension module names here, as strings. They can be
36 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
37 | # ones.
38 | extensions = []
39 |
40 | # Add any paths that contain templates here, relative to this directory.
41 | templates_path = ['_templates']
42 |
43 | # The suffix of source filenames.
44 | source_suffix = '.rst'
45 |
46 | # The encoding of source files.
47 | #source_encoding = 'utf-8-sig'
48 |
49 | # The master toctree document.
50 | master_doc = 'index'
51 |
52 | # General information about the project.
53 | project = u'exrm'
54 | copyright = u'2014, Paul Schoenfelder'
55 |
56 | # The version info for the project you're documenting, acts as replacement for
57 | # |version| and |release|, also used in various other places throughout the
58 | # built documents.
59 | #
60 | # The short X.Y version.
61 | version = '0.12.12'
62 | # The full version, including alpha/beta/rc tags.
63 | release = '0.12.12'
64 |
65 | # The language for content autogenerated by Sphinx. Refer to documentation
66 | # for a list of supported languages.
67 | #language = None
68 |
69 | # There are two options for replacing |today|: either, you set today to some
70 | # non-false value, then it is used:
71 | #today = ''
72 | # Else, today_fmt is used as the format for a strftime call.
73 | #today_fmt = '%B %d, %Y'
74 |
75 | # List of patterns, relative to source directory, that match files and
76 | # directories to ignore when looking for source files.
77 | exclude_patterns = []
78 |
79 | # The reST default role (used for this markup: `text`) to use for all
80 | # documents.
81 | #default_role = None
82 |
83 | # If true, '()' will be appended to :func: etc. cross-reference text.
84 | #add_function_parentheses = True
85 |
86 | # If true, the current module name will be prepended to all description
87 | # unit titles (such as .. function::).
88 | #add_module_names = True
89 |
90 | # If true, sectionauthor and moduleauthor directives will be shown in the
91 | # output. They are ignored by default.
92 | #show_authors = False
93 |
94 | # The name of the Pygments (syntax highlighting) style to use.
95 | pygments_style = 'sphinx'
96 |
97 | # A list of ignored prefixes for module index sorting.
98 | #modindex_common_prefix = []
99 |
100 | # If true, keep warnings as "system message" paragraphs in the built documents.
101 | #keep_warnings = False
102 |
103 |
104 | # -- Options for HTML output ----------------------------------------------
105 |
106 | # The theme to use for HTML and HTML Help pages. See the documentation for
107 | # a list of builtin themes.
108 | #html_theme = ''
109 |
110 | # Theme options are theme-specific and customize the look and feel of a theme
111 | # further. For a list of options available for each theme, see the
112 | # documentation.
113 | #html_theme_options = {}
114 |
115 | # Add any paths that contain custom themes here, relative to this directory.
116 | #html_theme_path = []
117 |
118 | # The name for this set of Sphinx documents. If None, it defaults to
119 | # " v documentation".
120 | #html_title = None
121 |
122 | # A shorter title for the navigation bar. Default is the same as html_title.
123 | #html_short_title = None
124 |
125 | # The name of an image file (relative to this directory) to place at the top
126 | # of the sidebar.
127 | #html_logo = None
128 |
129 | # The name of an image file (within the static path) to use as favicon of the
130 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
131 | # pixels large.
132 | #html_favicon = None
133 |
134 | # Add any paths that contain custom static files (such as style sheets) here,
135 | # relative to this directory. They are copied after the builtin static files,
136 | # so a file named "default.css" will overwrite the builtin "default.css".
137 | html_static_path = ['_static']
138 |
139 | # Add any extra paths that contain custom files (such as robots.txt or
140 | # .htaccess) here, relative to this directory. These files are copied
141 | # directly to the root of the documentation.
142 | #html_extra_path = []
143 |
144 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
145 | # using the given strftime format.
146 | #html_last_updated_fmt = '%b %d, %Y'
147 |
148 | # If true, SmartyPants will be used to convert quotes and dashes to
149 | # typographically correct entities.
150 | #html_use_smartypants = True
151 |
152 | # Custom sidebar templates, maps document names to template names.
153 | #html_sidebars = {}
154 |
155 | # Additional templates that should be rendered to pages, maps page names to
156 | # template names.
157 | #html_additional_pages = {}
158 |
159 | # If false, no module index is generated.
160 | #html_domain_indices = True
161 |
162 | # If false, no index is generated.
163 | #html_use_index = True
164 |
165 | # If true, the index is split into individual pages for each letter.
166 | #html_split_index = False
167 |
168 | # If true, links to the reST sources are added to the pages.
169 | #html_show_sourcelink = True
170 |
171 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
172 | #html_show_sphinx = True
173 |
174 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
175 | #html_show_copyright = True
176 |
177 | # If true, an OpenSearch description file will be output, and all pages will
178 | # contain a tag referring to it. The value of this option must be the
179 | # base URL from which the finished HTML is served.
180 | #html_use_opensearch = ''
181 |
182 | # This is the file name suffix for HTML files (e.g. ".xhtml").
183 | #html_file_suffix = None
184 |
185 | # Output file base name for HTML help builder.
186 | htmlhelp_basename = 'exrmdoc'
187 |
188 |
189 | # -- Options for LaTeX output ---------------------------------------------
190 |
191 | latex_elements = {
192 | # The paper size ('letterpaper' or 'a4paper').
193 | #'papersize': 'letterpaper',
194 |
195 | # The font size ('10pt', '11pt' or '12pt').
196 | #'pointsize': '10pt',
197 |
198 | # Additional stuff for the LaTeX preamble.
199 | #'preamble': '',
200 | }
201 |
202 | # Grouping the document tree into LaTeX files. List of tuples
203 | # (source start file, target name, title,
204 | # author, documentclass [howto, manual, or own class]).
205 | latex_documents = [
206 | ('index', 'exrm.tex', u'exrm Documentation',
207 | u'Paul Schoenfelder', 'manual'),
208 | ]
209 |
210 | # The name of an image file (relative to this directory) to place at the top of
211 | # the title page.
212 | #latex_logo = None
213 |
214 | # For "manual" documents, if this is true, then toplevel headings are parts,
215 | # not chapters.
216 | #latex_use_parts = False
217 |
218 | # If true, show page references after internal links.
219 | #latex_show_pagerefs = False
220 |
221 | # If true, show URL addresses after external links.
222 | #latex_show_urls = False
223 |
224 | # Documents to append as an appendix to all manuals.
225 | #latex_appendices = []
226 |
227 | # If false, no module index is generated.
228 | #latex_domain_indices = True
229 |
230 |
231 | # -- Options for manual page output ---------------------------------------
232 |
233 | # One entry per manual page. List of tuples
234 | # (source start file, name, description, authors, manual section).
235 | man_pages = [
236 | ('index', 'exrm', u'exrm Documentation',
237 | [u'Paul Schoenfelder'], 1)
238 | ]
239 |
240 | # If true, show URL addresses after external links.
241 | #man_show_urls = False
242 |
243 |
244 | # -- Options for Texinfo output -------------------------------------------
245 |
246 | # Grouping the document tree into Texinfo files. List of tuples
247 | # (source start file, target name, title, author,
248 | # dir menu entry, description, category)
249 | texinfo_documents = [
250 | ('index', 'exrm', u'exrm Documentation',
251 | u'Paul Schoenfelder', 'exrm', 'One line description of project.',
252 | 'Miscellaneous'),
253 | ]
254 |
255 | # Documents to append as an appendix to all manuals.
256 | #texinfo_appendices = []
257 |
258 | # If false, no module index is generated.
259 | #texinfo_domain_indices = True
260 |
261 | # How to display URL addresses: 'footnote', 'no', or 'inline'.
262 | #texinfo_show_urls = 'footnote'
263 |
264 | # If true, do not generate a @detailmenu in the "Top" node's menu.
265 | #texinfo_no_detailmenu = False
266 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing To Exrm
2 |
3 | I've thrown together the guidelines around how to contribute exrm so it's smooth
4 | sailing for everyone. Please take some time and read through this before creating
5 | a pull request. Your contributions are hugely important to the success of exrm,
6 | and I appreciate all your help!
7 |
8 | - [Issues Tracker](#issues-tracker)
9 | - [Bug Reports](#bug-reports)
10 | - [Feature Requests](#feature-requests)
11 | - [Contributing](#contributing)
12 | - [Pull Requests](#pull-requests)
13 |
14 | ## Issues Tracker
15 |
16 | I use the issues tracker to do the following things:
17 |
18 | * **requests for consideration (RFC)** - These are things which I, or you perhaps, am
19 | soliciting feedback on, in order to flesh out ideas, potential features, or big
20 | changes. If you have an idea, or a feature you'd like to implement, feel free to
21 | create issues that fit that definition, and I'll give them the RFC label.
22 | * **[bug reports](#bug-reports)** - Anything you encounter with exrm that is broken or
23 | is generally bad behavior, create an issue for it, and I'll label it appropriately.
24 | * **[submitting pull requests](#pull-requests)** - If you found and fixed a bug in exrm,
25 | please submit a PR with your changes! See the link for guidelines on PRs.
26 |
27 | All bug reports are given a difficulty classification between `starter` and `advanced`.
28 | This is so anyone can hop in and start pulling bugs off the stack if they wish to get
29 | involved. If you are new to the project, please start with one of the `starter` or
30 | `intermediate` bugs, as most of the stuff classified as `advanced` require intimate
31 | knowledge of exrm's internals. Regardless of level, if it's something you feel you want
32 | to tackle, leave a comment and let me know, and we can discuss it in more detail.
33 |
34 | ## Bug Reports
35 |
36 | A bug is a _demonstrable problem_ that is caused by the code in the repository.
37 |
38 | Guidelines for bug reports:
39 |
40 | 1. **Use the GitHub issue search** — check if the issue has already been
41 | reported.
42 |
43 | 2. **Check if the issue has been fixed** — try to reproduce it using the
44 | `master` branch in the repository.
45 |
46 | 3. **Isolate and report the problem** — ideally create a reduced test
47 | case. There are two test projects that are good starting points for this,
48 | [exrm-test](https://github.com/bitwalker/exrm-test) and
49 | [exrm-umbrella-test](https://github.com/bitwalker/exrm-umbrella-test)
50 |
51 | Please try to be as detailed as possible in your report. Include information about
52 | your operating system, your Erlang and Elixir versions (i.e. 17.1.2, or 0.14.3).
53 | Provide steps to reproduce the issue as well as the outcome you were expecting. All
54 | these details will help other developers to find and fix the bug.
55 |
56 | Example:
57 |
58 | > Short and descriptive example bug report title
59 | >
60 | > A summary of the issue and the environment in which it occurs. If suitable,
61 | > include the steps required to reproduce the bug.
62 | >
63 | > 1. This is the first step
64 | > 2. This is the second step
65 | > 3. Further steps, etc.
66 | >
67 | > `` - a link to the reduced test case (e.g. a GitHub Gist or project repo)
68 | >
69 | > Any other information you want to share that is relevant to the issue being
70 | > reported. This might include the lines of code that you have identified as
71 | > causing the bug, and potential solutions (and your opinions on their
72 | > merits).
73 |
74 | ## Feature Requests
75 |
76 | Feature requests are absolutely welcome, but before you dive in to implementing
77 | an idea, please open up an issue on the tracker as a request for consideration by
78 | creating the title of your issue prefixed with RFC.
79 |
80 | Example:
81 |
82 | > RFC: Some feature that would be super awesome
83 | >
84 | > A description of the new feature and why it's needed. This should open
85 | > up discussion and provide a starting point for other participants
86 | > to give their thoughts on whether the feature makes sense, what the best
87 | > path to implementation is, etc. If you made code changes to validate your
88 | > idea, link the url so others can look at the work you've done.
89 |
90 | Feature requests will be discussed by users of exrm, and the final vote will be made
91 | by me on whether or not it fits within the goals of the project. If there is
92 | strong merit for a feature to be implemented, you can be assured I will be interested
93 | in making it happen.
94 |
95 | ## Contributing
96 |
97 | Exrm is divided into a few major components within the `lib` folder:
98 |
99 | - `mix/tasks/release.ex` - This defines the primary release generation task for mix
100 | - `mix/tasks/release.clean.ex` - This defines the cleanup task for mix
101 | - `mix/tasks/release.plugins.ex` - This task allows users to see what active exrm plugins are loaded
102 | - `exrm/plugins/conform.ex` - This exrm plugin handles generating a `sys.config` for a release using conform
103 | - `exrm/plugins/consolidation.ex` - This exrm plugin handles performing protocol consolidation for a release
104 | - `exrm/appups.ex` - This module handles generating `.appup` files for release upgrades.
105 | - `exrm/config.ex` - This module contains the configuration struct containing the state and configuration of the release.
106 | - `exrm/plugin.ex` - This module defines the plugin behavior used by exrm plugins
107 | - `exrm/utils.ex` - This module provides core utilities for exrm
108 |
109 | After your changes are done, please remember to run the full test suite with
110 | `mix test`.
111 |
112 | With tests running and passing, and your [documentation](#contributing-documentation) done, your ready to send a PR!
113 |
114 | If you decide you want to build the html docs as well, you'll need the following in order to use the `mix docs` task:
115 |
116 | - python
117 | - node
118 | - bower and grunt: `npm install -g bower grunt`
119 | - sphinx: `pip install Sphinx`
120 |
121 | Then you should be able to run `mix docs` or `mix docs watch` to build and/or watch the html docs during development.
122 |
123 | ## Contributing Documentation
124 |
125 | Please make sure all modules are well documented with a `@moduledoc`, any relevant
126 | `@typedoc`s and all public functions documented with `@doc` and `@spec`. Use examples
127 | where possible (especially in doctest format if it's possible). There may be legacy
128 | code still in there without these, so if you see them, feel free to make a pull request
129 | to add more docs!
130 |
131 | Example:
132 |
133 | ```elixir
134 | @doc """
135 | Return only those elements for which `fun` is true.
136 |
137 | ## Examples
138 |
139 | iex> Enum.filter([1, 2, 3], fn(x) -> rem(x, 2) == 0 end)
140 | [2]
141 |
142 | """
143 | def filter(collection, fun) ...
144 | ```
145 |
146 | ## Pull requests
147 |
148 | Good pull requests - patches, improvements, new features - are a fantastic
149 | help. They should remain focused in scope and avoid containing unrelated
150 | commits.
151 |
152 | **IMPORTANT**: By submitting a patch, you agree that your work will be
153 | licensed under the license used by the project.
154 |
155 | If you have any large pull request in mind (e.g. implementing features,
156 | refactoring code, etc), **please ask first** otherwise you risk spending
157 | a lot of time working on something that the project's developers might
158 | not want to merge into the project.
159 |
160 | Please adhere to the coding conventions in the project (indentation,
161 | accurate comments, etc.) and don't forget to add your own tests and
162 | documentation. When working with git, we recommend the following process
163 | in order to craft an excellent pull request:
164 |
165 | 1. [Fork](http://help.github.com/fork-a-repo/) the project, clone your fork,
166 | and configure the remotes:
167 |
168 | ```bash
169 | # Clone your fork of the repo into the current directory
170 | git clone https://github.com//exrm
171 | # Navigate to the newly cloned directory
172 | cd exrm
173 | # Assign the original repo to a remote called "upstream"
174 | git remote add upstream https://github.com/bitwalker/exrm
175 | ```
176 |
177 | 2. If you cloned a while ago, get the latest changes from upstream:
178 |
179 | ```bash
180 | git checkout master
181 | git pull upstream master
182 | ```
183 |
184 | 3. Create a new topic branch (off of `master`) to contain your feature, change,
185 | or fix.
186 |
187 | **IMPORTANT**: Making changes in `master` is discouraged. You should always
188 | keep your local `master` in sync with upstream `master` and make your
189 | changes in topic branches.
190 |
191 | ```bash
192 | git checkout -b
193 | ```
194 |
195 | 4. Commit your changes in logical chunks. Keep your commit messages organized,
196 | with a short description in the first line and more detailed information on
197 | the following lines. Feel free to use Git's
198 | [interactive rebase](https://help.github.com/articles/interactive-rebase)
199 | feature to tidy up your commits before making them public.
200 |
201 | 5. Make sure all the tests are still passing.
202 |
203 | ```bash
204 | mix test
205 | ```
206 |
207 | 6. Push your topic branch up to your fork:
208 |
209 | ```bash
210 | git push origin
211 | ```
212 |
213 | 7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/)
214 | with a clear title and description.
215 |
216 | 8. If you haven't updated your pull request for a while, you should consider
217 | rebasing on master and resolving any conflicts.
218 |
219 | **IMPORTANT**: _Never ever_ merge upstream `master` into your branches. You
220 | should always `git rebase` on `master` to bring your changes up to date when
221 | necessary.
222 |
223 | ```bash
224 | git checkout master
225 | git pull upstream master
226 | git checkout
227 | git rebase master
228 | ```
229 |
230 | Thank you for your contributions!
231 |
--------------------------------------------------------------------------------
/docs/source/_themes/sphinx_rtd_theme/sass/_theme_rst.sass:
--------------------------------------------------------------------------------
1 | // -------------------------------------------------------------------------------------------------------------------
2 | // CONTRIBUTORS, PLEASE READ THIS!
3 | // -------------------------------------------------------------------------------------------------------------------
4 | // Couple things...
5 | // 1. Lots of this @extends from wyrm_core/_type.sass (http://www.github.com/snide/wyrm/.
6 | // * Try not to replace any @extends code. It's pretty generic stuff meant to work together.
7 | // * That said, know that I'm very unlikely to accept PRs from wyrm just to change style here.
8 | // 2. I plan to remove the !importants in here. Part of it is due to lazyness, part to sphinx's fondness for nesting.
9 | // 3. Try to use variables from wyrm_core/wy_variables.sass. Notable are...
10 | // * $base-line-height // All margins, padding and line-height should use this in .25 increments.
11 | // * $text-color, $text-light, $text-dark...etc
12 | // * $base-font-family, $custom-font-family, $code-font-family
13 | // 4. If you have changes for mobile/tablet, put them at the bottom of the sass file.
14 | // --------------------------------------------------------------------------------------------------------------------
15 |
16 | .rst-content
17 | // Sphinx by default applies HxW style attributes to images. This fixes that oversite.
18 | img
19 | max-width: 100%
20 | height: auto !important
21 |
22 | div.figure
23 | margin-bottom: $base-line-height
24 |
25 | div.figure.align-center
26 | text-align: center
27 |
28 | // Usually it's a good idea to give images some space.
29 | .section > img
30 | margin-bottom: $base-line-height
31 | // Questionable whether this is nice or not. It styles eternal links, but comes with some baggage.
32 | // a.reference.external:after
33 | // font-family: FontAwesome
34 | // content: " \f08e "
35 | // color: $text-light
36 | // vertical-align: super
37 | // font-size: 60%
38 |
39 | // For the most part, its safe to assume that sphinx wants you to use a blockquote as an indent. It gets
40 | // used in many different ways, so don't assume you can apply some fancy style, just leave it be.
41 | blockquote
42 | margin-left: $base-line-height
43 | line-height: $base-line-height
44 | margin-bottom: $base-line-height
45 | .literal-block, pre.literal-block
46 | @extend .codeblock
47 | // These are the various note pullouts that sphinx applies
48 | .note, .attention, .caution, .danger, .error, .hint, .important, .tip, .warning, .seealso, .admonition-todo
49 | @extend .wy-alert
50 | .last
51 | margin-bottom: 0
52 | .admonition-title
53 | @extend .wy-alert-title
54 | @extend .fa
55 | @extend .fa-exclamation-circle
56 | &:before
57 | margin-right: 4px
58 | .note, .seealso
59 | @extend .wy-alert.wy-alert-info
60 | .hint, .tip, .important
61 | @extend .wy-alert.wy-alert-success
62 | .error, .danger
63 | @extend .wy-alert.wy-alert-danger
64 | .warning, .caution, .attention, .admonition-todo
65 | @extend .wy-alert.wy-alert-warning
66 | // Some people put tables in notes. Let's give them very basic support.
67 | .admonition table
68 | border-color: rgba(0,0,0,.1)
69 | td, th
70 | background: transparent !important
71 | border-color: rgba(0,0,0,.1) !important
72 | .section ul, .toctree-wrapper ul
73 | @extend .wy-plain-list-disc
74 | .section ol.loweralpha, .section ol.loweralpha li
75 | list-style: lower-alpha
76 | .section ol.upperalpha, .section ol.upperalpha li
77 | list-style: upper-alpha
78 | .section ol, ol.arabic
79 | @extend .wy-plain-list-decimal
80 | .section ol p, .section ul p
81 | margin-bottom: $base-line-height / 2
82 | .line-block
83 | margin-left: $base-line-height
84 |
85 | // Generics handling of headings and toc stuff.
86 | .topic-title
87 | font-weight: bold
88 | margin-bottom: $base-line-height / 2
89 | .toc-backref
90 | color: $text-color
91 | .align-right
92 | float: right
93 | margin: 0px 0px $base-line-height $base-line-height
94 | .align-left
95 | float: left
96 | margin: 0px $base-line-height $base-line-height 0px
97 | .align-center
98 | margin: auto
99 | display: block
100 |
101 | // This is the #href that shows up on hover. Sphinx's is terrible so I hack it away.
102 | h1, h2, h3, h4, h5, h6, dl dt
103 | .headerlink
104 | display: none
105 | visibility: hidden
106 | font-size: 14px
107 | @extend .fa
108 | &:after
109 | visibility: visible
110 | content: "\f0c1"
111 | font-family: FontAwesome
112 | display: inline-block
113 | &:hover .headerlink
114 | display: inline-block
115 |
116 | // Sidebar content. You'll see at the bottom of this file I change it in mobile.
117 | .sidebar
118 | float: right
119 | width: 40%
120 | display: block
121 | margin: 0 0 $base-line-height $base-line-height
122 | padding: $base-line-height
123 | background: $table-stripe-color
124 | border: solid 1px $table-border-color
125 | // Sidebar content is usually less relevant, so adjust the margins and sizes.
126 | p, ul, dl
127 | font-size: 90%
128 | .last
129 | margin-bottom: 0
130 | .sidebar-title
131 | display: block
132 | font-family: $custom-font-family
133 | font-weight: bold
134 | background: $table-border-color
135 | padding: $base-line-height / 4 $base-line-height / 2
136 | margin: -$base-line-height
137 | margin-bottom: $base-line-height
138 | font-size: 100%
139 | // Sphinx can highlight searched text with ?highlighted=searchterm
140 | .highlighted
141 | background: $yellow
142 | display: inline-block
143 | font-weight: bold
144 | padding: 0 $base-line-height / 4
145 |
146 | // These are the little citation links [1] that show up within paragraphs.
147 | .footnote-reference, .citation-reference
148 | vertical-align: super
149 | font-size: 90%
150 |
151 | // Tables! Sphinx LOVES TABLES. Most of wyrm assumes you're only going to use a table as a table
152 | // so I have to write a bunch of unique stuff for Sphinx to style them up differently like it's 2003.
153 | table.docutils.citation, table.docutils.footnote
154 | background: none
155 | border: none
156 | color: $gray-light
157 | td, tr
158 | border: none
159 | background-color: transparent !important
160 | white-space: normal
161 | td.label
162 | padding-left: 0
163 | padding-right: 0
164 | vertical-align: top
165 | table.docutils
166 | @extend .wy-table
167 | @extend .wy-table-bordered-all
168 | &:not(.field-list)
169 | @extend .wy-table-striped
170 | // This table is what gets spit out for auto-generated API stuff. I style it smaller bits of padding.
171 | table.field-list
172 | @extend .wy-table
173 | border: none
174 | td
175 | border: none
176 | padding-top: 5px
177 | td > strong
178 | display: inline-block
179 | margin-top: 3px
180 | .field-name
181 | padding-right: 10px
182 | text-align: left
183 | white-space: nowrap
184 | .field-body
185 | text-align: left
186 | padding-left: 0
187 |
188 | // These are the "literals" that get spit out when you mark stuff as ``code`` as your write.
189 | tt
190 | @extend code
191 | color: $black
192 | big, em
193 | font-size: 100% !important
194 | line-height: normal
195 |
196 | .xref, a &
197 | font-weight: bold
198 | // If the literal is inside an a tag, let's color it like a link
199 | a tt
200 | color: $link-color
201 | dl
202 | margin-bottom: $base-line-height
203 | dt
204 | font-weight: bold
205 | // Most of the content within these dls are one liners, so I halve the normal margins.
206 | p, table, ul, ol
207 | margin-bottom: $base-line-height / 2 !important
208 | // rST seems to want dds to be treated as the browser would, indented.
209 | dd
210 | margin: 0 0 $base-line-height / 2 $base-line-height
211 | // This is what Sphinx spits out for it's autodocs. Depending upon what language the person is referencing
212 | // these things usually have a class of "method" or "class" or something similar, but really who knows.
213 | // Sphinx doesn't give me a generic class on these, so unfortunately I have to apply it to the root dl.
214 | // This makes me terribly unhappy and makes this code very nesty. Unfortunately I've seen hand-written docs
215 | // that output similar, but not quite the same nesting so this is really the best we can do.
216 | dl:not(.docutils)
217 | margin-bottom: $base-line-height
218 | // This would be the equivilant of a .. class::
219 | dt
220 | display: inline-block
221 | margin: $base-line-height / 4 0
222 | font-size: 90%
223 | line-height: normal
224 | background: lighten($blue, 50%)
225 | color: $blue
226 | border-top: solid 3px lighten($blue, 20%)
227 | padding: $base-line-height / 4
228 | position: relative
229 | &:before
230 | color: lighten($blue, 20%)
231 | .headerlink
232 | color: $text-color
233 | font-size: 100% !important
234 | // And this would be the .. method::
235 | dl dt
236 | margin-bottom: $base-line-height / 4
237 | border: none
238 | border-left: solid 3px hsl(0,0%,80%)
239 | background: hsl(0,0%,94%)
240 | color: $text-medium
241 | .headerlink
242 | color: $text-color
243 | font-size: 100% !important
244 | dt:first-child
245 | margin-top: 0
246 | // Since dts get the callout style, we treat this less as callouts.
247 | tt
248 | font-weight: bold
249 | &.descname, &.descclassname
250 | background-color: transparent
251 | border: none
252 | padding: 0
253 | font-size: 100% !important
254 | &.descname
255 | font-weight: bold
256 | // This is for more advanced parameter control
257 | .optional
258 | display: inline-block
259 | padding: 0 4px
260 | color: $black
261 | font-weight: bold
262 | .property
263 | display: inline-block
264 | padding-right: 8px
265 | // Doc links to sourcecode
266 | .viewcode-link, .viewcode-back
267 | display: inline-block
268 | color: $green
269 | font-size: 80%
270 | padding-left: $base-line-height
271 | .viewcode-back
272 | display: block
273 | float: right
274 | p.rubric
275 | margin-bottom: 12px
276 | font-weight: bold
277 |
278 | // Mobile specific
279 | +media($mobile)
280 | .rst-content
281 | .sidebar
282 | width: 100%
283 |
--------------------------------------------------------------------------------