Skip to content

Commit

Permalink
feat: initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
RafaelGSS committed May 21, 2024
1 parent ad0e079 commit 4b43e8e
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 0 deletions.
23 changes: 23 additions & 0 deletions .github/workflows/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: 'Runner Starter'
description: 'Turn on/off a self-hosted runner'
inputs:
instance_id:
description: 'ID of the EC2 instance to start OR the name of the scaling group to scale down'
required: true
action:
description: 'Define if I want to start or stop the runner'
required: true
aws_default_region:
description: 'AWS region to use'
required: true

runs:
using: "composite"
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Start/Stop Runner Instance
shell: bash
run: |
${GITHUB_ACTION_PATH}/instance_start_stop.bash --instance-id=${{ inputs.instance_id }} --action=${{ inputs.action }}
103 changes: 103 additions & 0 deletions .github/workflows/instance_start_stop.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/bin/bash

# Function to print messages in a fancy way
function printMessage {
local message="$1"
local type="$2"
local length=${#message}
local line=$(printf "%-${length}s" | tr ' ' '-')
echo ""
case "$type" in
"info")
echo -e "\033[1;34m$line\033[0m"
echo -e "\033[1;34m$message\033[0m"
echo -e "\033[1;34m$line\033[0m"
;;
"success")
echo -e "\033[1;32m$line\033[0m"
echo -e "\033[1;32m$message\033[0m"
echo -e "\033[1;32m$line\033[0m"
;;
"error")
echo -e "\033[1;31m$line\033[0m"
echo -e "\033[1;31m$message\033[0m"
echo -e "\033[1;31m$line\033[0m"
;;
*)
echo -e "\033[1;34m$line\033[0m"
echo -e "\033[1;34m$message\033[0m"
echo -e "\033[1;34m$line\033[0m"
;;
esac
echo ""
}

# Parse command line arguments
while [ $# -gt 0 ]; do
case "$1" in
--instance-id=*)
INSTANCE_ID="${1#*=}"
;;
--action=*)
ACTION="${1#*=}"
;;
*)
printMessage "Invalid argument: $1" "error"
exit 1
;;
esac
shift
done

# Check if instance ID is null
if [ -z "$INSTANCE_ID" ]; then
printMessage "--instance-id=XX-XXX is required" "error"
exit 1
fi

# Check if action is null
if [ -z "$ACTION" ]; then
printMessage "--action=start|stop is required" "error"
exit 1
fi

# Check if action is valid
if [ "$ACTION" != "start" ] && [ "$ACTION" != "stop" ]; then
printMessage "Invalid action: $ACTION" "error"
exit 1
fi

# Check if instance is stopped or started
INSTANCE_STATE=$(aws ec2 describe-instances --instance-ids "$INSTANCE_ID" --query "Reservations[].Instances[].State.Name" --output text)

if [ "$ACTION" = "start" ]; then
if [ "$INSTANCE_STATE" = "stopped" ]; then
INSTANCE_NAME=$(aws ec2 describe-instances --instance-ids "$INSTANCE_ID" --query "Reservations[].Instances[].Tags[?Key=='Name'].Value" --output text)
printMessage "Starting instance $INSTANCE_NAME ($INSTANCE_ID)..." "info"
aws ec2 start-instances --instance-ids "$INSTANCE_ID" >/dev/null
printMessage "Waiting for instance $INSTANCE_ID to start..." "info"
aws ec2 wait instance-running --instance-ids "$INSTANCE_ID"
printMessage "Instance $INSTANCE_ID is now running" "success"
elif [ "$INSTANCE_STATE" = "running" ]; then
INSTANCE_NAME=$(aws ec2 describe-instances --instance-ids "$INSTANCE_ID" --query "Reservations[].Instances[].Tags[?Key=='Name'].Value" --output text)
printMessage "Instance $INSTANCE_NAME ($INSTANCE_ID) is already running" "success"
else
printMessage "Instance $INSTANCE_ID is in an unknown state: $INSTANCE_STATE" "error"
exit 1
fi
elif [ "$ACTION" = "stop" ]; then
if [ "$INSTANCE_STATE" = "running" ]; then
INSTANCE_NAME=$(aws ec2 describe-instances --instance-ids "$INSTANCE_ID" --query "Reservations[].Instances[].Tags[?Key=='Name'].Value" --output text)
printMessage "Stopping instance $INSTANCE_NAME ($INSTANCE_ID)..." "info"
aws ec2 stop-instances --instance-ids "$INSTANCE_ID" >/dev/null
printMessage "Waiting for instance $INSTANCE_ID to stop..." "info"
aws ec2 wait instance-stopped --instance-ids "$INSTANCE_ID"
printMessage "Instance $INSTANCE_ID is now stopped" "success"
elif [ "$INSTANCE_STATE" = "stopped" ]; then
INSTANCE_NAME=$(aws ec2 describe-instances --instance-ids "$INSTANCE_ID" --query "Reservations[].Instances[].Tags[?Key=='Name'].Value" --output text)
printMessage "Instance $INSTANCE_NAME ($INSTANCE_ID) is already stopped" "success"
else
printMessage "Instance $INSTANCE_ID is in an unknown state: $INSTANCE_STATE" "error"
exit 1
fi
fi
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,31 @@ The runner is kept active every 2 days (to not be removed as a Github Runner) an
## Installation

TODO

## Usage

```yaml
steps:
# Configure AWS Credentials
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: us-west-2
role-to-assume: $ARN_IAM_ROLE

- name: Start Runner
uses: nodesource/aws-eco-runner@v1
with:
instance_id: $INSTANCE_ID
action: 'start'
aws_default_region: 'us-west-2'

...

- name: Stop Runner
uses: nodesource/aws-eco-runner@v1
with:
instance_id: $INSTANCE_ID
action: 'stop'
aws_default_region: 'us-west-2'
```
18 changes: 18 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: 'aws-eco-runner'
description: 'AWS Eco Runner is a solution designed to optimize the cost of using GitHub Actions runners on AWS. By automating the activation and deactivation of the instance, it ensures that you only incur costs when necessary'
author: 'NodeSource'

runs:
using: 'node20'
main: '.github/workflows/action.yml'

inputs:
instance_id:
description: 'ID of the EC2 instance to start OR the name of the scaling group to scale down'
required: true
action:
description: 'Define if I want to start or stop the runner'
required: true
aws_default_region:
description: 'AWS region to use'
required: true

0 comments on commit 4b43e8e

Please sign in to comment.