Skip to content

Feat: Add image tag support. #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ name: Test Compose Action
on:
workflow_dispatch:
push:
branches:
- main
paths:
- 'src/**'
- '.github/workflows/test.yml'
Expand Down Expand Up @@ -38,7 +36,23 @@ jobs:
organization: 'quant'
compose_file: 'docker-compose.yml'
base_url: 'https://portal.stage.quantcdn.io/api/v3'
image_tag_updates: '{"drupal": "v1.0.0"}'

- name: Debug output
run: |
echo "Compose file: ${{ steps.validate-compose-file.outputs.translated_compose }}"

- name: Validate image tag updates
run: |
# Parse the translated compose output
COMPOSE=$(echo '${{ steps.validate-compose-file.outputs.translated_compose }}')

# Check if drupal container has the correct tag
DRUPAL_TAG=$(echo "$COMPOSE" | jq -r '.containers[] | select(.name=="drupal") | .imageReference.identifier')

if [ "$DRUPAL_TAG" != "v1.0.0" ]; then
echo "Expected tag 'v1.0.0' for drupal container, but got '$DRUPAL_TAG'"
exit 1
fi

echo "✅ Image tag validation passed"
26 changes: 24 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,37 @@ Validate and prepare a translated docker compose specification to be used with o
organization: your-org-id
compose_file: path/to/docker-compose.yml
base_url: https://dashboard.quantcdn.io/api/v3 # Optional
image_tag_updates: '{"service1": "v1.0.0", "service2": "feature-x"}' # Optional
```

## Inputs

* `api_key`: Your Quant API key (required)
* `organization`: Your Quant organisation ID (required)
* `environment_name`: Name for the environment (required)
* `compose_file`: Path to your docker-compose file (required)
* `base_url`: Quant Cloud API URL (optional, defaults to https://dashboard.quantcdn.io/api/v3)
* `image_tag_updates`: JSON object mapping container names to new image tags (optional)

## Outputs

* `translated_compose`: Service definition to be used with other Quant Cloud actions.
* `translated_compose`: Service definition to be used with other Quant Cloud actions.

## Examples

### Updating image tags

You can update image tags for specific containers using the `image_tag_updates` input:

```yaml
- uses: quantcdn/quant-cloud-compose-action@v1
with:
api_key: ${{ secrets.QUANT_API_KEY }}
organization: your-org-id
compose_file: docker-compose.yml
image_tag_updates: '{"service1": "${{ steps.get-tag.outputs.tag }}"}'
```

This is useful when you want to:
- Use tags from previous steps
- Deploy feature branches
- Update specific services to different versions
3 changes: 3 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ inputs:
description: 'Quant Cloud API URL'
required: false
default: 'https://dashboard.quantcdn.io/api/v3'
image_tag_updates:
description: 'JSON object mapping container names to new image tags (e.g. {"service1": "v2", "service2": "feature-x"})'
required: false
outputs:
translated_compose:
description: 'The translated docker compose specification'
Expand Down
23 changes: 22 additions & 1 deletion dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -67565,6 +67565,7 @@ async function run() {
const apiKey = core.getInput('api_key', { required: true });
const org = core.getInput('organization', { required: true });
const composeFilePath = core.getInput('compose_file', { required: true });
const imageTagUpdatesStr = core.getInput('image_tag_updates', { required: false });
// Default to the public Quant Cloud API
const baseUrl = core.getInput('base_url', { required: false }) || 'https://dashboard.quantcdn.io/api/v3';
// Read the docker-compose file
Expand Down Expand Up @@ -67607,7 +67608,27 @@ async function run() {
core.setFailed('Compose file is invalid');
return;
}
const output = JSON.stringify(translatedCompose);
// Apply image tag updates if provided
if (imageTagUpdatesStr) {
core.info('Applying image tag updates');
try {
const imageTagUpdates = JSON.parse(imageTagUpdatesStr);
for (const container of translatedCompose.containers) {
if (container.name && imageTagUpdates[container.name]) {
const tag = imageTagUpdates[container.name];
core.info(`Updated image tag for container ${container.name} to ${tag}`);
container.imageReference = {
type: tag.includes(':') ? 'external' : 'internal',
identifier: tag
};
}
}
}
catch (error) {
core.warning('Failed to parse image tag updates, skipping tag updates');
}
}
const output = JSON.stringify(translatedCompose, null, 2);
core.setOutput('translated_compose', output);
core.info(`\n ✅ Successfully translated compose file`);
return;
Expand Down
45 changes: 37 additions & 8 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,40 @@
version: '3.8'

services:
php:
image: quant/portal-php:latest
restart: unless-stopped
drupal:
build:
context: .
dockerfile: ./dockerfiles/php.dockerfile
volumes:
- ./laravel-storage:/var/www/html/storage
env_file:
- .env
dockerfile: Dockerfile
ports:
- 80
volumes:
- drupal_data:/var/www/html/sites
depends_on:
- mariadb
environment:
- DRUPAL_DATABASE_HOST=mariadb
- DRUPAL_DATABASE_PORT_NUMBER=3306
- DRUPAL_DATABASE_NAME=drupal
- DRUPAL_DATABASE_USER=drupal
- DRUPAL_DATABASE_PASSWORD=drupal_password
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:80/"]
interval: 30s
timeout: 10s
retries: 3
start_period: 120s

mariadb:
image: mariadb:latest
volumes:
- mariadb_data:/var/lib/mysql
environment:
- MARIADB_DATABASE=drupal
- MARIADB_USER=drupal
- MARIADB_PASSWORD=drupal_password
- MARIADB_ROOT_PASSWORD=root_password
labels:
quant.type: none
volumes:
drupal_data:
mariadb_data:
28 changes: 27 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ interface ApiError {
}
}

interface ImageTagUpdates {
[key: string]: string;
}

const apiOpts = (apiKey: string) => {
return{
applyToRequest: (requestOptions: any) => {
Expand All @@ -28,6 +32,7 @@ async function run() {
const apiKey = core.getInput('api_key', { required: true });
const org = core.getInput('organization', { required: true });
const composeFilePath = core.getInput('compose_file', { required: true });
const imageTagUpdatesStr = core.getInput('image_tag_updates', { required: false });

// Default to the public Quant Cloud API
const baseUrl = core.getInput('base_url', { required: false }) || 'https://dashboard.quantcdn.io/api/v3';
Expand Down Expand Up @@ -84,7 +89,28 @@ async function run() {
return;
}

const output = JSON.stringify(translatedCompose);
// Apply image tag updates if provided
if (imageTagUpdatesStr) {
core.info('Applying image tag updates');
try {
const imageTagUpdates = JSON.parse(imageTagUpdatesStr) as ImageTagUpdates;

for (const container of translatedCompose.containers) {
if (container.name && imageTagUpdates[container.name]) {
const tag = imageTagUpdates[container.name];
core.info(`Updated image tag for container ${container.name} to ${tag}`);
container.imageReference = {
type: tag.includes(':') ? 'external' : 'internal',
identifier: tag
}
}
}
} catch (error) {
core.warning('Failed to parse image tag updates, skipping tag updates');
}
}

const output = JSON.stringify(translatedCompose, null, 2);
core.setOutput('translated_compose', output);
core.info(`\n ✅ Successfully translated compose file`);
return;
Expand Down
Loading