4
0
jamesread 2 долоо хоног өмнө
parent
commit
a3413c0bc3

+ 1 - 0
docs/modules/ROOT/nav.adoc

@@ -79,6 +79,7 @@
 ** xref:args/input_textarea.adoc[Input: Textarea]
 ** xref:args/suggestions.adoc[Suggestions]
 ** xref:args/env.adoc[Environment Variables]
+** xref:args/templates.adoc[Templates]
 * xref:dashboards/intro.adoc[Dashboards]
 ** xref:dashboards/examples.adoc[Examples]
 ** xref:dashboards/actions.adoc[Actions (Linked)]

+ 1 - 1
docs/modules/ROOT/pages/advanced_configuration/config_envs.adoc

@@ -49,6 +49,6 @@ actions:
     shellAfterCompleted: "apprise -t 'Backup on {{ .Env.HOSTNAME }}' -b '{{ output }}'"
 ----
 
-`.Env` uses the same Go template context as other action variables (e.g. `.Arguments`, `.CurrentEntity`, `.OliveTin`). The map is built from the process environment when OliveTin starts; values are read at template execution time. If a variable is missing, the template engine will report a missing-key error (with `missingkey=error`), so use defaulting when a variable might be unset, e.g. `{{ or .Env.OPTIONAL_VAR "default" }}`.
+`.Env` uses the same Go template context as other action variables (e.g. `.Arguments`, `.CurrentEntity`, `.OliveTin`). The map is built from the process environment when OliveTin starts; values are read at template execution time. If a variable is missing, the template engine will report a missing-key error (with `missingkey=error`), so use defaulting when a variable might be unset, e.g. `{{ or .Env.OPTIONAL_VAR "default" }}`. For template functions such as JSON encoding, see xref:args/templates.adoc#json-encoding[JSON encoding with Json].
 
 This feature addresses the need to use environment variables in templates without changing the config loader (see link:https://github.com/OliveTin/OliveTin/issues/840[GitHub issue #840]).

+ 2 - 2
docs/modules/ROOT/pages/args/env.adoc

@@ -85,11 +85,11 @@ fi
 
 To use the *process* environment (the environment OliveTin was started with) inside action template fields such as `shell` or `shellAfterCompleted`, use the `.Env` template variable: `{{ .Env.VAR_NAME }}`. This substitutes the value at execution time. See xref:advanced_configuration/config_envs.adoc#using-env-in-template-replacements[Using .Env in template replacements] for details and examples.
 
+For other template features, including JSON encoding of argument and entity values, see xref:args/templates.adoc[Templates in actions].
+
 == Notes
 
 . Argument names are converted to uppercase for environment variables, `name: filename` becomes `FILENAME`.
 . OliveTin sets `OLIVETIN=1` in the process environment for every action; see <<olivetin-env-var,The OLIVETIN environment variable>> above.
 . The execution request variables are exposed as `OT_USERNAME` and `OT_EXECUTIONTRACKINGID` in the process environment; see <<execution-request-variables,Execution Request Variables>> above.
 . The environment variables are passed into the execution context which uses a shell (/bin/sh on Linux), so it is also possible to use them with the $ notation in the `shell` line, like this; `shell: echo $FILENAME` for example.
-
-

+ 2 - 2
docs/modules/ROOT/pages/args/intro.adoc

@@ -3,7 +3,7 @@
 
 Actions and commands that OliveTin runs, without arguments, are generally quite safe - only that command can be run, without modifications. However, many users need the flexibility to set options on that command - normally called command line arguments. In OliveTin, arguments are defined in a shell commands like `echo {{ message }}`, with a bit of extra configuration.
 
-Examples of valid argument names are `{{ personName }}`, `{{ customer_number }}` and `{{ ISBN11_code }}`. 
+Examples of valid argument names are `{{ personName }}`, `{{ customer_number }}` and `{{ ISBN11_code }}`.
 
 * a-z (case insensitive)
 * _ is allowed
@@ -19,5 +19,5 @@ Now that you understand how arguments work, explore the different argument types
 * xref:args/suggestions.adoc[Argument suggestions] - Add dynamic suggestions to help users
 * xref:args/regex.adoc[Input validation with regex] - Validate user input with regular expressions
 * xref:args/env.adoc[Environment variables] - Use arguments to set environment variables
+* xref:args/templates.adoc[Templates] - Use Go templates in actions, including JSON encoding
 * xref:action_examples/intro.adoc[See examples] - View real-world examples using arguments
-

+ 70 - 0
docs/modules/ROOT/pages/args/templates.adoc

@@ -0,0 +1,70 @@
+[#templates]
+= Templates in actions
+
+OliveTin uses https://pkg.go.dev/text/template[Go text/template] syntax in action fields such as `shell`, `shellAfterCompleted`, entity directory titles, and `enabledExpression`. Template placeholders are written as `{{ ... }}`.
+
+In OliveTin 3k, use dotted names for template context variables:
+
+* `{{ .Arguments.NAME }}` — argument values (see xref:args/env.adoc[Environment variables])
+* `{{ .CurrentEntity.property }}` — entity properties (see xref:entities/intro.adoc[Entities])
+* `{{ .Env.VAR_NAME }}` — process environment (see xref:advanced_configuration/config_envs.adoc#using-env-in-template-replacements[Using .Env in template replacements])
+* `{{ .OliveTin.Build.Version }}` and related build/runtime fields
+
+In OliveTin 2k, argument and execution-request placeholders used the shorter form (for example, `{{ message }}` instead of `{{ .Arguments.message }}`).
+
+[#json-encoding]
+== JSON encoding with `Json`
+
+The `Json` template function encodes a value as a JSON string. Pipe a template value to it when you need structured data in a command — for example, passing argument or entity state to a script or HTTP client that expects JSON.
+
+[source,yaml]
+----
+actions:
+  - title: curl my knx thing
+    shell: curl --json https://knx.example.com/v1/group/global_on/write -d '{{ .Arguments | Json }}'
+    entity: light
+    arguments:
+      - name: value
+        default: "true"
+----
+
+After template substitution, `{{ .Arguments | Json }}` becomes a JSON object containing all argument names and values for that execution (including execution-request variables such as `ot_username` and `ot_executionTrackingId`).
+
+=== Examples
+
+Encode a single argument value:
+
+[source,yaml]
+----
+shell: echo {{ .Arguments.value | Json }}
+----
+
+If `value` is `hello`, the substituted command is `echo "hello"`.
+
+Encode an entity field:
+
+[source,yaml]
+----
+shell: curl -d {{ .CurrentEntity.foo.bar | Json }}
+----
+
+If `foo.bar` is the string `baz`, the substituted command is `curl -d "baz"`.
+
+Encode a nested entity object:
+
+[source,yaml]
+----
+shell: curl --json -d {{ .CurrentEntity.payload | Json }}
+----
+
+If `payload` is `{on: true}`, the substituted command is `curl --json -d {"on":true}`.
+
+=== Notes
+
+. `Json` uses Go's `encoding/json` package. Strings, numbers, booleans, objects, and arrays are encoded according to normal JSON rules.
+. Argument values in templates are strings (`map[string]string`). A checkbox or boolean argument therefore appears in JSON as a string (for example, `"true"`), not a JSON boolean.
+. If the piped value is missing or nil, `Json` produces `null`.
+. When embedding JSON in a shell command, quote the substitution if the JSON may contain spaces or shell metacharacters. Prefer single-quoted YAML strings around the template when possible, as shown in the curl example above.
+. For HTTP request bodies, pass one JSON-encoded value (or build the JSON structure you need in one template expression). Piping several values with spaces between them does not produce a single valid JSON document.
+
+See link:https://github.com/OliveTin/OliveTin/issues/829[GitHub issue #829] for the original feature request.

+ 78 - 0
docs/modules/dev/pages/signing.adoc

@@ -0,0 +1,78 @@
+# macOS release signing
+
+Release builds can sign and notarize the `darwin` binaries using [quill](https://github.com/anchore/quill) via GoReleaser. This runs on the existing Linux CI runner; no macOS runner is required.
+
+Signing is **optional**. If the GitHub secrets below are not all set, GoReleaser skips macOS signing and publishes unsigned binaries (the previous behaviour).
+
+## Prerequisites
+
+- An active [Apple Developer Program](https://developer.apple.com/programs/) membership.
+- A **Developer ID Application** certificate (not "Apple Development" or "Mac App Distribution").
+- An [App Store Connect API key](https://appstoreconnect.apple.com/access/integrations/api) with at least **Developer** access.
+
+## One-time setup
+
+### 1. Create the signing certificate
+
+1. Open [Certificates, Identifiers & Profiles](https://developer.apple.com/account/resources/certificates/list).
+2. Create a certificate of type **Developer ID Application**.
+3. Download the `.cer` file and double-click it to add it to **Keychain Access** on a Mac.
+4. In Keychain Access, export the certificate as a **Personal Information Exchange (`.p12`)** file. You will set an export password — remember it; this becomes `MACOS_SIGN_PASSWORD`.
+
+### 2. Create the notarization API key
+
+1. Open [App Store Connect → Users and Access → Integrations → App Store Connect API](https://appstoreconnect.apple.com/access/integrations/api).
+2. Create a key with **Developer** role (or Admin).
+3. Download the `.p8` file once (it cannot be downloaded again). Note the **Key ID** shown in the portal and the **Issuer ID** at the top of the API keys page.
+
+### 3. Base64-encode the key files
+
+Run on a machine that has the files (Linux or macOS):
+
+```sh
+base64 -w0 < ./Certificates.p12    # MACOS_SIGN_P12
+base64 -w0 < ./AuthKey_XXXXXX.p8   # MACOS_NOTARY_KEY
+```
+
+On macOS without GNU coreutils, use `base64 -i file | tr -d '\n'`.
+
+### 4. Add GitHub repository secrets
+
+In **Settings → Secrets and variables → Actions**, create:
+
+| Secret | Value |
+|--------|-------|
+| `MACOS_SIGN_P12` | Base64 contents of the `.p12` file |
+| `MACOS_SIGN_PASSWORD` | Password used when exporting the `.p12` |
+| `MACOS_NOTARY_KEY` | Base64 contents of the `.p8` file |
+| `MACOS_NOTARY_KEY_ID` | Key ID from App Store Connect (e.g. `ABC123DEF4`) |
+| `MACOS_NOTARY_ISSUER_ID` | Issuer UUID from App Store Connect |
+
+All five must be present for signing to run. Any missing secret disables signing for that release.
+
+## Renewal
+
+| Item | Typical lifetime | What to do |
+|------|------------------|------------|
+| Developer ID Application certificate | ~5 years | Create a new certificate in the Apple portal, export a new `.p12`, update `MACOS_SIGN_P12` and `MACOS_SIGN_PASSWORD`. |
+| App Store Connect API key | Does not expire, but can be revoked | Create a new key if compromised or lost; update `MACOS_NOTARY_KEY`, `MACOS_NOTARY_KEY_ID`, and optionally `MACOS_NOTARY_ISSUER_ID`. |
+| Apple Developer Program | Annual subscription | Renew membership before it lapses; existing certificates stop working if the account is inactive. |
+
+After updating secrets, the next release on `main` (via semantic-release) will use the new credentials automatically.
+
+## Verifying a signed release
+
+On a Mac, download a `OliveTin-darwin-*.tar.gz` release artifact and run:
+
+```sh
+tar -xzf OliveTin-darwin-arm64.tar.gz
+spctl -a -vv -t execute OliveTin-darwin-arm64/OliveTin
+```
+
+A signed and notarized binary should report `accepted` with `source=Notarized Developer ID`.
+
+## Configuration reference
+
+- GoReleaser: `notarize.macos` in [`.goreleaser.yml`](.goreleaser.yml)
+- CI secrets: [`.github/workflows/build-and-release.yml`](.github/workflows/build-and-release.yml) (`release` step)
+- [GoReleaser notarization docs](https://goreleaser.com/customization/notarize/)