├── action.yml ├── LICENSE ├── README.md ├── tmate2actions.sh └── ngrok2actions.sh /action.yml: -------------------------------------------------------------------------------- 1 | name: 'SSH to GitHub Actions' 2 | author: 'P3TERX' 3 | description: 'Connect to GitHub Actions VM via SSH for interactive debugging' 4 | inputs: 5 | mode: 6 | description: 'choose tmate or ngrok mode' 7 | required: false 8 | default: 'tmate' 9 | runs: 10 | using: "composite" 11 | steps: 12 | - run: $GITHUB_ACTION_PATH/${{ inputs.mode }}2actions.sh 13 | shell: bash 14 | branding: 15 | icon: 'terminal' 16 | color: 'gray-dark' 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 P3TERX 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SSH to GitHub Actions 2 | 3 | This GitHub Action offers you connect to GitHub Actions VM via SSH for interactive debugging 4 | 5 | ## Features 6 | 7 | - Support Ubuntu and macOS 8 | - Provides two optional SSH connection methods, tmate and ngrok 9 | - Proceed to the next step to stay connected 10 | - Send SSH connection info to Telegram 11 | 12 | ## Usage 13 | 14 | ### Connect to Github Actions VM via SSH by using [tmate](https://tmate.io) 15 | 16 | ```yaml 17 | - name: Start SSH via tmate 18 | uses: P3TERX/ssh2actions@main 19 | # Send connection info to Telegram (optional) 20 | # You can find related documents here: https://core.telegram.org/bots 21 | env: 22 | TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} 23 | TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }} 24 | ``` 25 | 26 | ### Connect to Github Actions VM via SSH by using [ngrok](https://ngrok.com) 27 | 28 | ```yaml 29 | - name: Start SSH via ngrok 30 | uses: P3TERX/ssh2actions@main 31 | with: 32 | mode: ngrok 33 | env: 34 | # After sign up on the https://ngrok.com 35 | # You can find this token here: https://dashboard.ngrok.com/auth/your-authtoken 36 | NGROK_TOKEN: ${{ secrets.NGROK_TOKEN }} 37 | 38 | # ngrok server region [us, eu, au, ap, sa, jp, in] (optional, default: us) 39 | # You can find this server region here: https://ngrok.com/docs#global-locations 40 | NGROK_REGION: us 41 | 42 | # This password you will use when authorizing via SSH 43 | SSH_PASSWORD: ${{ secrets.SSH_PASSWORD }} 44 | 45 | # Send connection info to Telegram (optional) 46 | # You can find related documents here: https://core.telegram.org/bots 47 | TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} 48 | TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }} 49 | ``` 50 | 51 | ## Lisence 52 | 53 | [MIT](https://github.com/P3TERX/ssh2actions/blob/main/LICENSE) © P3TERX 54 | -------------------------------------------------------------------------------- /tmate2actions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright (c) 2020 P3TERX 4 | # 5 | # This is free software, licensed under the MIT License. 6 | # See /LICENSE for more information. 7 | # 8 | # https://github.com/P3TERX/ssh2actions 9 | # File name:tmate2actions.sh 10 | # Description: Connect to Github Actions VM via SSH by using tmate 11 | # Version: 2.0 12 | # 13 | 14 | set -e 15 | Green_font_prefix="\033[32m" 16 | Red_font_prefix="\033[31m" 17 | Green_background_prefix="\033[42;37m" 18 | Red_background_prefix="\033[41;37m" 19 | Font_color_suffix="\033[0m" 20 | INFO="[${Green_font_prefix}INFO${Font_color_suffix}]" 21 | ERROR="[${Red_font_prefix}ERROR${Font_color_suffix}]" 22 | TMATE_SOCK="/tmp/tmate.sock" 23 | TELEGRAM_LOG="/tmp/telegram.log" 24 | CONTINUE_FILE="/tmp/continue" 25 | 26 | # Install tmate on macOS or Ubuntu 27 | echo -e "${INFO} Setting up tmate ..." 28 | if [[ -n "$(uname | grep Linux)" ]]; then 29 | curl -fsSL git.io/tmate.sh | bash 30 | elif [[ -x "$(command -v brew)" ]]; then 31 | brew install tmate 32 | else 33 | echo -e "${ERROR} This system is not supported!" 34 | exit 1 35 | fi 36 | 37 | # Generate ssh key if needed 38 | [[ -e ~/.ssh/id_rsa ]] || ssh-keygen -t rsa -f ~/.ssh/id_rsa -q -N "" 39 | 40 | # Run deamonized tmate 41 | echo -e "${INFO} Running tmate..." 42 | tmate -S ${TMATE_SOCK} new-session -d 43 | tmate -S ${TMATE_SOCK} wait tmate-ready 44 | 45 | # Print connection info 46 | TMATE_SSH=$(tmate -S ${TMATE_SOCK} display -p '#{tmate_ssh}') 47 | TMATE_WEB=$(tmate -S ${TMATE_SOCK} display -p '#{tmate_web}') 48 | MSG=" 49 | *GitHub Actions - tmate session info:* 50 | 51 | ⚡ *CLI:* 52 | \`${TMATE_SSH}\` 53 | 54 | 🔗 *URL:* 55 | ${TMATE_WEB} 56 | 57 | 🔔 *TIPS:* 58 | Run '\`touch ${CONTINUE_FILE}\`' to continue to the next step. 59 | " 60 | 61 | if [[ -n "${TELEGRAM_BOT_TOKEN}" && -n "${TELEGRAM_CHAT_ID}" ]]; then 62 | echo -e "${INFO} Sending message to Telegram..." 63 | curl -sSX POST "${TELEGRAM_API_URL:-https://api.telegram.org}/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ 64 | -d "disable_web_page_preview=true" \ 65 | -d "parse_mode=Markdown" \ 66 | -d "chat_id=${TELEGRAM_CHAT_ID}" \ 67 | -d "text=${MSG}" >${TELEGRAM_LOG} 68 | TELEGRAM_STATUS=$(cat ${TELEGRAM_LOG} | jq -r .ok) 69 | if [[ ${TELEGRAM_STATUS} != true ]]; then 70 | echo -e "${ERROR} Telegram message sending failed: $(cat ${TELEGRAM_LOG})" 71 | else 72 | echo -e "${INFO} Telegram message sent successfully!" 73 | fi 74 | fi 75 | 76 | while ((${PRT_COUNT:=1} <= ${PRT_TOTAL:=10})); do 77 | SECONDS_LEFT=${PRT_INTERVAL_SEC:=10} 78 | while ((${PRT_COUNT} > 1)) && ((${SECONDS_LEFT} > 0)); do 79 | echo -e "${INFO} (${PRT_COUNT}/${PRT_TOTAL}) Please wait ${SECONDS_LEFT}s ..." 80 | sleep 1 81 | SECONDS_LEFT=$((${SECONDS_LEFT} - 1)) 82 | done 83 | echo "-----------------------------------------------------------------------------------" 84 | echo "To connect to this session copy and paste the following into a terminal or browser:" 85 | echo -e "CLI: ${Green_font_prefix}${TMATE_SSH}${Font_color_suffix}" 86 | echo -e "URL: ${Green_font_prefix}${TMATE_WEB}${Font_color_suffix}" 87 | echo -e "TIPS: Run 'touch ${CONTINUE_FILE}' to continue to the next step." 88 | echo "-----------------------------------------------------------------------------------" 89 | PRT_COUNT=$((${PRT_COUNT} + 1)) 90 | done 91 | 92 | while [[ -S ${TMATE_SOCK} ]]; do 93 | sleep 1 94 | if [[ -e ${CONTINUE_FILE} ]]; then 95 | echo -e "${INFO} Continue to the next step." 96 | exit 0 97 | fi 98 | done 99 | 100 | # ref: https://github.com/csexton/debugger-action/blob/master/script.sh 101 | -------------------------------------------------------------------------------- /ngrok2actions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright (c) 2020 P3TERX 4 | # 5 | # This is free software, licensed under the MIT License. 6 | # See /LICENSE for more information. 7 | # 8 | # https://github.com/P3TERX/ssh2actions 9 | # File name:ngrok2actions.sh 10 | # Description: Connect to Github Actions VM via SSH by using ngrok 11 | # Version: 2.0 12 | # 13 | 14 | Green_font_prefix="\033[32m" 15 | Red_font_prefix="\033[31m" 16 | Green_background_prefix="\033[42;37m" 17 | Red_background_prefix="\033[41;37m" 18 | Font_color_suffix="\033[0m" 19 | INFO="[${Green_font_prefix}INFO${Font_color_suffix}]" 20 | ERROR="[${Red_font_prefix}ERROR${Font_color_suffix}]" 21 | LOG_FILE='/tmp/ngrok.log' 22 | TELEGRAM_LOG="/tmp/telegram.log" 23 | CONTINUE_FILE="/tmp/continue" 24 | 25 | if [[ -z "${NGROK_TOKEN}" ]]; then 26 | echo -e "${ERROR} Please set 'NGROK_TOKEN' environment variable." 27 | exit 2 28 | fi 29 | 30 | if [[ -z "${SSH_PASSWORD}" && -z "${SSH_PUBKEY}" && -z "${GH_SSH_PUBKEY}" ]]; then 31 | echo -e "${ERROR} Please set 'SSH_PASSWORD' environment variable." 32 | exit 3 33 | fi 34 | 35 | if [[ -n "$(uname | grep -i Linux)" ]]; then 36 | echo -e "${INFO} Install ngrok ..." 37 | curl -fsSL https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip -o ngrok.zip 38 | unzip ngrok.zip ngrok 39 | rm ngrok.zip 40 | chmod +x ngrok 41 | sudo mv ngrok /usr/local/bin 42 | ngrok -v 43 | elif [[ -n "$(uname | grep -i Darwin)" ]]; then 44 | echo -e "${INFO} Install ngrok ..." 45 | curl -fsSL https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-darwin-amd64.zip -o ngrok.zip 46 | unzip ngrok.zip ngrok 47 | rm ngrok.zip 48 | chmod +x ngrok 49 | sudo mv ngrok /usr/local/bin 50 | ngrok -v 51 | USER=root 52 | echo -e "${INFO} Set SSH service ..." 53 | echo 'PermitRootLogin yes' | sudo tee -a /etc/ssh/sshd_config >/dev/null 54 | sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist 55 | sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist 56 | else 57 | echo -e "${ERROR} This system is not supported!" 58 | exit 1 59 | fi 60 | 61 | if [[ -n "${SSH_PASSWORD}" ]]; then 62 | echo -e "${INFO} Set user(${USER}) password ..." 63 | echo -e "${SSH_PASSWORD}\n${SSH_PASSWORD}" | sudo passwd "${USER}" 64 | fi 65 | 66 | echo -e "${INFO} Start ngrok proxy for SSH port..." 67 | screen -dmS ngrok \ 68 | ngrok tcp 22 \ 69 | --log "${LOG_FILE}" \ 70 | --authtoken "${NGROK_TOKEN}" \ 71 | --region "${NGROK_REGION:-us}" 72 | 73 | while ((${SECONDS_LEFT:=10} > 0)); do 74 | echo -e "${INFO} Please wait ${SECONDS_LEFT}s ..." 75 | sleep 1 76 | SECONDS_LEFT=$((${SECONDS_LEFT} - 1)) 77 | done 78 | 79 | ERRORS_LOG=$(grep "command failed" ${LOG_FILE}) 80 | 81 | if [[ -e "${LOG_FILE}" && -z "${ERRORS_LOG}" ]]; then 82 | SSH_CMD="$(grep -oE "tcp://(.+)" ${LOG_FILE} | sed "s/tcp:\/\//ssh ${USER}@/" | sed "s/:/ -p /")" 83 | MSG=" 84 | *GitHub Actions - ngrok session info:* 85 | 86 | ⚡ *CLI:* 87 | \`${SSH_CMD}\` 88 | 89 | 🔔 *TIPS:* 90 | Run '\`touch ${CONTINUE_FILE}\`' to continue to the next step. 91 | " 92 | if [[ -n "${TELEGRAM_BOT_TOKEN}" && -n "${TELEGRAM_CHAT_ID}" ]]; then 93 | echo -e "${INFO} Sending message to Telegram..." 94 | curl -sSX POST "${TELEGRAM_API_URL:-https://api.telegram.org}/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ 95 | -d "disable_web_page_preview=true" \ 96 | -d "parse_mode=Markdown" \ 97 | -d "chat_id=${TELEGRAM_CHAT_ID}" \ 98 | -d "text=${MSG}" >${TELEGRAM_LOG} 99 | TELEGRAM_STATUS=$(cat ${TELEGRAM_LOG} | jq -r .ok) 100 | if [[ ${TELEGRAM_STATUS} != true ]]; then 101 | echo -e "${ERROR} Telegram message sending failed: $(cat ${TELEGRAM_LOG})" 102 | else 103 | echo -e "${INFO} Telegram message sent successfully!" 104 | fi 105 | fi 106 | while ((${PRT_COUNT:=1} <= ${PRT_TOTAL:=10})); do 107 | SECONDS_LEFT=${PRT_INTERVAL_SEC:=10} 108 | while ((${PRT_COUNT} > 1)) && ((${SECONDS_LEFT} > 0)); do 109 | echo -e "${INFO} (${PRT_COUNT}/${PRT_TOTAL}) Please wait ${SECONDS_LEFT}s ..." 110 | sleep 1 111 | SECONDS_LEFT=$((${SECONDS_LEFT} - 1)) 112 | done 113 | echo "------------------------------------------------------------------------" 114 | echo "To connect to this session copy and paste the following into a terminal:" 115 | echo -e "${Green_font_prefix}$SSH_CMD${Font_color_suffix}" 116 | echo -e "TIPS: Run 'touch ${CONTINUE_FILE}' to continue to the next step." 117 | echo "------------------------------------------------------------------------" 118 | PRT_COUNT=$((${PRT_COUNT} + 1)) 119 | done 120 | else 121 | echo "${ERRORS_LOG}" 122 | exit 4 123 | fi 124 | 125 | while [[ -n $(ps aux | grep ngrok) ]]; do 126 | sleep 1 127 | if [[ -e ${CONTINUE_FILE} ]]; then 128 | echo -e "${INFO} Continue to the next step." 129 | exit 0 130 | fi 131 | done 132 | 133 | # ref: https://gist.github.com/retyui/7115bb6acf151351a143ec8f96a7c561 134 | --------------------------------------------------------------------------------