diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..bd2927a --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,36 @@ +name: scp pipeline +on: + push: + branches: + - master + +jobs: + build: + name: Build + runs-on: ubuntu-latest + + steps: + - name: checkout + uses: actions/checkout@v1 + + - name: scp pipeline + uses: cross-the-world/scp-pipeline@master + with: + host: ${{ secrets.DC_HOST }} + user: ${{ secrets.DC_USER }} + pass: ${{ secrets.DC_PASS }} + port: ${{ secrets.DC_PORT }} + connect_timeout: 10s + local: './test/*' + remote: /home/github/test/ + scp: | + ./test/test*.csv => "/home/github/test/test2/" + + - name: local remote scp + uses: cross-the-world/scp-pipeline@master + with: + host: ${{ secrets.DC_HOST }} + user: ${{ secrets.DC_USER }} + pass: ${{ secrets.DC_PASS }} + local: "./test/test1*" + remote: /home/github/test/test1/ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..043359d --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.idea + +test.sh +.env \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..cafb10f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +FROM alpine:latest + +LABEL "maintainer"="Scott Ng " +LABEL "repository"="https://github.com/cross-the-world/scp-pipeline" +LABEL "version"="1.0.0" + +LABEL "com.github.actions.name"="scp-pipeline" +LABEL "com.github.actions.description"="Pipeline: scp" +LABEL "com.github.actions.icon"="copy" +LABEL "com.github.actions.color"="gray-dark" + +RUN apk update && \ + apk add ca-certificates && \ + apk add --no-cache openssh-client openssl openssh sshpass && \ + apk add --no-cache --upgrade bash openssh sshpass && \ + rm -rf /var/cache/apk/* + +COPY entrypoint.sh /entrypoint.sh +COPY test /opt/test +RUN chmod +x /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/README.md b/README.md index 3fd7953..b4e1057 100644 --- a/README.md +++ b/README.md @@ -1 +1,85 @@ -# scp-pipeline \ No newline at end of file +# SCP Pipeline + +[Github actions](https://help.github.com/en/actions/creating-actions/creating-a-docker-container-action) + +This action allows copying per scp +* scp if defined +* local -> remote if defined + +## Inputs +see the [action.yml](./action.yml) file for more detail imformation. + +### `host` + +**Required** ssh remote host. + +### `port` + +**NOT Required** ssh remote port. Default 22 + +### `user` + +**Required** ssh remote user. + +### `pass` + +**NOT Required** ssh remote pass. + +### `key` + +**NOT Required** ssh remote key as string. + +### `connect_timeout` + +**NOT Required** connection timeout to remote host. Default 30s + +### `local` + +**NOT Required** execute pre-commands before scp. + +### `remote` + +**NOT Required** execute pre-commands after scp. + +### `scp` + +**NOT Required** scp from local to remote. + +**Syntax** +local_path => remote_path +e.g. +/opt/test/* => /home/github/test + + +## Usages +see the [deploy.yml](./.github/workflows/deploy.yml) file for more detail imformation. + +#### scp pipeline +```yaml +- name: scp pipeline + uses: cross-the-world/scp-pipeline@master + with: + host: ${{ secrets.DC_HOST }} + user: ${{ secrets.DC_USER }} + pass: ${{ secrets.DC_PASS }} + port: ${{ secrets.DC_PORT }} + connect_timeout: 10s + local: './test/*' + remote: /home/github/test/ + scp: | + ./test/test*.csv => "/home/github/test/test2/" +``` + +#### local remote scp +```yaml +- name: local remote scp + uses: cross-the-world/scp-pipeline@master + with: + host: ${{ secrets.DC_HOST }} + user: ${{ secrets.DC_USER }} + pass: ${{ secrets.DC_PASS }} + local: "./test/test1*" + remote: /home/github/test/test1/ +``` + + diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..e7040ff --- /dev/null +++ b/action.yml @@ -0,0 +1,38 @@ +name: 'scp-pipeline' +description: 'Pipeline: scp' +author: 'Scott Ng' +inputs: + host: + description: 'ssh remote host' + required: true + port: + description: 'ssh remote port' + default: 22 + user: + description: 'ssh remote user' + required: true + key: + description: 'content of ssh private key. ex raw content of ~/.ssh/id_rsa' + required: false + pass: + description: 'ssh remote password' + required: false + connect_timeout: + description: 'connection timeout to remote host' + default: "30s" + required: false + local: + description: 'source to copy' + required: false + remote: + description: 'destination for copy' + required: false + scp: + description: 'scp from local to remote' + required: false +runs: + using: 'docker' + image: 'Dockerfile' +branding: + icon: 'copy' + color: 'gray-dark' \ No newline at end of file diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..5319ff5 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,83 @@ +#!/bin/bash + +set -e + +createKeyFile() { + local SSH_PATH="$HOME/.ssh" + + mkdir -p "$SSH_PATH" + touch "$SSH_PATH/known_hosts" + + echo "$INPUT_KEY" > "$SSH_PATH/id_rsa" + + chmod 700 "$SSH_PATH" + chmod 600 "$SSH_PATH/known_hosts" + chmod 600 "$SSH_PATH/id_rsa" + + eval $(ssh-agent) + ssh-add "$SSH_PATH/id_rsa" + + ssh-keyscan -t rsa "$INPUT_HOST" >> "$SSH_PATH/known_hosts" +} + +executeSCP() { + local USEPASS=$1 + local LINES=$2 + local COMMAND= + + CMD="scp" + if $USEPASS; then + CMD="sshpass -p $INPUT_PASS scp" + fi + + while IFS= read -r LINE; do + delimiter="=>" + LINE=$(echo $LINE) + if [[ -z "${LINE}" ]]; then + continue + fi + s=$LINE$delimiter + arr=() + while [[ $s ]]; do + arr+=( "${s%%"$delimiter"*}" ); + s=${s#*"$delimiter"}; + done; + LOCAL=$(eval 'echo "${arr[0]}"') + LOCAL=$(eval echo "$LOCAL") + REMOTE=$(eval 'echo "${arr[1]}"') + REMOTE=$(eval echo "$REMOTE") + + if [[ -z "${LOCAL}" ]] || [[ -z "${REMOTE}" ]]; then + echo "LOCAL/REMOTE can not be parsed $LINE" + else + echo "Copying $LOCAL ---> $REMOTE" + $CMD -r -o StrictHostKeyChecking=no -o ConnectTimeout=${INPUT_CONNECT_TIMEOUT:-30s} -P "${INPUT_PORT:-22}" $LOCAL "$INPUT_USER"@"$INPUT_HOST":$REMOTE > /dev/stdout + fi + done <<< "$LINES" +} + + +###################################################################################### + +echo "+++++++++++++++++++STARTING PIPELINES+++++++++++++++++++" + +USEPASS=true +if [[ -z "${INPUT_KEY}" ]]; then + echo "+++++++++++++++++++Use password+++++++++++++++++++" +else + echo "+++++++++++++++++++Create Key File+++++++++++++++++++" + USEPASS=false + createKeyFile || false +fi + +if ! [[ -z "${INPUT_LOCAL}" ]] && ! [[ -z "${INPUT_REMOTE}" ]]; then + echo "+++++++++++++++++++Pipeline: LOCAL -> REMOTE+++++++++++++++++++" + executeSCP "$USEPASS" "$INPUT_LOCAL => $INPUT_REMOTE" || false +fi + +if ! [[ -z "${INPUT_SCP}" ]]; then + echo "+++++++++++++++++++Pipeline: RUNNING SCP+++++++++++++++++++" + executeSCP "$USEPASS" "$INPUT_SCP" || false +fi + +echo "+++++++++++++++++++END PIPELINES+++++++++++++++++++" diff --git a/test/test1.csv b/test/test1.csv new file mode 100644 index 0000000..e69de29 diff --git a/test/test1.txt b/test/test1.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/test2.csv b/test/test2.csv new file mode 100644 index 0000000..e69de29