Bootstrap FreeKB - GitHub Actions - Upload file using SCP
GitHub Actions - Upload file using SCP

Updated:   |  GitHub Actions articles

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.

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 Buy Me A Coffee



Comments


Add a Comment


Please enter be6014 in the box below so that we can be sure you are a human.