You can choose to write your GitHub actions using either Docker or JavaScript. The action.yml file describes your action and is called metadata file and uses the metadata syntax for GitHub Actions.

Docker and JavaScript actions require a metadata file. The metadata filename must be either action.yml or action.yaml. The data in the metadata file defines the inputs, outputs and main entrypoint for your action (about YAML syntax for GitHub Actions).

Deploy with scp (Docker Action)

This action uses a Docker container to copy files with scp.

The Dockerfile executes entrypoint.sh and this script executes sshpass with the values of the input fields which are declared in the action.yml metadata file.

Set the values for runs: in your action.yml to specify which Dockerfile to use

runs:
  using: "docker"
  image: "Dockerfile"

Dockerfile

FROM alpine:3.11.6
RUN apk add --update openssh sshpass
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x entrypoint.sh
ENTRYPOINT [ "/entrypoint.sh" ]

To access the value of an input field inside your entrypoint.sh you have to add the prefix $INPUT_ and use uppercase letters.

entrypoint.sh

#!/bin/sh -l
export SSHPASS=$INPUT_PASSWORD
sshpass -e scp -r -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $INPUT_SOURCE $INPUT_USERNAME@$INPUT_HOSTNAME:$INPUT_TARGET

This is a private action, because of this we have to use the path to the location of the action in this repository

uses: ./.github/actions/deploy-with-scp-docker
with:
  hostname: ${{ secrets.HOSTNAME }}
  username: ${{ secrets.USERNAME }}
  password: ${{ secrets.PASSWORD }}
  source: "."
  target: ${{ secrets.TARGET }}

For more information checkout the documentation about creating a Docker container action and the documentation about Dockerfile support.

Deploy with sftp (JavaScript Action)

This action uses Node.js to copy files with sftp.

The index.js uses the ssh2-sftp-client package with the input fields which are declared in the _action.yml_ metadata file to upload files with sftp.

Set the values for runs: in your action.yml to specify which JavaScript file to execute. We use the deploy-with-sftp-javascript/dist/index.js file because the deploy-with-sftp-javascript/index.js file got compiled using @zeit/ncc.

As an alternative to checking in your node_modules directory you can use a tool called zeit/ncc to compile your code and modules into one file used for distribution (commit, tag and push your action to GitHub documentation).

runs:
  using: "node12"
  main: "dist/index.js"

To access the value of an input field inside your index.js you have to use the @actions/core package.

index.js

const core = require("@actions/core");
const SftpClient = require("ssh2-sftp-client");

async function main() {
  const client = new SftpClient();
  const source = core.getInput("source");
  const target = core.getInput("target");
  const sftpConfig = {
    host: core.getInput("hostname"),
    username: core.getInput("username"),
    password: core.getInput("password"),
  };

  try {
    await client.connect(sftpConfig);
    client.on("upload", (info) => {
      console.log(`Uploaded ${info.source}`);
    });
    return await client.uploadDir(source, target);
  } finally {
    client.end();
  }
}

main()
  .then((msg) => {
    console.log(msg);
  })
  .catch((err) => {
    core.setFailed(err.message);
  });

This is a private action, because of this we have to use the path to the location of the action in this repository. You can set secrets in the settings page of your repository.

uses: ./.github/actions/deploy-with-sftp-javascript
with:
  hostname: ${{ secrets.HOSTNAME }}
  username: ${{ secrets.USERNAME }}
  password: ${{ secrets.PASSWORD }}
  source: "."
  target: ${{ secrets.TARGET }}

For more information checkout the documentation about creating a JavaScript container action and the GitHub Actions Toolkit is a really great collections of useful packages for developing GitHub JavaScript actions.

Usage in GitHub workflow

name: CI

on:
  push:
    branches: [master]
  pull_request:
    branches: [master]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2

      - name: Deploy with sftp JavaScript
        uses: ./.github/actions/deploy-with-sftp-javascript
        with:
          hostname: ${{ secrets.HOSTNAME }}
          username: ${{ secrets.USERNAME }}
          password: ${{ secrets.PASSWORD }}
          source: "./files-to-upload"
          target: "./html/javascript-action"

      - name: Deploy with scp Docker
        uses: ./.github/actions/deploy-with-scp-docker
        with:
          hostname: ${{ secrets.HOSTNAME }}
          username: ${{ secrets.USERNAME }}
          password: ${{ secrets.PASSWORD }}
          source: "./files-to-upload"
          target: "./html/docker-action"

The source code is available on GitHub.