diff --git a/mandoc.css b/mandoc.css new file mode 100644 index 0000000..6bfce46 --- /dev/null +++ b/mandoc.css @@ -0,0 +1,368 @@ +/* $OpenBSD: mandoc.css,v 1.39 2022/07/06 14:27:55 schwarze Exp $ */ +/* + * Standard style sheet for mandoc(1) -Thtml and man.cgi(8). + * + * Written by Ingo Schwarze . + * I place this file into the public domain. + * Permission to use, copy, modify, and distribute it for any purpose + * with or without fee is hereby granted, without any conditions. + */ + +/* Global defaults. */ + +html { max-width: 65em; + --bg: #FFFFFF; + --fg: #000000; } +body { background: var(--bg); + color: var(--fg); + font-family: Helvetica,Arial,sans-serif; } +h1, h2 { font-size: 110%; } +table { margin-top: 0em; + margin-bottom: 0em; + border-collapse: collapse; } +/* Some browsers set border-color in a browser style for tbody, + * but not for table, resulting in inconsistent border styling. */ +tbody { border-color: inherit; } +tr { border-color: inherit; } +td { vertical-align: top; + padding-left: 0.2em; + padding-right: 0.2em; + border-color: inherit; } +ul, ol, dl { margin-top: 0em; + margin-bottom: 0em; } +li, dt { margin-top: 1em; } +pre { font-family: inherit; } + +.permalink { border-bottom: thin dotted; + color: inherit; + font: inherit; + text-decoration: inherit; } +* { clear: both } + +/* Search form and search results. */ + +fieldset { border: thin solid silver; + border-radius: 1em; + text-align: center; } +input[name=expr] { + width: 25%; } + +table.results { margin-top: 1em; + margin-left: 2em; + font-size: smaller; } + +/* Header and footer lines. */ + +div[role=doc-pageheader] { + display: flex; + border-bottom: 1px dotted #808080; + margin-bottom: 1em; + font-size: smaller; } +.head-ltitle { flex: 1; } +.head-vol { flex: 0 1 auto; + text-align: center; } +.head-rtitle { flex: 1; + text-align: right; } + +div[role=doc-pagefooter] { + display: flex; + justify-content: space-between; + border-top: 1px dotted #808080; + margin-top: 1em; + font-size: smaller; } +.foot-left { flex: 1; } +.foot-date { flex: 0 1 auto; + text-align: center; } +.foot-os { flex: 1; + text-align: right; } + +/* Sections and paragraphs. */ + +main { margin-left: 3.8em; } +.Nd { } +section.Sh { } +h2.Sh { margin-top: 1.2em; + margin-bottom: 0.6em; + margin-left: -3.2em; } +section.Ss { } +h3.Ss { margin-top: 1.2em; + margin-bottom: 0.6em; + margin-left: -1.2em; + font-size: 105%; } +.Pp { margin: 0.6em 0em; } +.Sx { } +.Xr { } + +/* Displays and lists. */ + +.Bd { } +.Bd-indent { margin-left: 3.8em; } + +.Bl-bullet { list-style-type: disc; + padding-left: 1em; } +.Bl-bullet > li { } +.Bl-dash { list-style-type: none; + padding-left: 0em; } +.Bl-dash > li:before { + content: "\2014 "; } +.Bl-item { list-style-type: none; + padding-left: 0em; } +.Bl-item > li { } +.Bl-compact > li { + margin-top: 0em; } + +.Bl-enum { padding-left: 2em; } +.Bl-enum > li { } +.Bl-compact > li { + margin-top: 0em; } + +.Bl-diag { } +.Bl-diag > dt { + font-style: normal; + font-weight: bold; } +.Bl-diag > dd { + margin-left: 0em; } +.Bl-hang { } +.Bl-hang > dt { } +.Bl-hang > dd { + margin-left: 5.5em; } +.Bl-inset { } +.Bl-inset > dt { } +.Bl-inset > dd { + margin-left: 0em; } +.Bl-ohang { } +.Bl-ohang > dt { } +.Bl-ohang > dd { + margin-left: 0em; } +.Bl-tag { margin-top: 0.6em; + margin-left: 5.5em; } +.Bl-tag > dt { + float: left; + margin-top: 0em; + margin-left: -5.5em; + padding-right: 0.5em; + vertical-align: top; } +.Bl-tag > dd { + clear: right; + column-count: 1; /* Force block formatting context. */ + width: 100%; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0.6em; + vertical-align: top; } +.Bl-compact { margin-top: 0em; } +.Bl-compact > dd { + margin-bottom: 0em; } +.Bl-compact > dt { + margin-top: 0em; } + +.Bl-column { } +.Bl-column > tbody > tr { } +.Bl-column > tbody > tr > td { + margin-top: 1em; } +.Bl-compact > tbody > tr > td { + margin-top: 0em; } + +.Rs { font-style: normal; + font-weight: normal; } +.RsA { } +.RsB { font-style: italic; + font-weight: normal; } +.RsC { } +.RsD { } +.RsI { font-style: italic; + font-weight: normal; } +.RsJ { font-style: italic; + font-weight: normal; } +.RsN { } +.RsO { } +.RsP { } +.RsQ { } +.RsR { } +.RsT { text-decoration: underline; } +.RsU { } +.RsV { } + +.eqn { } +.tbl td { vertical-align: middle; } + +.HP { margin-left: 3.8em; + text-indent: -3.8em; } + +/* Semantic markup for command line utilities. */ + +table.Nm { } +code.Nm { font-style: normal; + font-weight: bold; + font-family: inherit; } +.Fl { font-style: normal; + font-weight: bold; + font-family: inherit; } +.Cm { font-style: normal; + font-weight: bold; + font-family: inherit; } +.Ar { font-style: italic; + font-weight: normal; } +.Op { display: inline flow; } +.Ic { font-style: normal; + font-weight: bold; + font-family: inherit; } +.Ev { font-style: normal; + font-weight: normal; + font-family: monospace; } +.Pa { font-style: italic; + font-weight: normal; } + +/* Semantic markup for function libraries. */ + +.Lb { } +code.In { font-style: normal; + font-weight: bold; + font-family: inherit; } +a.In { } +.Fd { font-style: normal; + font-weight: bold; + font-family: inherit; } +.Ft { font-style: italic; + font-weight: normal; } +.Fn { font-style: normal; + font-weight: bold; + font-family: inherit; } +.Fa { font-style: italic; + font-weight: normal; } +.Vt { font-style: italic; + font-weight: normal; } +.Va { font-style: italic; + font-weight: normal; } +.Dv { font-style: normal; + font-weight: normal; + font-family: monospace; } +.Er { font-style: normal; + font-weight: normal; + font-family: monospace; } + +/* Various semantic markup. */ + +.An { } +.Lk { } +.Mt { } +.Cd { font-style: normal; + font-weight: bold; + font-family: inherit; } +.Ad { font-style: italic; + font-weight: normal; } +.Ms { font-style: normal; + font-weight: bold; } +.St { } +.Ux { } + +/* Physical markup. */ + +.Bf { display: inline flow; } +.No { font-style: normal; + font-weight: normal; } +.Em { font-style: italic; + font-weight: normal; } +.Sy { font-style: normal; + font-weight: bold; } +.Li { font-style: normal; + font-weight: normal; + font-family: monospace; } + +/* Tooltip support. */ + +h2.Sh, h3.Ss { position: relative; } +.An, .Ar, .Cd, .Cm, .Dv, .Em, .Er, .Ev, .Fa, .Fd, .Fl, .Fn, .Ft, +.Ic, code.In, .Lb, .Lk, .Ms, .Mt, .Nd, code.Nm, .Pa, .Rs, +.St, .Sx, .Sy, .Va, .Vt, .Xr { + display: inline flow; + position: relative; } + +.An::before { content: "An"; } +.Ar::before { content: "Ar"; } +.Cd::before { content: "Cd"; } +.Cm::before { content: "Cm"; } +.Dv::before { content: "Dv"; } +.Em::before { content: "Em"; } +.Er::before { content: "Er"; } +.Ev::before { content: "Ev"; } +.Fa::before { content: "Fa"; } +.Fd::before { content: "Fd"; } +.Fl::before { content: "Fl"; } +.Fn::before { content: "Fn"; } +.Ft::before { content: "Ft"; } +.Ic::before { content: "Ic"; } +code.In::before { content: "In"; } +.Lb::before { content: "Lb"; } +.Lk::before { content: "Lk"; } +.Ms::before { content: "Ms"; } +.Mt::before { content: "Mt"; } +.Nd::before { content: "Nd"; } +code.Nm::before { content: "Nm"; } +.Pa::before { content: "Pa"; } +.Rs::before { content: "Rs"; } +h2.Sh::before { content: "Sh"; } +h3.Ss::before { content: "Ss"; } +.St::before { content: "St"; } +.Sx::before { content: "Sx"; } +.Sy::before { content: "Sy"; } +.Va::before { content: "Va"; } +.Vt::before { content: "Vt"; } +.Xr::before { content: "Xr"; } + +.An::before, .Ar::before, .Cd::before, .Cm::before, +.Dv::before, .Em::before, .Er::before, .Ev::before, +.Fa::before, .Fd::before, .Fl::before, .Fn::before, .Ft::before, +.Ic::before, code.In::before, .Lb::before, .Lk::before, +.Ms::before, .Mt::before, .Nd::before, code.Nm::before, +.Pa::before, .Rs::before, +h2.Sh::before, h3.Ss::before, .St::before, .Sx::before, .Sy::before, +.Va::before, .Vt::before, .Xr::before { + opacity: 0; + transition: .15s ease opacity; + pointer-events: none; + position: absolute; + bottom: 100%; + box-shadow: 0 0 .35em var(--fg); + padding: .15em .25em; + white-space: nowrap; + font-family: Helvetica,Arial,sans-serif; + font-style: normal; + font-weight: bold; + background: var(--bg); + color: var(--fg); } +.An:hover::before, .Ar:hover::before, .Cd:hover::before, .Cm:hover::before, +.Dv:hover::before, .Em:hover::before, .Er:hover::before, .Ev:hover::before, +.Fa:hover::before, .Fd:hover::before, .Fl:hover::before, .Fn:hover::before, +.Ft:hover::before, .Ic:hover::before, code.In:hover::before, +.Lb:hover::before, .Lk:hover::before, .Ms:hover::before, .Mt:hover::before, +.Nd:hover::before, code.Nm:hover::before, .Pa:hover::before, +.Rs:hover::before, h2.Sh:hover::before, h3.Ss:hover::before, .St:hover::before, +.Sx:hover::before, .Sy:hover::before, .Va:hover::before, .Vt:hover::before, +.Xr:hover::before { + opacity: 1; + pointer-events: inherit; } + +/* Overrides to avoid excessive margins on small devices. */ + +@media (max-width: 37.5em) { +main { margin-left: 0.5em; } +h2.Sh, h3.Ss { margin-left: 0em; } +.Bd-indent { margin-left: 2em; } +.Bl-hang > dd { + margin-left: 2em; } +.Bl-tag { margin-left: 2em; } +.Bl-tag > dt { + margin-left: -2em; } +.HP { margin-left: 2em; + text-indent: -2em; } +} + +/* Overrides for a dark color scheme for accessibility. */ + +@media (prefers-color-scheme: dark) { +html { --bg: #1E1F21; + --fg: #EEEFF1; } +:link { color: #BAD7FF; } +:visited { color: #F6BAFF; } +} diff --git a/snare.1.html b/snare.1.html new file mode 100644 index 0000000..480dc1e --- /dev/null +++ b/snare.1.html @@ -0,0 +1,93 @@ + + + + + + + SNARE(1) + + + + + + + + +
SNARE(1)General Commands ManualSNARE(1)
+
+
+

+

snareGitHub + webhooks runner

+
+
+

+ + + + + +
snare[-c config-file] + [-d]
+
+
+

+

snare is a GitHub webhooks daemon. When + snare receives a webhook event from a given + repository, it authenticates the request, and then executes a user-defined + “per-repo program” with information about the webhook event. + The “per-repo program” is run in a freshly created temporary + directory which is removed once it has completed.

+

The options are as follows:

+
+
+ config-file
+
is a path to a snare.conf configuration file. If + not specified, snare assumes the configuration + file is located at /etc/snare/snare.conf/.
+
+
tells snare not to daemonise: in other words, + `snare` stays in the foreground and logs errors to stderr. This can be + useful for debugging.
+
+
+
+

+

snare runs an HTTP server which GitHub can + send webhook requests to. Configuring a webhook for a given GitHub + repository is relatively simple: go to that repository, then + “Settings > Webhooks > Add webhook”. For + “payload”, specify + “http://yourmachine.com:port/”, specify a + “secret” (which you will then reuse as the + + in snare.conf(5)) and then choose which events you wish + GitHub to deliver.

+
+
+

+

snare runs an HTTP server. If you wish, as + is recommended, to send your webhooks over an encrypted connection, you will + need to run a proxy in front of snare.

+
+
+

+

When run as a daemon, snare logs to + syslogd(8) under the “daemon” facility.

+
+
+

+

snare.conf(5)

+

https://tratt.net/laurie/src/snare

+
+
+ + + + + +
2020-02-10Debian
+ + diff --git a/snare.conf.5.html b/snare.conf.5.html new file mode 100644 index 0000000..a03fec2 --- /dev/null +++ b/snare.conf.5.html @@ -0,0 +1,318 @@ + + + + + + + SNARE.CONF(5) + + + + + + + + +
SNARE.CONF(5)File Formats ManualSNARE.CONF(5)
+
+
+

+

snare.confsnare + configuration file

+
+
+

+

snare.conf is the configuration file for + snare(1). It consists of one or more top-level options and + one GitHub block.

+

The top-level options are:

+
+
"address";
+
is a mandatory address and port number to listen on. The format of + address is either: +
+
x.x.x.x:port
+
an IPv4 address and port. For example, + ‘0.0.0.0:8765’ will listen on + port 8765 on for all IPv4 addresses.
+
[x:x:x]:port
+
an IPv6 address and port. For example, + ‘[::]:8765’ will listen on port + 8765 for all IPv4 and IPv6 addresses.
+
+
+
+ ;
+
is an optional non-zero positive integer specifying the maximum number of + jobs to run in parallel. Defaults to the number of CPUs in the + machine.
+
+ "user-name";
+
is an optional username that snare.conf will try + and change into after it has bound to a network port. Note that + snare.conf will refuse to run as root unless + user is specified. As part of changing user, + snare.conf: +
    +
  • changes its uid, euid, suid to the UID of + user-name.
  • +
  • changes its gid, egid, sgid to the primary GID of + user-name.
  • +
  • sets the $HOME environment variable to the home directory of + user-name.
  • +
  • sets the $USER environment variable to + user-name.
  • +
+

All other environment variables are passed through to commands + unchanged.

+
+
+
specifies GitHub specific options.
+
+

A ‘github’ block supports the following options:

+
+
+ "regex" { match-options }
+
where regex is a regular expression in + Rust regex format that + must match against a "owner/repo" full repository name. If it + matches, then match-options are applied. + "regex" must match against the full repository name: in other + words, it is equivalent to + . + Thus the regex "a/b" does not match against the full repository + name "a/bc", but the regex "a/b.*" does match against + "a/bc".
+
+

A ‘match’ block supports the following options:

+
+
+ "shell-cmd";
+
optionally specifies a command to be run. shell-cmd will + be executed via ‘$SHELL -c’. The + following escape sequences are recognised and replaced before execution: +
+
+
the GitHub event type (e.g. + ‘pull_request’).
+
+
the path to the GitHub JSON.
+
+
the repository owner.
+
+
the repository.
+
+
a literal ‘%’.
+
+ Note that ‘%’ may not be followed by + any character other than those above. +

The escape sequences are guaranteed to satisfy the regular + expression "[a-zA-Z0-9._-]+" and not to be the strings + "." or "..". This means that they are safe to pass + as shell arguments and/or to be included in file system paths.

+
+
"shell-cmd";
+
optionally specifies a command to be run when a job exits unsuccessfully. + shell-cmd will be executed via + ‘$SHELL -c’. The following escape + sequences are recognised and replaced before execution: +
+
+
the GitHub event type (e.g. + ‘pull_request’).
+
+
the path to the GitHub JSON.
+
+
the repository owner.
+
+
the repository.
+
+
the path to the file containing the job's combined stderr / + stdout.
+
+
a literal ‘%’.
+
+ Note that ‘%’ may not be followed by + any character other than those above. +

The escape sequences are guaranteed to satisfy the regular + expression "[a-zA-Z0-9._-]+" and not to be the strings + "." or "..". This means that they are safe to pass + as shell arguments and/or to be included in file system paths.

+
+
(evict | parallel | sequential);
+
specifies what to do when multiple requests for the same repository are + queued at once: +
+
+
only run one job for this repository at a time. Additional jobs will + stay on the queue: if a new job comes in for that repository, it + evicts any previously queued jobs for that repository. In other words, + for this repository there can be at most one running job and one + queued job at any point.
+
+
run as many jobs for this repository in parallel as possible.
+
+
only run one job for this repository at a time. Additional jobs will + stay on the queue and be executed in FIFO order.
+
+

The default match block sets this to + sequential, which is always safe, though at the + possible expense of lower job throughput for any given repository.

+
+
"secret";
+
is the optional GitHub secret used to sign the webhook request. This + allows snare.conf to tell the difference between + genuine webhook requests and those from malfeasants. Although this is + optional, we + + recommend setting it in all cases. Note also that if a GitHub request is + signed, but you have not specified a secret, then snare will return the + request as “unauthorised” to remind you to use the secret at + both ends.
+
+ ;
+
specifies the elapsed time, as a positive integer, in seconds that a + process can run before being sent SIGTERM. The default + match block sets this to one hour (3600 seconds).
+
+

match blocks are evaluated in order from top to + bottom with each successful match overriding previous settings. A default + match block is inserted before any user + match blocks:

+
+
match ".*" {
+  queue = sequential;
+  timeout = 3600;
+}
+
+
+
+

+

The minimal recommended snare.conf file is + as follows:

+
+
listen = "<address>:<port>";
+github {
+  match ".*" {
+    cmd = "/path/to/prps/%o/%r %e %j";
+    errorcmd = "cat %s | mailx -s \"snare error: github.com/%o/%r\" someone@example.com";
+    secret = "<secret>";
+  }
+}
+
+

where "/path/to/prps" is a path to a directory where + per-repo programs are stored. Each repository then has a unique program + "%o/%r" which will be executed with two arguments: the GitHub + event; and the path to the GitHub JSON. If a job exits unsuccessfully then + an email will be sent to someone@example.com containing the job's comined + stderr and stdout output (assuming that a suitable sendmail clone has been + installed and activated).

+

The top-to-bottom evaluation of match blocks allow users to + specify defaults which are only overridden for specific repositories. For + example, for the following configuration file:

+
+
listen = "<address>:<port>";
+github {
+  match ".*" {
+    cmd = "/path/to/prps/%o/%r %e %j";
+    errorcmd = "cat %s | mailx -s \"snare error: github.com/%o/%r\" abc@def.com";
+    secret = "sec";
+  }
+  match "a/b" {
+    errorcmd = "lpr %s";
+  }
+}
+
+

the following repositories will have these settings:

+
+
a/b:
+  queue = sequential
+  timeout = 3600
+  cmd = "/path/to/prps/%o/%r %e %j";
+  errorcmd = "lpr %s";
+  secret = "sec"
+c/d:
+  queue = sequential
+  timeout = 3600
+  cmd = "/path/to/prps/%o/%r %e %j";
+  errorcmd = "cat %s | mailx -s \"snare error: github.com/%o/%r\" abc@def.com";
+  secret = "sec"
+
+

The following program expects to be called with an event and a + JSON path (i.e. "%e %j") and uses shell script to send a list of + commits and diffs to the address specified in $EMAIL on each + “push” to master. It works for any public GitHub + repository:

+
+
#! /bin/sh
+
+set -euf
+
+# A list of email addresses separated by spaces.
+EMAILS="someone@example.com someone.else@example.com"
+# A GitHub URL either https or git.
+REPO_URL="git@github.com:owner/repo.git"
+
+if [ "$1" != "push" ]; then
+    exit 0
+fi
+
+ref=`jq .ref "$2" | tr -d '
+if [ "$ref" != "refs/heads/master" ]; then
+    exit 0
+fi
+
+repo_fullname=`jq .repository.full_name "$2" | tr -d '
+repo_url=`jq .repository.html_url "$2" | tr -d '
+before_hash=`jq .before "$2" | tr -d '
+after_hash=`jq .after "$2" | tr -d '
+echo "$before_hash" | grep -E "^[a-fA-F0-9]+$" 2>&1 > /dev/null
+echo "$after_hash" | grep -E "^[a-fA-F0-9]+$" 2>&1 > /dev/null
+
+git clone "$REPO_URL" repo
+cd repo
+for email in `echo "$EMAILS"`; do
+    git log --reverse -p "$before_hash..$after_hash" \
+      | mail -s "Push to $repo_fullname" "$email"
+done
+
+

where jq + is a command-line JSON processor. Depending on your needs, you can make this + type of script arbitrarily more complex and powerful (for example, not + cloning afresh on each pull).

+

Note that this program is deliberately untrusting of external + input: it is careful to quote all arguments obtained from JSON; and it uses + a fixed directory name (“repo”) rather than a file name from + JSON that might include characters (such as “../..”) that + would cause the script to leak data about other parts of the file + system.

+
+
+

+

snare(1)

+

GitHub's + webhooks documentation.

+
+
+

+

snare(1) was written by + Laurence Tratt + https://tratt.net/laurie/

+
+
+ + + + + +
2020-02-10Debian
+ +