
GitHub Actions can be used to do something whenever something happens in one of your GitHub repositories. If you are not familiar with GitHub Actions, check out my article Getting Started with GitHub Actions.
Let's say you have a repository named my-repo that contains 2 files, foo.jpg and bar.jpg, perhaps like this.
- https://github.com/JohnDoe/my-repo/blob/main/images/foo.jpg
- https://github.com/JohnDoe/my-repo/blob/main/images/bar.jpg
Check out my article Public key authentication with OpenSSH on Linux for details on how to configure the target server to allow SSH connections.
You can SCP files using:
- The plain ole run command
- appleboy SCP action (this article)
appleboy/scp-action@master can be used to SCP one or more files in one of your GitHub repositories to one or more target servers. In this example the following secrets PASSWORD is created in your repository > Settings > Secrets and variables > Actions
name: GitHub Action
run-name: ${{ github.workflow }} run by ${{ github.actor }}
on:
push:
branches:
- main
jobs:
github-action-job:
runs-on: ubuntu-latest
steps:
- name: Checking out the repository code . . .
uses: actions/checkout@v4
- name: copy foo.jpg to /tmp
uses: appleboy/scp-action@master
with:
host: ec2-10-11-12-13.compute-1.amazonaws.com
username: ec2-user
password: ${{ secrets.PASSWORD}}
port: 22
source: "foo.jpg"
target: "/tmp"
Or, better yet, you can used a SSH keypair. At your repository > Settings > Secrets and variables > Actions, you would have a secret that contains the contents of the users SSH private key file on the target server, such as $HOME/.ssh/id_rsa or $HOME/.ssh/id_rsa.
And then you would use key: ${{ secrets.PRIVATE_KEY }}".
name: GitHub Action
run-name: ${{ github.workflow }} run by ${{ github.actor }}
on:
push:
branches:
- main
jobs:
github-action-job:
runs-on: ubuntu-latest
steps:
- name: Checking out the repository code . . .
uses: actions/checkout@v4
- name: copy foo.jpg to /tmp/foo.jpg on EC2 instance ec2-10-11-12-13.compute-1.amazonaws.com
uses: appleboy/scp-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.PRIVATE_KEY }}
port: ${{ secrets.PORT }}
source: "foo.jpg"
target: "/tmp"
If you are SCP a file to an Amazon Web Services (AWS) EC2 Instance, the Security Group will need to allow connections from GitHub on port 22. Here is how you can get the GitHub IP address and update the Security Group. Additionally, this uses truemark/aws-ec2-describe-instance-action to get the DNS name of the EC2 instance.
name: GitHub Action
run-name: ${{ github.workflow }} run by ${{ github.actor }}
on:
push:
branches:
- main
jobs:
github-action-job:
runs-on: ubuntu-latest
steps:
- name: Checking out the repository code . . .
uses: actions/checkout@v4
- name: Get Github action IP
id: ip
uses: haythem/public-ip@v1.3
- name: describe my-ec2-instance
id: my-ec2-instance
uses: truemark/aws-ec2-describe-instance-action@v2
with:
instance-id: i-123abc456def789gh
region: us-east-1
- name: echo my-ec2-instancepublic-dns-name
run: |
echo ${{ steps.my-ec2-instance.outputs.public-dns-name }}
- name: Update EC2 Security Group to allow connections on port 22 from GitHub
run: |
aws ec2 authorize-security-group-ingress --group-id sg-abcdefg123456789 --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32
- name: copy foo.jpg to /tmp/foo.jpg on EC2 instance ec2-10-11-12-13.compute-1.amazonaws.com
uses: appleboy/scp-action@master
with:
host: ${{ steps.my-ec2-instance.outputs.public-dns-name }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.RSA_PRIVATE_KEY }}
port: ${{ secrets.PORT }}
source: "foo.jpg"
target: "/tmp"
- name: Return EC2 Security Group to allow connections on port 22 from 10.11.12.13/32
run: |
aws ec2 authorize-security-group-ingress --group-id sg-abcdefg123456789 --protocol tcp --port 22 --cidr 10.11.12.13/32
Here is how you can first get the count of changed files and then only move onto the next job if the count of change files is greater than zero.
name: GitHub Action
run-name: ${{ github.workflow }} run by ${{ github.actor }}
on:
push:
branches:
- main
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
permissions:
id-token: write
contents: read
jobs:
get_changed_files:
runs-on: ubuntu-latest
steps:
- name: Checking out the repository code
uses: actions/checkout@v4
- name: Get changed files excluding README.md, github/workflows/main.yml, .png, .jpg and .jpeg files
id: changed-files
uses: tj-actions/changed-files@v40
with:
separator: ","
files: |
!README.md
!*.png
!*.jpg
!*.jpeg
!.github/workflows/main.yml
- name: changed files
run: |
echo "changed files = ${{ steps.changed-files.outputs.all_changed_files }}"
- name: changed files count
run: |
echo "changed files count = ${{ steps.changed-files.outputs.all_changed_files_count }}"
outputs:
changed_files_count: ${{ steps.changed-files.outputs.all_changed_files_count }}
deploy_changed_files:
name: SCP changed files from GitHub to EC2 instances
runs-on: ubuntu-latest
needs: get_changed_files
if: needs.get_changed_files.outputs.changed_files_count > 0
steps:
- name: Checking out the repository code
uses: actions/checkout@v4
- name: Get changed files excluding README.md, github/workflows/main.yml, .png, .jpg and .jpeg files
id: changed-files
uses: tj-actions/changed-files@v40
with:
separator: ","
files: |
!README.md
!*.png
!*.jpg
!*.jpeg
!.github/workflows/main.yml
- name: echo steps.changed-files.outputs.all_changed_files
run: |
echo "changed files = ${{ steps.changed-files.outputs.all_changed_files }}"
- name: aws-actions/configure-aws-credentials@v4
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubAction-AssumeRoleWithAction
role-session-name: GitHub_to_AWS_via_FederatedOIDC
aws-region: us-east-1
- name: Get Github action IP
id: ip
uses: haythem/public-ip@v1.3
- name: describe i-abc123efg456hij789ab
id: i-abc123efg456hij789ab
uses: truemark/aws-ec2-describe-instance-action@v2
with:
instance-id: i-abc123efg456hij789ab
region: us-east-1
- name: echo i-abc123efg456hij789ab public-dns-name
run: |
echo ${{ steps.i-abc123efg456hij789ab.outputs.public-dns-name }}
- name: Add Github Actions IP to Security group
run: |
aws ec2 authorize-security-group-ingress --group-id sg-abc123def456hij78912 --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32
- name: copy ${{steps.changed-files.outputs.all_changed_files}} to /tmp on EC2 instances
uses: appleboy/scp-action@master
with:
host: ${{ steps.i-abc123efg456hij789ab.outputs.public-dns-name }}
username: ec2-user
key: ${{ secrets.ED25519_PRIVATE_KEY }}
port: 22
source: "${{ steps.changed-files.outputs.all_changed_files }}"
target: /tmp
- name: Remove Github Actions IP from Security group
run: |
aws ec2 revoke-security-group-ingress --group-id sg-abc123def456hij78912 --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32
Did you find this article helpful?
If so, consider buying me a coffee over at