Compare commits

...

22 Commits

Author SHA1 Message Date
f3417df036 opt: fix ntfy 2025-12-30 14:51:23 +07:00
8284b41d30 opt: fix ntfy 2025-12-30 14:47:31 +07:00
428a753fa2 opt: fix ntfy 2025-12-30 14:46:06 +07:00
a3aae4ea1d opt: fix ntfy 2025-12-30 14:43:39 +07:00
fdcac755aa opt: fix ntfy 2025-12-30 14:39:46 +07:00
4a94742273 opt: fix ntfy 2025-12-30 14:36:34 +07:00
e969f3da44 opt: fix ntfy 2025-12-30 14:32:04 +07:00
b62856deea fix ntfy 2025-12-30 14:23:41 +07:00
dad171096b fix ntfy 2025-12-30 14:19:56 +07:00
c3ab382adc opt: fix ntfy 2025-12-30 14:02:07 +07:00
ec6d95ed7b opt: moderm message 2025-12-30 13:58:00 +07:00
c95c3212c4 opt: moderm message 2025-12-30 13:55:14 +07:00
c047741832 opt: moderm message 2025-12-30 13:50:34 +07:00
783b920fa4 opt: moderm message 2025-12-30 11:54:42 +07:00
b428b04fef opt: moderm message 2025-12-30 11:46:50 +07:00
7c86049049 opt: fix syntax error 2025-12-30 11:38:02 +07:00
8613e74f11 fix gmail 2025-12-30 11:29:48 +07:00
002788fc03 fix gmail send error 2025-12-30 11:06:36 +07:00
6472fe639a refactor: replace sendmail with curl for Gmail notifications 2025-12-29 16:57:11 +07:00
19ba568834 feat: introduce Telegram bot token and chat ID as action inputs 2025-12-29 16:45:15 +07:00
72836873c7 feat: Add default values for Ntfy, Git URL, and Gmail configuration inputs 2025-12-29 16:38:07 +07:00
b87291aa21 Reorder ntfy parallel execution and wait after gmail and telegram notifications. 2025-12-29 16:36:16 +07:00
3 changed files with 661 additions and 50 deletions

View File

@@ -24,7 +24,6 @@ inputs:
ntfy_username:
description: 'Ntfy Basic Auth Username'
required: false
default: 'homesrv'
ntfy_password:
description: 'Ntfy Basic Auth Password'
required: false
@@ -37,14 +36,20 @@ inputs:
gmail_user:
description: 'Gmail username (sender)'
required: false
default: 'sitienbmt@gmail.com'
gmail_to:
description: 'Email recipient'
required: false
default: 'sitienbmt@gmail.com'
gmail_password:
description: 'Gmail App Password'
required: false
# Telegram Configuration
telegram_bot_token:
description: 'Telegram Bot Token'
required: false
telegram_chat_id:
description: 'Telegram Chat ID'
required: false
@@ -60,19 +65,23 @@ runs:
MESSAGE: ${{ inputs.message }}
# Ntfy
NTFY_URL: ${{ inputs.ntfy_url }}
NTFY_TOPIC: ${{ inputs.ntfy_topic }}
NTFY_USERNAME: ${{ inputs.ntfy_username }}
NTFY_PASSWORD: ${{ inputs.ntfy_password || secrets.NTFY_PASSWORD }}
GIT_URL: ${{ inputs.server_url }}
NTFY_URL: ${{ inputs.ntfy_url || 'https://ntfy.hcmc.online' }}
NTFY_TOPIC: ${{ inputs.ntfy_topic || 'act_runner_deployment' }}
NTFY_USERNAME: ${{ inputs.ntfy_username || env.NTFY_AUTH_USER }}
NTFY_PASSWORD: ${{ inputs.ntfy_password || env.NTFY_AUTH_PASS }}
# Git
GIT_URL: ${{ inputs.server_url || 'https://git.hcmc.online' }}
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_RUN_ID: ${{ github.run_id }}
# Gmail
GMAIL_USER: ${{ inputs.gmail_user }}
GMAIL_TO: ${{ inputs.gmail_to }}
GMAIL_PASS: ${{ inputs.gmail_password || secrets.GMAIL_APP_PASSWORD }}
GMAIL_USER: ${{ inputs.gmail_user || env.GMAIL_USER }}
GMAIL_TO: ${{ inputs.gmail_to || 'tienngodev@proton.me' }}
GMAIL_PASS: ${{ inputs.gmail_password || env.GMAIL_PASSWORD }}
# Telegram
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
TELEGRAM_BOT_TOKEN: ${{ inputs.telegram_bot_token || env.TELEGRAM_BOT_TOKEN }}
TELEGRAM_CHAT_ID: ${{ inputs.telegram_chat_id || env.TELEGRAM_BOT_CHATID }}
run: |
bash ${{ github.action_path }}/notify.sh

294
deploy-deploy-109.log Normal file
View File

@@ -0,0 +1,294 @@
2025-12-30T07:32:30.8126454Z homesrv(version:v0.2.13) received task 109 of job deploy, be triggered by event: push
2025-12-30T07:32:30.8139159Z workflow prepared
2025-12-30T07:32:30.8142097Z evaluating expression 'success()'
2025-12-30T07:32:30.8144318Z expression 'success()' evaluated to 'true'
2025-12-30T07:32:30.8155417Z ☁ git clone 'https://github.com/actions/checkout' # ref=v4
2025-12-30T07:32:30.8156396Z cloning https://github.com/actions/checkout to /data/gitea/.cached/act/c3fe249fe73091a17d6638fe1341e7bd0bcc3466ce52323c0688e83e2463a4ab
2025-12-30T07:32:31.6576078Z Non-terminating error while running 'git clone': some refs were not updated
2025-12-30T07:32:31.6588585Z ☁ git clone 'https://git.hcmc.online/actions/deploy-notify' # ref=main
2025-12-30T07:32:31.6589123Z cloning https://git.hcmc.online/actions/deploy-notify to /data/gitea/.cached/act/231e124cf9cb26095e9a23a48769cf6f9d538910dcf8b91081f910a9f3cd9cd1
2025-12-30T07:32:32.1747479Z Provided ref is not a sha. Checking out branch before pulling changes
2025-12-30T07:32:32.6477649Z Cloned https://git.hcmc.online/actions/deploy-notify to /data/gitea/.cached/act/231e124cf9cb26095e9a23a48769cf6f9d538910dcf8b91081f910a9f3cd9cd1
2025-12-30T07:32:32.6478468Z Provided ref is not a sha. Updating branch ref after pull
2025-12-30T07:32:32.6511993Z Checked out main
2025-12-30T07:32:32.6521486Z expression 'Deploy: ${{ github.repository }} - ${{ github.event.head_commit.message }}' rewritten to 'format('Deploy: {0} - {1}', github.repository, github.event.head_commit.message)'
2025-12-30T07:32:32.6521988Z evaluating expression 'format('Deploy: {0} - {1}', github.repository, github.event.head_commit.message)'
2025-12-30T07:32:32.6523093Z expression 'format('Deploy: {0} - {1}', github.repository, github.event.head_commit.message)' evaluated to '%!t(string=Deploy: tienngo/timelapse-calc - update notify step deploy\n)'
2025-12-30T07:32:32.6523753Z expression '${{ job.status }}' rewritten to 'format('{0}', job.status)'
2025-12-30T07:32:32.6524067Z evaluating expression 'format('{0}', job.status)'
2025-12-30T07:32:32.6524631Z expression 'format('{0}', job.status)' evaluated to '%!t(string=success)'
2025-12-30T07:32:32.6525238Z expression 'Branch: ${{ github.ref_name }}\nCommit: ${{ github.sha }}\nMessage: ${{ github.event.head_commit.message }}\nStatus: ${{ job.status }}\nActor: ${{ github.event.head_commit.author.name }}' rewritten to 'format('Branch: {0}\nCommit: {1}\nMessage: {2}\nStatus: {3}\nActor: {4}', github.ref_name, github.sha, github.event.head_commit.message, job.status, github.event.head_commit.author.name)'
2025-12-30T07:32:32.6525774Z evaluating expression 'format('Branch: {0}\nCommit: {1}\nMessage: {2}\nStatus: {3}\nActor: {4}', github.ref_name, github.sha, github.event.head_commit.message, job.status, github.event.head_commit.author.name)'
2025-12-30T07:32:32.6527217Z expression 'format('Branch: {0}\nCommit: {1}\nMessage: {2}\nStatus: {3}\nActor: {4}', github.ref_name, github.sha, github.event.head_commit.message, job.status, github.event.head_commit.author.name)' evaluated to '%!t(string=Branch: main\nCommit: 932931977e56f0891ab5d38aaa8c9bf33d98a6e5\nMessage: update notify step deploy\n\nStatus: success\nActor: Tien Ngo)'
2025-12-30T07:32:32.6528019Z evaluating expression 'always()'
2025-12-30T07:32:32.6528798Z expression 'always()' evaluated to 'true'
2025-12-30T07:32:32.6529292Z ⭐ Run Pre Send Deployment Notification
2025-12-30T07:32:32.6533368Z run pre step for 'Send Deployment Notification'
2025-12-30T07:32:32.6536064Z ✅ Success - Pre Send Deployment Notification
2025-12-30T07:32:32.6550793Z evaluating expression ''
2025-12-30T07:32:32.6552563Z expression '' evaluated to 'true'
2025-12-30T07:32:32.6553382Z ⭐ Run Main actions/checkout@v4
2025-12-30T07:32:32.6563628Z expression '${{ github.token }}' rewritten to 'format('{0}', github.token)'
2025-12-30T07:32:32.6564156Z evaluating expression 'format('{0}', github.token)'
2025-12-30T07:32:32.6564965Z expression 'format('{0}', github.token)' evaluated to '%!t(string=***)'
2025-12-30T07:32:32.6565747Z expression '${{ github.repository }}' rewritten to 'format('{0}', github.repository)'
2025-12-30T07:32:32.6566081Z evaluating expression 'format('{0}', github.repository)'
2025-12-30T07:32:32.6566752Z expression 'format('{0}', github.repository)' evaluated to '%!t(string=tienngo/timelapse-calc)'
2025-12-30T07:32:32.6567826Z type=remote-action actionDir=/data/gitea/.cached/act/c3fe249fe73091a17d6638fe1341e7bd0bcc3466ce52323c0688e83e2463a4ab actionPath= workdir=/workspace/tienngo/timelapse-calc actionCacheDir=/data/gitea/.cached/act actionName=c3fe249fe73091a17d6638fe1341e7bd0bcc3466ce52323c0688e83e2463a4ab containerActionDir=/data/gitea/.cached/act/5d0d2b4f61fe7cc3/act/actions/c3fe249fe73091a17d6638fe1341e7bd0bcc3466ce52323c0688e83e2463a4ab
2025-12-30T07:32:32.6568399Z /data/gitea/.cached/act/5d0d2b4f61fe7cc3/act/actions/c3fe249fe73091a17d6638fe1341e7bd0bcc3466ce52323c0688e83e2463a4ab
2025-12-30T07:32:32.6568920Z Stripping prefix:/data/gitea/.cached/act/c3fe249fe73091a17d6638fe1341e7bd0bcc3466ce52323c0688e83e2463a4ab/ src:/data/gitea/.cached/act/c3fe249fe73091a17d6638fe1341e7bd0bcc3466ce52323c0688e83e2463a4ab/
2025-12-30T07:32:32.8325994Z executing remote job container: [node /data/gitea/.cached/act/5d0d2b4f61fe7cc3/act/actions/c3fe249fe73091a17d6638fe1341e7bd0bcc3466ce52323c0688e83e2463a4ab/dist/index.js]
2025-12-30T07:32:32.9624447Z ::add-matcher::/data/gitea/.cached/act/5d0d2b4f61fe7cc3/act/actions/c3fe249fe73091a17d6638fe1341e7bd0bcc3466ce52323c0688e83e2463a4ab/dist/problem-matcher.json
2025-12-30T07:32:32.9624759Z ::add-matcher::/data/gitea/.cached/act/5d0d2b4f61fe7cc3/act/actions/c3fe249fe73091a17d6638fe1341e7bd0bcc3466ce52323c0688e83e2463a4ab/dist/problem-matcher.json
2025-12-30T07:32:32.9629678Z Syncing repository: tienngo/timelapse-calc
2025-12-30T07:32:32.9634356Z ::group::Getting Git version info
2025-12-30T07:32:32.9635373Z Working directory is '/data/gitea/.cached/act/5d0d2b4f61fe7cc3/hostexecutor'
2025-12-30T07:32:32.9683437Z [command]/usr/bin/git version
2025-12-30T07:32:32.9734174Z git version 2.39.5
2025-12-30T07:32:32.9767623Z ::endgroup::
2025-12-30T07:32:32.9782199Z Copying '/root/.gitconfig' to '/data/gitea/.cached/act/5d0d2b4f61fe7cc3/tmp/884ffe14-9f3c-4bdf-bce9-6de2f49f81e3/.gitconfig'
2025-12-30T07:32:33.0840988Z Temporarily overriding HOME='/data/gitea/.cached/act/5d0d2b4f61fe7cc3/tmp/884ffe14-9f3c-4bdf-bce9-6de2f49f81e3' before making global git config changes
2025-12-30T07:32:33.0842684Z Adding repository directory to the temporary git global config as a safe directory
2025-12-30T07:32:33.0857425Z [command]/usr/bin/git config --global --add safe.directory /data/gitea/.cached/act/5d0d2b4f61fe7cc3/hostexecutor
2025-12-30T07:32:33.1203399Z Deleting the contents of '/data/gitea/.cached/act/5d0d2b4f61fe7cc3/hostexecutor'
2025-12-30T07:32:33.1211477Z ::group::Initializing the repository
2025-12-30T07:32:33.1220523Z [command]/usr/bin/git init /data/gitea/.cached/act/5d0d2b4f61fe7cc3/hostexecutor
2025-12-30T07:32:33.1270269Z hint: Using 'master' as the name for the initial branch. This default branch name
2025-12-30T07:32:33.1271231Z hint: is subject to change. To configure the initial branch name to use in all
2025-12-30T07:32:33.1271788Z hint: of your new repositories, which will suppress this warning, call:
2025-12-30T07:32:33.1272226Z hint:
2025-12-30T07:32:33.1272533Z hint: git config --global init.defaultBranch <name>
2025-12-30T07:32:33.1272883Z hint:
2025-12-30T07:32:33.1273210Z hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
2025-12-30T07:32:33.1273671Z hint: 'development'. The just-created branch can be renamed via this command:
2025-12-30T07:32:33.1274046Z hint:
2025-12-30T07:32:33.1274389Z hint: git branch -m <name>
2025-12-30T07:32:33.1576649Z Initialized empty Git repository in /data/gitea/.cached/act/5d0d2b4f61fe7cc3/hostexecutor/.git/
2025-12-30T07:32:33.1598170Z [command]/usr/bin/git remote add origin https://git.hcmc.online/tienngo/timelapse-calc
2025-12-30T07:32:33.1664855Z ::endgroup::
2025-12-30T07:32:33.1665232Z ::group::Disabling automatic garbage collection
2025-12-30T07:32:33.1671748Z [command]/usr/bin/git config --local gc.auto 0
2025-12-30T07:32:33.1822148Z ::endgroup::
2025-12-30T07:32:33.1823572Z ::group::Setting up auth
2025-12-30T07:32:33.1838064Z [command]/usr/bin/git config --local --name-only --get-regexp core\.sshCommand
2025-12-30T07:32:33.1892769Z [command]/usr/bin/git submodule foreach --recursive sh -c "git config --local --name-only --get-regexp 'core\.sshCommand' && git config --local --unset-all 'core.sshCommand' || :"
2025-12-30T07:32:33.2201840Z [command]/usr/bin/git config --local --name-only --get-regexp http\.https\:\/\/git\.hcmc\.online\/\.extraheader
2025-12-30T07:32:33.2242202Z [command]/usr/bin/git submodule foreach --recursive sh -c "git config --local --name-only --get-regexp 'http\.https\:\/\/git\.hcmc\.online\/\.extraheader' && git config --local --unset-all 'http.https://git.hcmc.online/.extraheader' || :"
2025-12-30T07:32:33.2497293Z [command]/usr/bin/git config --local --name-only --get-regexp ^includeIf\.gitdir:
2025-12-30T07:32:33.2545019Z [command]/usr/bin/git submodule foreach --recursive git config --local --show-origin --name-only --get-regexp remote.origin.url
2025-12-30T07:32:33.2881058Z [command]/usr/bin/git config --local http.https://git.hcmc.online/.extraheader AUTHORIZATION: basic ***
2025-12-30T07:32:33.2944246Z ::endgroup::
2025-12-30T07:32:33.2944864Z ::group::Fetching the repository
2025-12-30T07:32:33.2959513Z [command]/usr/bin/git -c protocol.version=2 fetch --no-tags --prune --no-recurse-submodules --depth=1 origin +932931977e56f0891ab5d38aaa8c9bf33d98a6e5:refs/remotes/origin/main
2025-12-30T07:32:34.9671126Z From https://git.hcmc.online/tienngo/timelapse-calc
2025-12-30T07:32:34.9672247Z * [new ref] 932931977e56f0891ab5d38aaa8c9bf33d98a6e5 -> origin/main
2025-12-30T07:32:34.9712755Z ::endgroup::
2025-12-30T07:32:34.9713610Z ::group::Determining the checkout info
2025-12-30T07:32:34.9718153Z ::endgroup::
2025-12-30T07:32:34.9728328Z [command]/usr/bin/git sparse-checkout disable
2025-12-30T07:32:35.0282710Z [command]/usr/bin/git config --local --unset-all extensions.worktreeConfig
2025-12-30T07:32:35.0327875Z ::group::Checking out the ref
2025-12-30T07:32:35.0336360Z [command]/usr/bin/git checkout --progress --force -B main refs/remotes/origin/main
2025-12-30T07:32:35.0434721Z Switched to a new branch 'main'
2025-12-30T07:32:35.0436712Z branch 'main' set up to track 'origin/main'.
2025-12-30T07:32:35.0447253Z ::endgroup::
2025-12-30T07:32:35.0508769Z [command]/usr/bin/git log -1 --format=%H
2025-12-30T07:32:35.0549499Z 932931977e56f0891ab5d38aaa8c9bf33d98a6e5
2025-12-30T07:32:35.0582645Z ::remove-matcher owner=checkout-git::
2025-12-30T07:32:35.2420475Z [?25l[+] Building 0.0s (0/1) docker:default
2025-12-30T07:32:35.4235029Z [?25h[?25l[+] Building 0.2s (1/3) docker:default
2025-12-30T07:32:35.4237863Z  => [internal] load build definition from Dockerfile 0.0s
2025-12-30T07:32:35.4238991Z  => => transferring dockerfile: 925B 0.0s
2025-12-30T07:32:35.4240187Z  => [internal] load metadata for docker.io/library/nginx:alpine 0.2s
2025-12-30T07:32:35.4240850Z => [internal] load metadata for docker.io/library/node:20-alpine 0.2s
2025-12-30T07:32:35.5737006Z [?25h[?25l[+] Building 0.3s (1/3) docker:default
2025-12-30T07:32:35.5738736Z  => [internal] load build definition from Dockerfile 0.0s
2025-12-30T07:32:35.5739374Z  => => transferring dockerfile: 925B 0.0s
2025-12-30T07:32:35.5739895Z  => [internal] load metadata for docker.io/library/nginx:alpine 0.3s
2025-12-30T07:32:35.5740271Z => [internal] load metadata for docker.io/library/node:20-alpine 0.3s
2025-12-30T07:32:35.7243723Z [?25h[?25l[+] Building 0.5s (1/3) docker:default
2025-12-30T07:32:35.7246601Z  => [internal] load build definition from Dockerfile 0.0s
2025-12-30T07:32:35.7247933Z  => => transferring dockerfile: 925B 0.0s
2025-12-30T07:32:35.7248855Z  => [internal] load metadata for docker.io/library/nginx:alpine 0.5s
2025-12-30T07:32:35.7249998Z => [internal] load metadata for docker.io/library/node:20-alpine 0.5s
2025-12-30T07:32:35.8745588Z [?25h[?25l[+] Building 0.6s (1/3) docker:default
2025-12-30T07:32:35.8748835Z  => [internal] load build definition from Dockerfile 0.0s
2025-12-30T07:32:35.8768676Z  => => transferring dockerfile: 925B 0.0s
2025-12-30T07:32:35.8769467Z  => [internal] load metadata for docker.io/library/nginx:alpine 0.6s
2025-12-30T07:32:35.8769889Z => [internal] load metadata for docker.io/library/node:20-alpine 0.6s
2025-12-30T07:32:36.0232692Z [?25h[?25l[+] Building 0.8s (1/3) docker:default
2025-12-30T07:32:36.0234190Z  => [internal] load build definition from Dockerfile 0.0s
2025-12-30T07:32:36.0234835Z  => => transferring dockerfile: 925B 0.0s
2025-12-30T07:32:36.0235390Z  => [internal] load metadata for docker.io/library/nginx:alpine 0.8s
2025-12-30T07:32:36.0235815Z => [internal] load metadata for docker.io/library/node:20-alpine 0.8s
2025-12-30T07:32:36.1742299Z [?25h[?25l[+] Building 0.9s (1/3) docker:default
2025-12-30T07:32:36.1745369Z  => [internal] load build definition from Dockerfile 0.0s
2025-12-30T07:32:36.1746611Z  => => transferring dockerfile: 925B 0.0s
2025-12-30T07:32:36.1747627Z  => [internal] load metadata for docker.io/library/nginx:alpine 0.9s
2025-12-30T07:32:36.1748380Z => [internal] load metadata for docker.io/library/node:20-alpine 0.9s
2025-12-30T07:32:36.3236571Z [?25h[?25l[+] Building 1.1s (1/3) docker:default
2025-12-30T07:32:36.3237429Z  => [internal] load build definition from Dockerfile 0.0s
2025-12-30T07:32:36.3237864Z  => => transferring dockerfile: 925B 0.0s
2025-12-30T07:32:36.3238171Z  => [internal] load metadata for docker.io/library/nginx:alpine 1.1s
2025-12-30T07:32:36.3238462Z => [internal] load metadata for docker.io/library/node:20-alpine 1.1s
2025-12-30T07:32:36.4735168Z [?25h[?25l[+] Building 1.2s (1/3) docker:default
2025-12-30T07:32:36.4735713Z  => [internal] load build definition from Dockerfile 0.0s
2025-12-30T07:32:36.4735915Z  => => transferring dockerfile: 925B 0.0s
2025-12-30T07:32:36.4736158Z  => [internal] load metadata for docker.io/library/nginx:alpine 1.2s
2025-12-30T07:32:36.4736394Z => [internal] load metadata for docker.io/library/node:20-alpine 1.2s
2025-12-30T07:32:36.6237280Z [?25h[?25l[+] Building 1.4s (1/3) docker:default
2025-12-30T07:32:36.6240656Z  => [internal] load build definition from Dockerfile 0.0s
2025-12-30T07:32:36.6241999Z  => => transferring dockerfile: 925B 0.0s
2025-12-30T07:32:36.6242738Z  => [internal] load metadata for docker.io/library/nginx:alpine 1.4s
2025-12-30T07:32:36.6243262Z => [internal] load metadata for docker.io/library/node:20-alpine 1.4s
2025-12-30T07:32:36.7739316Z [?25h[?25l[+] Building 1.5s (1/3) docker:default
2025-12-30T07:32:36.7741167Z  => [internal] load build definition from Dockerfile 0.0s
2025-12-30T07:32:36.7741903Z  => => transferring dockerfile: 925B 0.0s
2025-12-30T07:32:36.7742584Z  => [internal] load metadata for docker.io/library/nginx:alpine 1.5s
2025-12-30T07:32:36.7743556Z => [internal] load metadata for docker.io/library/node:20-alpine 1.5s
2025-12-30T07:32:36.8759780Z [?25h[?25l[+] Building 1.6s (2/3) docker:default
2025-12-30T07:32:36.8760359Z  => [internal] load build definition from Dockerfile 0.0s
2025-12-30T07:32:36.8760687Z  => => transferring dockerfile: 925B 0.0s
2025-12-30T07:32:36.8760887Z  => [internal] load metadata for docker.io/library/nginx:alpine 1.6s
2025-12-30T07:32:36.8761114Z  => [internal] load metadata for docker.io/library/node:20-alpine 1.6s
2025-12-30T07:32:37.0265928Z [?25h[?25l[+] Building 1.8s (2/3) docker:default
2025-12-30T07:32:37.0268652Z  => [internal] load build definition from Dockerfile 0.0s
2025-12-30T07:32:37.0270026Z  => => transferring dockerfile: 925B 0.0s
2025-12-30T07:32:37.0271170Z  => [internal] load metadata for docker.io/library/nginx:alpine 1.8s
2025-12-30T07:32:37.0272004Z  => [internal] load metadata for docker.io/library/node:20-alpine 1.6s
2025-12-30T07:32:37.1768885Z [?25h[?25l[+] Building 1.9s (2/3) docker:default
2025-12-30T07:32:37.1769954Z  => [internal] load build definition from Dockerfile 0.0s
2025-12-30T07:32:37.1770432Z  => => transferring dockerfile: 925B 0.0s
2025-12-30T07:32:37.1770854Z  => [internal] load metadata for docker.io/library/nginx:alpine 1.9s
2025-12-30T07:32:37.1771400Z  => [internal] load metadata for docker.io/library/node:20-alpine 1.6s
2025-12-30T07:32:37.1890360Z [?25h[?25l[+] Building 1.9s (3/3) docker:default
2025-12-30T07:32:37.1891094Z  => [internal] load build definition from Dockerfile 0.0s
2025-12-30T07:32:37.1891331Z  => => transferring dockerfile: 925B 0.0s
2025-12-30T07:32:37.1891500Z  => [internal] load metadata for docker.io/library/nginx:alpine 1.9s
2025-12-30T07:32:37.1891783Z  => [internal] load metadata for docker.io/library/node:20-alpine 1.6s
2025-12-30T07:32:37.2993207Z [?25h[?25l[+] Building 2.1s (14/15) docker:default
2025-12-30T07:32:37.2993965Z  => CACHED [stage-1 2/3] COPY --from=build /app/dist /usr/share/nginx/htm 0.0s
2025-12-30T07:32:37.2994497Z  => CACHED [stage-1 3/3] RUN echo 'server { listen 80; server_nam 0.0s
2025-12-30T07:32:37.2994889Z  => exporting to image 0.0s
2025-12-30T07:32:37.2995113Z  => => exporting layers 0.0s
2025-12-30T07:32:37.2995282Z  => => exporting manifest sha256:07b51d6e7a1006650af2c468628cde0a62f44cfa 0.0s
2025-12-30T07:32:37.2995438Z  => => exporting config sha256:f29c33089c7663ebbb5b4b5aa2d8763ce0f0dbe608 0.0s
2025-12-30T07:32:37.2995592Z  => => exporting attestation manifest sha256:394edcb413d981f3b4b90e855de3 0.0s
2025-12-30T07:32:37.2995761Z  => => exporting manifest list sha256:2d5c99a88ce4710519e2c9b5c5be4a08986 0.0s
2025-12-30T07:32:37.4074166Z [?25h[?25l[+] Building 2.2s (15/15) FINISHED docker:default
2025-12-30T07:32:37.4075141Z  => [internal] load build definition from Dockerfile 0.0s
2025-12-30T07:32:37.4075759Z  => => transferring dockerfile: 925B 0.0s
2025-12-30T07:32:37.4076148Z  => [internal] load metadata for docker.io/library/nginx:alpine 1.9s
2025-12-30T07:32:37.4076431Z  => [internal] load metadata for docker.io/library/node:20-alpine 1.6s
2025-12-30T07:32:37.4076692Z  => [internal] load .dockerignore 0.0s
2025-12-30T07:32:37.4076919Z  => => transferring context: 366B 0.0s
2025-12-30T07:32:37.4077115Z  => [build 1/6] FROM docker.io/library/node:20-alpine@sha256:658d0f63e501 0.0s
2025-12-30T07:32:37.4077344Z  => => resolve docker.io/library/node:20-alpine@sha256:658d0f63e501824d6c 0.0s
2025-12-30T07:32:37.4077504Z  => [stage-1 1/3] FROM docker.io/library/nginx:alpine@sha256:8491795299c8 0.0s
2025-12-30T07:32:37.4077721Z  => => resolve docker.io/library/nginx:alpine@sha256:8491795299c8e739b7fc 0.0s
2025-12-30T07:32:37.4077871Z  => [internal] load build context 0.0s
2025-12-30T07:32:37.4078017Z  => => transferring context: 168.59kB 0.0s
2025-12-30T07:32:37.4078205Z  => CACHED [build 2/6] WORKDIR /app 0.0s
2025-12-30T07:32:37.4078411Z  => CACHED [build 3/6] COPY package.json package-lock.json ./ 0.0s
2025-12-30T07:32:37.4078575Z  => CACHED [build 4/6] RUN npm ci 0.0s
2025-12-30T07:32:37.4078724Z  => CACHED [build 5/6] COPY . . 0.0s
2025-12-30T07:32:37.4078905Z  => CACHED [build 6/6] RUN npm run build 0.0s
2025-12-30T07:32:37.4079088Z  => CACHED [stage-1 2/3] COPY --from=build /app/dist /usr/share/nginx/htm 0.0s
2025-12-30T07:32:37.4079671Z  => CACHED [stage-1 3/3] RUN echo 'server { listen 80; server_nam 0.0s
2025-12-30T07:32:37.4079963Z  => exporting to image 0.1s
2025-12-30T07:32:37.4080255Z  => => exporting layers 0.0s
2025-12-30T07:32:37.4080449Z  => => exporting manifest sha256:07b51d6e7a1006650af2c468628cde0a62f44cfa 0.0s
2025-12-30T07:32:37.4080603Z  => => exporting config sha256:f29c33089c7663ebbb5b4b5aa2d8763ce0f0dbe608 0.0s
2025-12-30T07:32:37.4080778Z  => => exporting attestation manifest sha256:394edcb413d981f3b4b90e855de3 0.0s
2025-12-30T07:32:37.4081040Z  => => exporting manifest list sha256:2d5c99a88ce4710519e2c9b5c5be4a08986 0.0s
2025-12-30T07:32:37.4081302Z  => => naming to docker.io/library/timelapse-calc:latest 0.0s
2025-12-30T07:32:37.4081594Z  => => unpacking to docker.io/library/timelapse-calc:latest 0.0s
2025-12-30T07:32:37.4143763Z [?25h
2025-12-30T07:32:37.8437241Z timelapse-calc
2025-12-30T07:32:37.8869730Z timelapse-calc
2025-12-30T07:32:37.9578262Z 6b42f72afe74af1f06f12d4123382b831509d306567fcab8681bb2b4831b58ee
2025-12-30T07:32:38.2451575Z timelapse-calc timelapse-calc:latest Up Less than a second
2025-12-30T07:32:38.2452272Z udemy-license udemy-license:latest Up 25 hours
2025-12-30T07:32:38.2452514Z udemy-cookies-api udemy-cookies-api:latest Up 25 hours
2025-12-30T07:32:38.2452712Z vaultwarden vaultwarden/server:latest Up 27 hours (healthy)
2025-12-30T07:32:38.2452878Z bepcuatom-frontend bepcuatom-frontend:latest Up 4 days
2025-12-30T07:32:38.2453036Z bepcuatom-backend bepcuatom-backend:latest Up 4 days
2025-12-30T07:32:38.2453192Z gitea gitea/gitea:latest Up 23 hours
2025-12-30T07:32:38.2453338Z immich_server ghcr.io/immich-app/immich-server:v2 Up 5 days (healthy)
2025-12-30T07:32:38.4076472Z
2025-12-30T07:32:38.4077335Z ╔════════════════════════════════════════╗
2025-12-30T07:32:38.4077723Z ║ 🚀 Deployment Notification System ║
2025-12-30T07:32:38.4077997Z ╚════════════════════════════════════════╝
2025-12-30T07:32:38.4078206Z
2025-12-30T07:32:38.4092152Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2025-12-30T07:32:38.4093160Z 📧 Gmail SMTP Email
2025-12-30T07:32:38.4093722Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2025-12-30T07:32:38.4094313Z From: sitienbmt@gmail.com
2025-12-30T07:32:38.4094601Z To: tienngodev@proton.me
2025-12-30T07:32:38.4095045Z SMTP: smtp.gmail.com:587
2025-12-30T07:32:38.4095375Z
2025-12-30T07:32:38.4095740Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2025-12-30T07:32:38.4096199Z ✈ Telegram Message
2025-12-30T07:32:38.4096579Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2025-12-30T07:32:38.4096905Z Chat ID: 5722742247
2025-12-30T07:32:38.4097158Z
2025-12-30T07:32:38.4099255Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2025-12-30T07:32:38.4099994Z 🔔 Ntfy Push Notification
2025-12-30T07:32:38.4100555Z ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2025-12-30T07:32:38.4101318Z Server: https://ntfy.hcmc.online
2025-12-30T07:32:38.4101626Z Topic: act_runner_deployment
2025-12-30T07:32:38.4101919Z
2025-12-30T07:32:38.4102528Z ✓ Using Basic Authentication
2025-12-30T07:32:38.4102877Z
2025-12-30T07:32:38.4132868Z → Sending Telegram message...
2025-12-30T07:32:38.4134118Z → Sending push notification...
2025-12-30T07:32:38.4134573Z → Target: https://ntfy.hcmc.online/act_runner_deployment
2025-12-30T07:32:38.4304037Z → Sending HTML email...
2025-12-30T07:32:39.2274173Z ✓ Message sent successfully
2025-12-30T07:32:39.2274881Z
2025-12-30T07:32:41.4674276Z ✓ Email sent successfully
2025-12-30T07:32:41.4675673Z
2025-12-30T07:32:41.4689242Z ❌ Failure - Main Send notification
2025-12-30T07:32:41.4693405Z exit status 92
2025-12-30T07:32:41.4694144Z ❌ Failure - Main Send Deployment Notification
2025-12-30T07:32:41.4696719Z exit status 92
2025-12-30T07:32:41.4698285Z expression '${{ job.status }}' rewritten to 'format('{0}', job.status)'
2025-12-30T07:32:41.4698544Z evaluating expression 'format('{0}', job.status)'
2025-12-30T07:32:41.4699160Z expression 'format('{0}', job.status)' evaluated to '%!t(string=failure)'
2025-12-30T07:32:41.4699683Z expression 'Branch: ${{ github.ref_name }}\nCommit: ${{ github.sha }}\nMessage: ${{ github.event.head_commit.message }}\nStatus: ${{ job.status }}\nActor: ${{ github.event.head_commit.author.name }}' rewritten to 'format('Branch: {0}\nCommit: {1}\nMessage: {2}\nStatus: {3}\nActor: {4}', github.ref_name, github.sha, github.event.head_commit.message, job.status, github.event.head_commit.author.name)'
2025-12-30T07:32:41.4700039Z evaluating expression 'format('Branch: {0}\nCommit: {1}\nMessage: {2}\nStatus: {3}\nActor: {4}', github.ref_name, github.sha, github.event.head_commit.message, job.status, github.event.head_commit.author.name)'
2025-12-30T07:32:41.4700945Z expression 'format('Branch: {0}\nCommit: {1}\nMessage: {2}\nStatus: {3}\nActor: {4}', github.ref_name, github.sha, github.event.head_commit.message, job.status, github.event.head_commit.author.name)' evaluated to '%!t(string=Branch: main\nCommit: 932931977e56f0891ab5d38aaa8c9bf33d98a6e5\nMessage: update notify step deploy\n\nStatus: failure\nActor: Tien Ngo)'
2025-12-30T07:32:41.4701496Z expression 'Deploy: ${{ github.repository }} - ${{ github.event.head_commit.message }}' rewritten to 'format('Deploy: {0} - {1}', github.repository, github.event.head_commit.message)'
2025-12-30T07:32:41.4701754Z evaluating expression 'format('Deploy: {0} - {1}', github.repository, github.event.head_commit.message)'
2025-12-30T07:32:41.4702324Z expression 'format('Deploy: {0} - {1}', github.repository, github.event.head_commit.message)' evaluated to '%!t(string=Deploy: tienngo/timelapse-calc - update notify step deploy\n)'
2025-12-30T07:32:41.4702901Z evaluating expression 'always()'
2025-12-30T07:32:41.4703233Z expression 'always()' evaluated to 'true'
2025-12-30T07:32:41.4703441Z ⭐ Run Post Send Deployment Notification
2025-12-30T07:32:41.4705793Z run post step for 'Send Deployment Notification'
2025-12-30T07:32:41.4706644Z /data/gitea/.cached/act/5d0d2b4f61fe7cc3/act/actions/231e124cf9cb26095e9a23a48769cf6f9d538910dcf8b91081f910a9f3cd9cd1
2025-12-30T07:32:41.4707054Z Stripping prefix:/data/gitea/.cached/act/231e124cf9cb26095e9a23a48769cf6f9d538910dcf8b91081f910a9f3cd9cd1/ src:/data/gitea/.cached/act/231e124cf9cb26095e9a23a48769cf6f9d538910dcf8b91081f910a9f3cd9cd1/
2025-12-30T07:32:41.5883739Z ✅ Success - Post Send Deployment Notification
2025-12-30T07:32:41.5888078Z evaluating expression 'always()'
2025-12-30T07:32:41.5888614Z expression 'always()' evaluated to 'true'
2025-12-30T07:32:41.5888834Z ⭐ Run Post actions/checkout@v4
2025-12-30T07:32:41.5890816Z run post step for 'actions/checkout@v4'
2025-12-30T07:32:41.5891666Z executing remote job container: [node /data/gitea/.cached/act/5d0d2b4f61fe7cc3/act/actions/c3fe249fe73091a17d6638fe1341e7bd0bcc3466ce52323c0688e83e2463a4ab/dist/index.js]
2025-12-30T07:32:41.7173670Z [command]/usr/bin/git version
2025-12-30T07:32:41.7227322Z git version 2.39.5
2025-12-30T07:32:41.7263798Z ***
2025-12-30T07:32:41.7277313Z Copying '/root/.gitconfig' to '/data/gitea/.cached/act/5d0d2b4f61fe7cc3/tmp/d51fc143-53fe-480a-8347-b89464300cdf/.gitconfig'
2025-12-30T07:32:41.7292479Z Temporarily overriding HOME='/data/gitea/.cached/act/5d0d2b4f61fe7cc3/tmp/d51fc143-53fe-480a-8347-b89464300cdf' before making global git config changes
2025-12-30T07:32:41.7293705Z Adding repository directory to the temporary git global config as a safe directory
2025-12-30T07:32:41.7301326Z [command]/usr/bin/git config --global --add safe.directory /data/gitea/.cached/act/5d0d2b4f61fe7cc3/hostexecutor
2025-12-30T07:32:41.7349164Z [command]/usr/bin/git config --local --name-only --get-regexp core\.sshCommand
2025-12-30T07:32:41.7400252Z [command]/usr/bin/git submodule foreach --recursive sh -c "git config --local --name-only --get-regexp 'core\.sshCommand' && git config --local --unset-all 'core.sshCommand' || :"
2025-12-30T07:32:41.7652558Z [command]/usr/bin/git config --local --name-only --get-regexp http\.https\:\/\/git\.hcmc\.online\/\.extraheader
2025-12-30T07:32:41.7679784Z http.https://git.hcmc.online/.extraheader
2025-12-30T07:32:41.7694965Z [command]/usr/bin/git config --local --unset-all http.https://git.hcmc.online/.extraheader
2025-12-30T07:32:41.7793730Z [command]/usr/bin/git submodule foreach --recursive sh -c "git config --local --name-only --get-regexp 'http\.https\:\/\/git\.hcmc\.online\/\.extraheader' && git config --local --unset-all 'http.https://git.hcmc.online/.extraheader' || :"
2025-12-30T07:32:41.8044091Z [command]/usr/bin/git config --local --name-only --get-regexp ^includeIf\.gitdir:
2025-12-30T07:32:41.8086505Z [command]/usr/bin/git submodule foreach --recursive git config --local --show-origin --name-only --get-regexp remote.origin.url
2025-12-30T07:32:41.8393480Z ✅ Success - Post actions/checkout@v4
2025-12-30T07:32:41.8396921Z Cleaning up container for job deploy
2025-12-30T07:32:41.8898513Z 🏁 Job failed
2025-12-30T07:32:41.8899384Z Job 'deploy' failed

382
notify.sh
View File

@@ -7,85 +7,393 @@ if [ "$STATUS" = "failure" ]; then
ICON="❌"
fi
# Prepare Text for Telegram (Markdown)
TEXT="$ICON *$TITLE*%0A%0A$MESSAGE"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo "Starting notifications..."
# Function: Send to Ntfy
echo ""
echo -e "${GREEN}╔════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ 🚀 Deployment Notification System ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════╝${NC}"
echo ""
# Function: Send to Ntfy (Modern Push Notification)
send_ntfy() {
echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${YELLOW}🔔 Ntfy Push Notification${NC}"
echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
if [ -n "$NTFY_URL" ] && [ -n "$NTFY_TOPIC" ]; then
local click_url="$GIT_URL/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
local auth_args=""
# Check for Basic Auth
if [ -n "$NTFY_USERNAME" ] && [ -n "$NTFY_PASSWORD" ]; then
echo -e " Server: ${GREEN}$NTFY_URL${NC}"
echo -e " Topic: ${GREEN}$NTFY_TOPIC${NC}"
echo -e " Auth: ${GREEN}Basic Auth${NC}"
auth_args="-u $NTFY_USERNAME:$NTFY_PASSWORD"
else
echo -e " Server: ${GREEN}$NTFY_URL${NC}"
echo -e " Topic: ${GREEN}$NTFY_TOPIC${NC}"
echo -e " Auth: ${YELLOW}None (Public)${NC}"
fi
echo "[Ntfy] Sending..."
if curl -s $auth_args -X POST "$NTFY_URL/$NTFY_TOPIC" \
echo -e " ${YELLOW}${NC} Sending push notification..."
echo -e " ${YELLOW}Debug - Raw MESSAGE:${NC}"
echo "$MESSAGE" | sed 's/^/ RAW: /'
echo -e " ${YELLOW}Debug - Interpreted MESSAGE:${NC}"
echo -e "$MESSAGE" | sed 's/^/ INT: /'
echo ""
# Create temp file with message content
local temp_msg=$(mktemp)
echo -e "$MESSAGE" > "$temp_msg"
echo -e " ${YELLOW}Debug - Temp file content:${NC}"
cat "$temp_msg" | sed 's/^/ FILE: /'
echo ""
# Disable exit on error for curl
set +e
response=$(curl -s -w "\n%{http_code}" --http1.1 -k $auth_args \
-X POST "$NTFY_URL/$NTFY_TOPIC" \
-H "Title: $ICON $TITLE" \
-H "Priority: 4" \
-H "Click: $click_url" \
-H "Actions: view, Open Logs, $click_url" \
-d "$MESSAGE"; then
echo "[Ntfy] Sent."
-T "$temp_msg" 2>&1)
curl_exit_code=$?
# Clean up temp file
rm -f "$temp_msg"
set -e
# Check curl exit code
if [ $curl_exit_code -ne 0 ]; then
echo -e " ${RED}${NC} Failed to send (curl error: $curl_exit_code)"
if [ -n "$response" ]; then
echo -e " ${RED}Error:${NC} $response"
fi
else
echo "[Ntfy] Failed."
http_code=$(echo "$response" | tail -n1)
if [ "$http_code" = "200" ] || [ "$http_code" = "201" ]; then
echo -e " ${GREEN}${NC} Sent successfully (HTTP $http_code)"
else
echo -e " ${RED}${NC} Failed (HTTP $http_code)"
response_body=$(echo "$response" | head -n -1)
if [ -n "$response_body" ]; then
echo -e " ${RED}Response:${NC} $response_body"
fi
fi
fi
echo ""
fi
}
# Function: Send to Gmail
# Function: Send to Gmail (Modern HTML Email)
send_gmail() {
if [ -n "$GMAIL_USER" ] && [ -n "$GMAIL_TO" ] && [ -n "$GMAIL_PASS" ]; then
if ! command -v sendmail &> /dev/null; then
echo "[Gmail] Warning: sendmail not found, skipping."
return
echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${YELLOW}📧 Gmail SMTP Email${NC}"
echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e " From: ${GREEN}$GMAIL_USER${NC}"
echo -e " To: ${GREEN}$GMAIL_TO${NC}"
echo -e " SMTP: ${GREEN}smtp.gmail.com:587${NC}"
echo ""
# Determine status color and badge
local status_color="#22c55e"
local status_bg="#dcfce7"
local status_text="SUCCESS"
if [ "$STATUS" = "failure" ]; then
status_color="#ef4444"
status_bg="#fee2e2"
status_text="FAILURE"
fi
echo "[Gmail] Sending..."
{
echo "Subject: $ICON $TITLE"
echo "From: $GMAIL_USER"
echo "To: $GMAIL_TO"
echo ""
echo "$MESSAGE"
} | sendmail -S smtp.gmail.com:587 \
-au"$GMAIL_USER" \
-ap"$GMAIL_PASS" \
"$GMAIL_TO" && echo "[Gmail] Sent." || echo "[Gmail] Failed."
# Parse structured message data
local branch=$(echo "$MESSAGE" | grep -oP '^Branch:\s*\K.*' || echo "")
local commit=$(echo "$MESSAGE" | grep -oP '^Commit:\s*\K.*' || echo "")
local commit_msg=$(echo "$MESSAGE" | grep -oP '^Message:\s*\K.*' || echo "")
local actor=$(echo "$MESSAGE" | grep -oP '^Actor:\s*\K.*' || echo "")
# Shorten commit hash for display
local commit_short="${commit:0:8}"
# Build modern HTML email with inline CSS
local html_body=$(cat <<EOF
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>$TITLE</title>
</head>
<body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background-color: #f3f4f6;">
<table width="100%" cellpadding="0" cellspacing="0" style="background-color: #f3f4f6; padding: 40px 20px;">
<tr>
<td align="center">
<table width="600" cellpadding="0" cellspacing="0" style="background-color: #ffffff; border-radius: 12px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); overflow: hidden;">
<!-- Header -->
<tr>
<td style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 32px 40px; text-align: center;">
<h1 style="margin: 0; color: #ffffff; font-size: 28px; font-weight: 700;">$ICON Deployment Notification</h1>
</td>
</tr>
<!-- Status Badge -->
<tr>
<td style="padding: 32px 40px 24px; text-align: center;">
<div style="display: inline-block; background-color: $status_bg; color: $status_color; padding: 8px 20px; border-radius: 20px; font-weight: 600; font-size: 14px; letter-spacing: 0.5px;">
$status_text
</div>
</td>
</tr>
<!-- Repository Info -->
<tr>
<td style="padding: 0 40px 24px; text-align: center;">
<h2 style="margin: 0; color: #111827; font-size: 20px; font-weight: 600;">${GITHUB_REPOSITORY:-Repository}</h2>
</td>
</tr>
<!-- Deployment Details Cards -->
<tr>
<td style="padding: 0 40px 32px;">
<table width="100%" cellpadding="0" cellspacing="0">
<!-- Branch -->
<tr>
<td style="padding-bottom: 12px;">
<div style="background-color: #f9fafb; border-left: 4px solid #3b82f6; padding: 16px; border-radius: 6px;">
<div style="color: #6b7280; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px;">🌿 Branch</div>
<div style="color: #111827; font-size: 15px; font-weight: 500; font-family: 'Courier New', monospace;">$branch</div>
</div>
</td>
</tr>
<!-- Commit -->
<tr>
<td style="padding-bottom: 12px;">
<div style="background-color: #f9fafb; border-left: 4px solid #8b5cf6; padding: 16px; border-radius: 6px;">
<div style="color: #6b7280; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px;">🔖 Commit</div>
<div style="color: #111827; font-size: 15px; font-weight: 500; font-family: 'Courier New', monospace;">$commit_short</div>
</div>
</td>
</tr>
<!-- Commit Message -->
<tr>
<td style="padding-bottom: 12px;">
<div style="background-color: #f9fafb; border-left: 4px solid $status_color; padding: 16px; border-radius: 6px;">
<div style="color: #6b7280; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px;">💬 Commit Message</div>
<div style="color: #111827; font-size: 15px; line-height: 1.5;">$commit_msg</div>
</div>
</td>
</tr>
<!-- Actor -->
<tr>
<td>
<div style="background-color: #f9fafb; border-left: 4px solid #10b981; padding: 16px; border-radius: 6px;">
<div style="color: #6b7280; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px;">👤 Author</div>
<div style="color: #111827; font-size: 15px; font-weight: 500;">$actor</div>
</div>
</td>
</tr>
</table>
</td>
</tr>
<!-- Metadata -->
<tr>
<td style="padding: 0 40px 32px;">
<table width="100%" cellpadding="8" cellspacing="0" style="border-top: 1px solid #e5e7eb; background-color: #fafafa; border-radius: 6px;">
<tr>
<td style="color: #6b7280; font-size: 13px; padding-top: 16px;">
<strong>🔢 Run ID:</strong> ${GITHUB_RUN_ID:-N/A}
</td>
</tr>
<tr>
<td style="color: #6b7280; font-size: 13px;">
<strong>⏰ Timestamp:</strong> $(date -u +"%Y-%m-%d %H:%M:%S UTC")
</td>
</tr>
</table>
</td>
</tr>
<!-- Action Button -->
<tr>
<td style="padding: 0 40px 40px; text-align: center;">
<a href="$GIT_URL/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" style="display: inline-block; background-color: #667eea; color: #ffffff; text-decoration: none; padding: 14px 36px; border-radius: 8px; font-weight: 600; font-size: 15px; box-shadow: 0 2px 4px rgba(102, 126, 234, 0.3);">
📋 View Deployment Logs
</a>
</td>
</tr>
<!-- Footer -->
<tr>
<td style="background-color: #f9fafb; padding: 24px 40px; text-align: center; border-top: 1px solid #e5e7eb;">
<p style="margin: 0; color: #9ca3af; font-size: 12px;">
🤖 Automated deployment notification from <strong>Act Runner</strong>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
EOF
)
# Create MIME email with proper headers
local boundary="----=_Part_$(date +%s)_$(( RANDOM ))"
local email_content=$(cat <<EOF
From: Act Runner Deployment <noreply@actrunner>
Reply-To: $GMAIL_USER
To: $GMAIL_TO
Subject: $ICON $TITLE
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="$boundary"
--$boundary
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
$ICON $TITLE
Status: $STATUS
Message: $MESSAGE
Repository: ${GITHUB_REPOSITORY:-N/A}
Run ID: ${GITHUB_RUN_ID:-N/A}
Timestamp: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
View logs: $GIT_URL/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}
--$boundary
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8bit
$html_body
--$boundary--
EOF
)
# Send email via SMTP
echo -e " ${YELLOW}${NC} Sending HTML email..."
response=$(printf "%s" "$email_content" | curl --ssl-reqd \
--url "smtp://smtp.gmail.com:587" \
--user "$GMAIL_USER:$GMAIL_PASS" \
--mail-from "$GMAIL_USER" \
--mail-rcpt "$GMAIL_TO" \
--upload-file - \
--silent \
--show-error 2>&1)
exit_code=$?
if [ $exit_code -eq 0 ]; then
echo -e " ${GREEN}${NC} Email sent successfully"
else
echo -e " ${RED}${NC} Failed to send email"
echo -e " ${RED}Error:${NC} $response"
fi
echo ""
fi
}
# Function: Send to Telegram
# Function: Send to Telegram (Modern Rich Message)
send_telegram() {
if [ -n "$TELEGRAM_BOT_TOKEN" ] && [ -n "$TELEGRAM_CHAT_ID" ]; then
echo "[Telegram] Sending..."
if curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
-d chat_id="$TELEGRAM_CHAT_ID" \
-d parse_mode="Markdown" \
-d text="$TEXT"; then
echo "[Telegram] Sent."
else
echo "[Telegram] Failed."
echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${YELLOW}✈️ Telegram Message${NC}"
echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e " Chat ID: ${GREEN}$TELEGRAM_CHAT_ID${NC}"
echo ""
# Determine status emoji and formatting
local status_emoji="✅"
local status_text="SUCCESS"
if [ "$STATUS" = "failure" ]; then
status_emoji="❌"
status_text="FAILURE"
fi
# Build rich Telegram message with MarkdownV2 formatting
local telegram_message=$(cat <<EOF
$ICON *$TITLE*
━━━━━━━━━━━━━━━━━━━━━━
$status_emoji *Status:* \`$status_text\`
━━━━━━━━━━━━━━━━━━━━━━
📝 *Message:*
$MESSAGE
📊 *Details:*
• Repository: \`${GITHUB_REPOSITORY:-N/A}\`
• Run ID: \`${GITHUB_RUN_ID:-N/A}\`
• Timestamp: \`$(date -u +"%Y-%m-%d %H:%M:%S UTC")\`
🔗 [View Deployment Logs]($GIT_URL/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID})
EOF
)
echo -e " ${YELLOW}${NC} Sending Telegram message..."
response=$(curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
-H "Content-Type: application/json" \
-d "{
\"chat_id\": \"$TELEGRAM_CHAT_ID\",
\"parse_mode\": \"Markdown\",
\"text\": $(echo "$telegram_message" | jq -Rs .),
\"disable_web_page_preview\": false,
\"reply_markup\": {
\"inline_keyboard\": [[
{
\"text\": \"📋 View Logs\",
\"url\": \"$GIT_URL/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}\"
}
]]
}
}" 2>&1)
# Check if message was sent successfully
if echo "$response" | grep -q '"ok":true'; then
echo -e " ${GREEN}${NC} Message sent successfully"
else
echo -e " ${RED}${NC} Failed to send message"
# Try to extract error description
error_desc=$(echo "$response" | grep -o '"description":"[^"]*"' | cut -d'"' -f4)
if [ -n "$error_desc" ]; then
echo -e " ${RED}Error:${NC} $error_desc"
fi
fi
echo ""
fi
}
# Execute in parallel
send_ntfy &
PID_NTFY=$!
send_gmail &
PID_GMAIL=$!
send_telegram &
PID_TG=$!
send_ntfy &
PID_NTFY=$!
# Wait for completion
wait $PID_NTFY
wait $PID_GMAIL
wait $PID_TG
wait $PID_NTFY
echo "All notifications processed."