diff --git a/README.md b/README.md
index 16966ffe..fe8fd8aa 100644
--- a/README.md
+++ b/README.md
@@ -217,7 +217,7 @@ Now you're ready to go!
| `runner-home-dir` | Optional. Used only with the `start` mode. | Specifies a directory where pre-installed actions-runner software and scripts are located.
|
| `pre-runner-script` | Optional. Used only with the `start` mode. | Specifies bash commands to run before the runner starts. It's useful for installing dependencies with apt-get, yum, dnf, etc. For example:
- name: Start EC2 runner
with:
mode: start
...
pre-runner-script: \|
sudo yum update -y && \
sudo yum install docker git libicu -y
sudo systemctl enable docker
|
| `market-type` | Optional. Used only with the `start` mode. | This field accepts only the value `spot`.
If set to `spot`, the runner will be launched as a Spot instance.
If omitted, the runner will be launched as an on-demand instance. |
-| `block-device-mappings` | Optional. Used only with the `start` mode. | JSON string specifying the block device mappings for the EC2 instance. For example:
[{"DeviceName": "/dev/sda1", "Ebs": {"VolumeSize": 100, "VolumeType": "gp3"}}] See AWS BlockDeviceMapping docs for all options. |
+| `block-device-mappings` | Optional. Used only with the `start` mode. | JSON string specifying the block device mappings for the EC2 instance. For example:
[{"DeviceName": "/dev/sda1", "Ebs": {"VolumeSize": 100, "VolumeType": "gp3"}}] See AWS BlockDeviceMapping docs for all options.
**Note on EBS Volume Deletion**: All EBS volumes are automatically configured with `DeleteOnTermination: true` to prevent orphaned volumes and unexpected costs. The action will add this property to any volume that doesn't explicitly set it. If you explicitly set `DeleteOnTermination: false`, that setting will be respected. |
| `startup-quiet-period-seconds` | Optional | Default: 30 |
| `startup-retry-interval-seconds` | Optional | Default: 10 |
| `startup-timeout-minutes` | Optional | Default: 5 |
@@ -286,6 +286,8 @@ jobs:
[
{"DeviceName": "/dev/sda1", "Ebs": {"VolumeSize": 100, "VolumeType": "gp3"}}
]
+ # Note: To preserve a volume after instance termination, explicitly set DeleteOnTermination: false:
+ # {"DeviceName": "/dev/sdb", "Ebs": {"VolumeSize": 50, "DeleteOnTermination": false}}
do-the-job:
name: Do the job on the runner
needs: start-runner # required to start the main job when the runner is ready
diff --git a/dist/index.js b/dist/index.js
index 7e20435b..85a87a9a 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -145115,6 +145115,38 @@ function buildMarketOptions() {
};
}
+/**
+ * Ensures all block device mappings have DeleteOnTermination set to true.
+ * Respects explicit user settings if DeleteOnTermination is already defined.
+ *
+ * @param {Array} blockDeviceMappings - Array of BlockDeviceMapping objects
+ * @returns {Array} Modified array with DeleteOnTermination set appropriately
+ */
+function ensureDeleteOnTermination(blockDeviceMappings) {
+ if (!Array.isArray(blockDeviceMappings) || blockDeviceMappings.length === 0) {
+ return blockDeviceMappings;
+ }
+
+ return blockDeviceMappings.map(mapping => {
+ // Create a shallow copy to avoid mutating the original
+ const modifiedMapping = { ...mapping };
+
+ // Only process if the mapping has an Ebs configuration
+ if (modifiedMapping.Ebs) {
+ // Create a shallow copy of the Ebs object
+ modifiedMapping.Ebs = { ...modifiedMapping.Ebs };
+
+ // Only set DeleteOnTermination if it's not already explicitly defined
+ // This respects user's explicit choice if they set it to false
+ if (modifiedMapping.Ebs.DeleteOnTermination === undefined) {
+ modifiedMapping.Ebs.DeleteOnTermination = true;
+ }
+ }
+
+ return modifiedMapping;
+ });
+}
+
async function createEc2InstanceWithParams(imageId, subnetId, securityGroupId, label, githubRegistrationToken, region) {
// Region is always specified now, so we can directly use it
const ec2ClientOptions = { region };
@@ -145143,13 +145175,14 @@ async function createEc2InstanceWithParams(imageId, subnetId, securityGroupId, l
Ebs: {
...(config.input.ec2VolumeSize !== '' && { VolumeSize: config.input.ec2VolumeSize }),
...(config.input.ec2VolumeType !== '' && { VolumeType: config.input.ec2VolumeType }),
+ DeleteOnTermination: true,
},
},
];
}
if (config.input.blockDeviceMappings.length > 0) {
- params.BlockDeviceMappings = config.input.blockDeviceMappings;
+ params.BlockDeviceMappings = ensureDeleteOnTermination(config.input.blockDeviceMappings);
}
const result = await ec2.send(new RunInstancesCommand(params));
diff --git a/src/aws.js b/src/aws.js
index 80afacfa..afe5a29c 100644
--- a/src/aws.js
+++ b/src/aws.js
@@ -107,6 +107,38 @@ function buildMarketOptions() {
};
}
+/**
+ * Ensures all block device mappings have DeleteOnTermination set to true.
+ * Respects explicit user settings if DeleteOnTermination is already defined.
+ *
+ * @param {Array} blockDeviceMappings - Array of BlockDeviceMapping objects
+ * @returns {Array} Modified array with DeleteOnTermination set appropriately
+ */
+function ensureDeleteOnTermination(blockDeviceMappings) {
+ if (!Array.isArray(blockDeviceMappings) || blockDeviceMappings.length === 0) {
+ return blockDeviceMappings;
+ }
+
+ return blockDeviceMappings.map(mapping => {
+ // Create a shallow copy to avoid mutating the original
+ const modifiedMapping = { ...mapping };
+
+ // Only process if the mapping has an Ebs configuration
+ if (modifiedMapping.Ebs) {
+ // Create a shallow copy of the Ebs object
+ modifiedMapping.Ebs = { ...modifiedMapping.Ebs };
+
+ // Only set DeleteOnTermination if it's not already explicitly defined
+ // This respects user's explicit choice if they set it to false
+ if (modifiedMapping.Ebs.DeleteOnTermination === undefined) {
+ modifiedMapping.Ebs.DeleteOnTermination = true;
+ }
+ }
+
+ return modifiedMapping;
+ });
+}
+
async function createEc2InstanceWithParams(imageId, subnetId, securityGroupId, label, githubRegistrationToken, region) {
// Region is always specified now, so we can directly use it
const ec2ClientOptions = { region };
@@ -135,13 +167,14 @@ async function createEc2InstanceWithParams(imageId, subnetId, securityGroupId, l
Ebs: {
...(config.input.ec2VolumeSize !== '' && { VolumeSize: config.input.ec2VolumeSize }),
...(config.input.ec2VolumeType !== '' && { VolumeType: config.input.ec2VolumeType }),
+ DeleteOnTermination: true,
},
},
];
}
if (config.input.blockDeviceMappings.length > 0) {
- params.BlockDeviceMappings = config.input.blockDeviceMappings;
+ params.BlockDeviceMappings = ensureDeleteOnTermination(config.input.blockDeviceMappings);
}
const result = await ec2.send(new RunInstancesCommand(params));