Skip to content

Commit 04da671

Browse files
author
Nguyen Huu Thuong
committed
initial ssh scp ssh action
1 parent de60e6d commit 04da671

File tree

9 files changed

+381
-0
lines changed

9 files changed

+381
-0
lines changed

.github/workflows/deploy.yml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: scp files
2+
on: [push]
3+
4+
jobs:
5+
build:
6+
name: Build
7+
runs-on: ubuntu-latest
8+
9+
steps:
10+
- name: checkout
11+
uses: actions/checkout@v1
12+
13+
- name: ssh scp ssh pipelines
14+
uses: cross-the-world/[email protected]
15+
env:
16+
WELCOME: "ssh scp ssh pipelines"
17+
LASTSSH: "Doing something after copying"
18+
with:
19+
host: {{ secrets.DC_HOST }}
20+
user: {{ secrets.DC_USER }}
21+
pass: {{ secrets.DC_PASS }}
22+
port: {{ secrets.DC_PORT }}
23+
connect_timeout: 10s
24+
first_ssh: |
25+
rm -rf /home/github/test
26+
ls -la \necho $WELCOME
27+
mkdir -p /home/github/test/test1 &&
28+
mkdir -p /home/github/test/test2 &&
29+
scp: |
30+
'./test/*' => /home/github/test/
31+
./test/test1* => /home/github/test/test1/
32+
./test/test*.csv => "/home/github/test/test2/"
33+
last_ssh: |
34+
echo $LASTSSH &&
35+
(mkdir test1/test || true)
36+
|| ls -la
37+
38+
- name: scp ssh pipelines
39+
uses: cross-the-world/[email protected]
40+
env:
41+
WELCOME: "scp ssh pipelines"
42+
with:
43+
host: {{ secrets.DC_HOST }}
44+
user: {{ secrets.DC_USER }}
45+
pass: {{ secrets.DC_PASS }}
46+
scp: |
47+
./test/test1* => /home/github/test/test1/
48+
./test/test*.csv => "/home/github/test/test2/"
49+
last_ssh: |
50+
echo $LASTSSH
51+
ls -la
52+
53+
- name: scp pipelines
54+
uses: cross-the-world/[email protected]
55+
env:
56+
WELCOME: "scp pipelines"
57+
with:
58+
host: {{ secrets.DC_HOST }}
59+
user: {{ secrets.DC_USER }}
60+
pass: {{ secrets.DC_PASS }}
61+
scp: |
62+
'./test/*' => /home/github/test/

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.idea
2+
3+
test.sh
4+
.env

Dockerfile

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
FROM alpine:latest
2+
3+
LABEL "maintainer"="Scott Ng <[email protected]>"
4+
LABEL "repository"="https://github.com/cross-the-world/ssh-scp-ssh-pipelines"
5+
LABEL "version"="1.0.0"
6+
7+
LABEL "com.github.actions.name"="ssh-scp-ssh-pipelines"
8+
LABEL "com.github.actions.description"="Pipelines: ssh -> scp -> ssh"
9+
LABEL "com.github.actions.icon"="terminal"
10+
LABEL "com.github.actions.color"="gray-dark"
11+
12+
RUN apk update && \
13+
apk add ca-certificates && \
14+
apk add --no-cache openssh-client openssl openssh sshpass && \
15+
apk add --no-cache --upgrade bash openssh sshpass && \
16+
rm -rf /var/cache/apk/*
17+
18+
COPY entrypoint.sh /entrypoint.sh
19+
COPY test /opt/test
20+
RUN chmod +x /entrypoint.sh
21+
22+
ENTRYPOINT ["/entrypoint.sh"]

README.md

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# SSH SCP SSH Pipelines
2+
3+
Credit to [SSH SCP Action of Ali Najafizadeh](https://github.com/alinz/ssh-scp-action)
4+
5+
This action allows doing
6+
1. ssh
7+
2. scp
8+
3. ssh
9+
10+
## Inputs
11+
see the [action.yml](./action.yml) file for more detail imformation.
12+
13+
### `host`
14+
15+
**Required** ssh remote host.
16+
17+
### `port`
18+
19+
**NOT Required** ssh remote port. Default 22
20+
21+
### `user`
22+
23+
**Required** ssh remote user.
24+
25+
### `pass`
26+
27+
**NOT Required** ssh remote pass.
28+
29+
### `key`
30+
31+
**NOT Required** ssh remote key as string.
32+
33+
### `connect_timeout`
34+
35+
**NOT Required** connection timeout to remote host. Default 30s
36+
37+
### `first_ssh`
38+
39+
**NOT Required** execute pre-commands before scp.
40+
41+
### `scp`
42+
43+
**NOT Required** scp from local to remote.
44+
45+
**Syntax**
46+
local_path => remote_path
47+
e.g.
48+
/opt/test/* => /home/github/test
49+
50+
### `last_ssh`
51+
52+
**NOT Required** execute pre-commands after scp.
53+
54+
55+
## Usages
56+
57+
#### ssh scp ssh pipelines
58+
```yaml
59+
- name: ssh scp ssh pipelines
60+
uses: cross-the-world/[email protected]
61+
env:
62+
WELCOME: "ssh scp ssh pipelines"
63+
LASTSSH: "Doing something after copying"
64+
with:
65+
host: {{ secrets.DC_HOST }}
66+
user: {{ secrets.DC_USER }}
67+
pass: {{ secrets.DC_PASS }}
68+
port: {{ secrets.DC_PORT }}
69+
connect_timeout: 10s
70+
first_ssh: |
71+
rm -rf /home/github/test
72+
ls -la \necho $WELCOME
73+
mkdir -p /home/github/test/test1 &&
74+
mkdir -p /home/github/test/test2 &&
75+
scp: |
76+
'./test/*' => /home/github/test/
77+
./test/test1* => /home/github/test/test1/
78+
./test/test*.csv => "/home/github/test/test2/"
79+
last_ssh: |
80+
echo $LASTSSH &&
81+
(mkdir test1/test || true)
82+
|| ls -la
83+
```
84+
85+
#### scp ssh pipelines
86+
```yaml
87+
- name: scp ssh pipelines
88+
uses: cross-the-world/[email protected]
89+
env:
90+
LASTSSH: "Doing something after copying"
91+
with:
92+
host: {{ secrets.DC_HOST }}
93+
user: {{ secrets.DC_USER }}
94+
pass: {{ secrets.DC_PASS }}
95+
scp: |
96+
./test/test1* => /home/github/test/test1/
97+
./test/test*.csv => "/home/github/test/test2/"
98+
last_ssh: |
99+
echo $LASTSSH
100+
ls -la
101+
```
102+
103+
#### scp pipelines
104+
```yaml
105+
- name: scp pipelines
106+
uses: cross-the-world/[email protected]
107+
with:
108+
host: {{ secrets.DC_HOST }}
109+
user: {{ secrets.DC_USER }}
110+
pass: {{ secrets.DC_PASS }}
111+
scp: |
112+
'./test/*' => /home/github/test/
113+
```
114+
115+

action.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: 'ssh-scp-ssh-pipelines'
2+
description: 'Pipelines: ssh -> scp -> ssh'
3+
author: 'Scott Ng'
4+
inputs:
5+
host:
6+
description: 'ssh remote host'
7+
required: true
8+
port:
9+
description: 'ssh remote port'
10+
default: 22
11+
user:
12+
description: 'ssh remote user'
13+
required: true
14+
key:
15+
description: 'content of ssh private key. ex raw content of ~/.ssh/id_rsa'
16+
required: false
17+
pass:
18+
description: 'ssh remote password'
19+
required: false
20+
connect_timeout:
21+
description: 'connection timeout to remote host'
22+
default: "30s"
23+
required: false
24+
first_ssh:
25+
description: 'execute pre-commands before scp'
26+
required: false
27+
scp:
28+
description: 'scp from local to remote'
29+
required: false
30+
last_ssh:
31+
description: 'execute post-commands after scp'
32+
required: false
33+
runs:
34+
using: 'docker'
35+
image: 'Dockerfile'
36+
branding:
37+
icon: 'terminal'
38+
color: 'gray-dark'

entrypoint.sh

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
createKeyFile() {
6+
local SSH_PATH="$HOME/.ssh"
7+
8+
mkdir -p "$SSH_PATH"
9+
touch "$SSH_PATH/known_hosts"
10+
11+
echo "$INPUT_KEY" > "$SSH_PATH/id_rsa"
12+
13+
chmod 700 "$SSH_PATH"
14+
chmod 600 "$SSH_PATH/known_hosts"
15+
chmod 600 "$SSH_PATH/id_rsa"
16+
17+
eval $(ssh-agent)
18+
ssh-add "$SSH_PATH/id_rsa"
19+
20+
ssh-keyscan -t rsa "$INPUT_HOST" >> "$SSH_PATH/known_hosts"
21+
}
22+
23+
executeSSH() {
24+
local USEPASS=$1
25+
local LINES=$(echo -e $2)
26+
local COMMAND=""
27+
28+
# holds all commands separated by semi-colon or keep "&&"
29+
local COMMANDS=""
30+
31+
# this while read each commands in line and
32+
# evaluate each line against all environment variables
33+
while IFS=$'\n' read -r LINE; do
34+
LINE=$(echo $LINE)
35+
COMBINE="&&"
36+
LASTCOMBINE="&&"
37+
if [[ $LINE =~ ^.*\&\&$ ]]; then
38+
LINE="$LINE true"
39+
elif [[ $LINE =~ ^\&\&.*$ ]]; then
40+
LINE="true $LINE"
41+
elif [[ $LINE =~ ^.*\|\|$ ]]; then
42+
LINE="$LINE false"
43+
LASTCOMBINE="||"
44+
elif [[ $LINE =~ ^\|\|.*$ ]]; then
45+
LINE="false $LINE"
46+
COMBINE="||"
47+
fi
48+
LINE=$(eval 'echo "$LINE"')
49+
LINE=$(eval echo "$LINE")
50+
LINE="$LINE $LASTCOMBINE"
51+
52+
if [ -z "$COMMANDS" ]; then
53+
COMMANDS="$LINE"
54+
else
55+
# ref. https://unix.stackexchange.com/questions/459923/multiple-commands-in-sshpass
56+
if [[ $COMMANDS =~ ^.*\&\&$ ]] || [[ $COMMANDS =~ ^.*\|\|$ ]]; then
57+
COMMANDS="$COMMANDS $LINE"
58+
else
59+
COMMANDS="$COMMANDS $COMBINE $LINE"
60+
fi
61+
fi
62+
done <<< "$LINES"
63+
64+
if [[ $COMMANDS =~ ^.*\&\&$ ]]; then
65+
COMMANDS="$COMMANDS true"
66+
elif [[ $COMMANDS =~ ^.*\|\|$ ]]; then
67+
COMMANDS="$COMMANDS false"
68+
fi
69+
echo "$COMMANDS"
70+
71+
CMD="ssh"
72+
if $USEPASS; then
73+
CMD="sshpass -p $INPUT_PASS ssh"
74+
fi
75+
$CMD -o StrictHostKeyChecking=no -o ConnectTimeout=${INPUT_CONNECT_TIMEOUT:-30s} -p "${INPUT_PORT:-22}" "$INPUT_USER"@"$INPUT_HOST" "$COMMANDS" > /dev/stdout
76+
}
77+
78+
executeSCP() {
79+
local USEPASS=$1
80+
local LINES=$(echo -e $2)
81+
local COMMAND=
82+
83+
CMD="scp"
84+
if $USEPASS; then
85+
CMD="sshpass -p $INPUT_PASS scp"
86+
fi
87+
88+
while IFS=$'\n' read -r LINE; do
89+
delimiter="=>"
90+
LINE=`echo $LINE`
91+
s=$LINE$delimiter
92+
arr=()
93+
while [[ $s ]]; do
94+
arr+=( "${s%%"$delimiter"*}" );
95+
s=${s#*"$delimiter"};
96+
done;
97+
LOCAL=$(eval 'echo "${arr[0]}"')
98+
LOCAL=$(eval echo "$LOCAL")
99+
REMOTE=$(eval 'echo "${arr[1]}"')
100+
REMOTE=$(eval echo "$REMOTE")
101+
102+
if [[ -z "${LOCAL}" ]] || [[ -z "${REMOTE}" ]]; then
103+
echo "LOCAL/REMOTE can not be parsed $LINE"
104+
else
105+
echo "Copying $LOCAL ---> $REMOTE"
106+
$CMD -r -o StrictHostKeyChecking=no -o ConnectTimeout=${INPUT_CONNECT_TIMEOUT:-30s} -P "${INPUT_PORT:-22}" $LOCAL "$INPUT_USER"@"$INPUT_HOST":$REMOTE > /dev/stdout
107+
fi
108+
done <<< "$LINES"
109+
}
110+
111+
112+
######################################################################################
113+
114+
echo "+++++++++++++++++++STARTING PIPELINES+++++++++++++++++++"
115+
116+
USEPASS=true
117+
if [[ -z "${INPUT_KEY}" ]]; then
118+
echo "+++++++++++++++++++Use password+++++++++++++++++++"
119+
else
120+
echo "+++++++++++++++++++Create Key File+++++++++++++++++++"
121+
USEPASS=false
122+
createKeyFile || false
123+
fi
124+
125+
if ! [[ -z "${INPUT_FIRST_SSH}" ]]; then
126+
echo "+++++++++++++++++++Step 1: RUNNING SSH+++++++++++++++++++"
127+
executeSSH "$USEPASS" "$INPUT_FIRST_SSH" || false
128+
fi
129+
130+
if ! [[ -z "${INPUT_SCP}" ]]; then
131+
echo "+++++++++++++++++++Step 2: RUNNING SCP+++++++++++++++++++"
132+
executeSCP "$USEPASS" "$INPUT_SCP" || false
133+
fi
134+
135+
if ! [[ -z "${INPUT_LAST_SSH}" ]]; then
136+
echo "+++++++++++++++++++Step 3: RUNNING SSH+++++++++++++++++++"
137+
executeSSH "$USEPASS" "$INPUT_LAST_SSH" || false
138+
fi
139+
140+
echo "+++++++++++++++++++END PIPELINES+++++++++++++++++++"

test/test1.csv

Whitespace-only changes.

test/test1.txt

Whitespace-only changes.

test/test2.csv

Whitespace-only changes.

0 commit comments

Comments
 (0)