commit 6a2ea30caea691a6e895088682c399f13c30d5e2 Author: Ondrej Belusky Date: Wed Oct 28 09:10:53 2026 +0100 Deploy a stack with dnode from any repo, so no repo copies the dnode setup diff --git a/README.md b/README.md new file mode 100644 index 0000000..3a24def --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# dnode-deploy + +Deploys a stack with [dnode](https://lab.zlymeda.dynu.net/go/dnode) from a Gitea workflow, pulling the newest images. The runner needs `dnode` on its path (`go-executor` has it). + +The `go` org already holds `DNODE_CONFIG`, `DNODE_KNOWN_HOSTS` (variables) and `DNODE_SSH_KEY` (secret), so a repo there needs nothing set up. + +```yaml + deploy-master: + needs: build-master + if: github.ref == 'refs/heads/master' + runs-on: go-executor + steps: + - uses: https://lab.zlymeda.dynu.net/actions/dnode-deploy@master + with: + stack: goodwe + nodes: hp1 hp2 # or 'all' (default), which can roll out with health checks + deploy_tag: master + dnode_config: ${{ vars.DNODE_CONFIG }} + dnode_ssh_key: ${{ secrets.DNODE_SSH_KEY }} + dnode_known_hosts: ${{ vars.DNODE_KNOWN_HOSTS }} + ntfy_topic: ${{ vars.NTFY_RELEASE_TOPIC || 'gitea-releases' }} + ntfy_token: ${{ secrets.NTFY_TOKEN }} + ntfy_failure_topic: ${{ vars.NTFY_FAILURE_TOPIC }} +``` + +`nodes: all` deploys to every configured node, so use it only for a stack that runs everywhere; name the nodes otherwise, as a node without the stack fails the deploy. diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..a12dfd8 --- /dev/null +++ b/action.yml @@ -0,0 +1,97 @@ +name: dnode deploy +description: Deploy a compose stack or systemd unit with dnode, pulling the newest images, and notify via ntfy. + +inputs: + stack: + description: Stack or unit to deploy (e.g. goodwe, nats) + required: true + nodes: + description: > + 'all' for every configured node, or the node names separated by spaces, + deployed one at a time in that order (e.g. 'hp1 hp2') + default: all + rollout: + description: With nodes 'all', deploy one node at a time and wait for health in between + default: 'true' + pull: + description: Pull the newest images before starting + default: 'true' + dnode_config: + description: dnode nodes.yaml (vars.DNODE_CONFIG) + required: true + dnode_ssh_key: + description: SSH private key for the nodes (secrets.DNODE_SSH_KEY) + required: true + dnode_known_hosts: + description: known_hosts for the nodes (vars.DNODE_KNOWN_HOSTS) + required: true + deploy_tag: + description: What was deployed, for the notification (e.g. master) + default: '' + ntfy_topic: + description: ntfy topic for the success notification; none when empty + default: '' + ntfy_token: + description: ntfy token + default: '' + ntfy_failure_topic: + description: ntfy topic for the failure notification (defaults to ntfy_topic) + default: '' + +runs: + using: composite + steps: + - name: Configure dnode + shell: bash + env: + DNODE_CONFIG_CONTENT: ${{ inputs.dnode_config }} + DNODE_SSH_KEY_CONTENT: ${{ inputs.dnode_ssh_key }} + DNODE_KNOWN_HOSTS_CONTENT: ${{ inputs.dnode_known_hosts }} + run: | + mkdir -p ~/.config/dnode ~/.ssh + printf '%s\n' "$DNODE_CONFIG_CONTENT" > ~/.config/dnode/nodes.yaml + printf '%s\n' "$DNODE_SSH_KEY_CONTENT" > ~/.ssh/dnode_deploy_key + printf '%s\n' "$DNODE_KNOWN_HOSTS_CONTENT" > ~/.ssh/known_hosts + chmod 600 ~/.config/dnode/nodes.yaml ~/.ssh/dnode_deploy_key ~/.ssh/known_hosts + + - name: Deploy + shell: bash + env: + STACK: ${{ inputs.stack }} + NODES: ${{ inputs.nodes }} + ROLLOUT: ${{ inputs.rollout }} + PULL: ${{ inputs.pull }} + run: | + set -euo pipefail + export DNODE_SSH_KEY="$HOME/.ssh/dnode_deploy_key" + flags=() + [ "$PULL" = "true" ] && flags+=(--pull) + dnode nodes + if [ "$NODES" = "all" ]; then + [ "$ROLLOUT" = "true" ] && flags+=(--rollout) + dnode deploy "$STACK" --all "${flags[@]}" + else + for node in $NODES; do + echo "::group::$node" + dnode deploy "$node" "$STACK" "${flags[@]}" + echo "::endgroup::" + done + fi + + - name: Notify Success + if: success() && inputs.ntfy_topic != '' + uses: https://lab.zlymeda.dynu.net/actions/ntfy-notify@main + with: + ntfy_topic: ${{ inputs.ntfy_topic }} + ntfy_token: ${{ inputs.ntfy_token }} + status: success + message: 🚀 ${{ inputs.stack }} deployed to ${{ inputs.nodes }}${{ inputs.deploy_tag && format(' ({0})', inputs.deploy_tag) || '' }} + + - name: Notify Failure + if: failure() && (inputs.ntfy_failure_topic != '' || inputs.ntfy_topic != '') + uses: https://lab.zlymeda.dynu.net/actions/ntfy-notify@main + with: + ntfy_topic: ${{ inputs.ntfy_failure_topic || inputs.ntfy_topic }} + ntfy_token: ${{ inputs.ntfy_token }} + status: failure + message: Deploy failed (${{ inputs.stack }} to ${{ inputs.nodes }})${{ inputs.deploy_tag && format(' ({0})', inputs.deploy_tag) || '' }}