Skip to content

[IMPORT] Ubuntu

[IMPORT] Ubuntu #7

name: Process Image Import Request
on:
issues:
types: [opened, edited, labeled]
jobs:
process-import-request:
if: contains(github.event.issue.labels.*.name, 'import-request')
runs-on: ubuntu-latest
permissions:
issues: write
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Extract issue body
id: extract_data
uses: actions/github-script@v6
with:
script: |
const issue = context.payload.issue
const body = issue.body
// Parse the form data
const sourceMatch = body.match(/### Image Source\s*\n\s*(.*)/);
const repoMatch = body.match(/### Repository Name\s*\n\s*(.*)/);
const imageMatch = body.match(/### Image Name\s*\n\s*(.*)/);
const versionMatch = body.match(/### Image Version\/Tag\s*\n\s*(.*)/);
const useLatestMatch = body.match(/- \[(?:x|X)\] Import the latest version of this image/);
const isOfficialMatch = body.match(/- \[(?:x|X)\] This is an official Docker Hub image/);
const source = sourceMatch ? sourceMatch[1].trim() : null;
const repo = repoMatch ? repoMatch[1].trim() : null;
const image = imageMatch ? imageMatch[1].trim() : null;
const version = versionMatch ? versionMatch[1].trim() : null;
const useLatest = Boolean(useLatestMatch);
const isOfficial = Boolean(isOfficialMatch);
const imageTag = useLatest || !version ? 'latest' : version;
if (!source || !image) {
await github.rest.issues.createComment({
issue_number: issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '⚠️ Error: Missing required information. Please make sure to provide source and image name.'
});
return core.setFailed('Missing required information');
}
// For non-official images, repository is required
if (!isOfficial && !repo) {
await github.rest.issues.createComment({
issue_number: issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '⚠️ Error: Repository name is required for non-official images. If this is an official image, please check the "This is an official Docker Hub image" option.'
});
return core.setFailed('Missing repository name for non-official image');
}
core.setOutput('source', source);
core.setOutput('repo', repo || 'library'); // For official images, use 'library' as repository
core.setOutput('image', image);
core.setOutput('version', imageTag);
core.setOutput('isOfficial', isOfficial);
core.setOutput('useLatest', useLatest.toString());
// Format the source image string based on whether it's an official image or not
const sourceImageDisplay = isOfficial ? `${image}:${imageTag}` : `${repo}/${image}:${imageTag}`;
// Add comment about processing
await github.rest.issues.createComment({
issue_number: issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## 🔄 Processing Import Request
Processing request to import \`${sourceImageDisplay}\` from ${source}.
- **Source**: ${source}
- **Image**: ${sourceImageDisplay}
- **Type**: ${isOfficial ? 'Official Image' : 'Repository Image'}
- **Version**: ${imageTag}
Starting import process. Please wait...`
});
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# - name: Login to DockerHub
# uses: docker/login-action@v3
# with:
# username: ${{ secrets.DOCKERHUB_USERNAME }}
# password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Pull and push image
id: docker_pull_push
env:
SOURCE_REPO: ${{ steps.extract_data.outputs.repo }}
IMAGE_NAME: ${{ steps.extract_data.outputs.image }}
IMAGE_VERSION: ${{ steps.extract_data.outputs.version }}
IS_OFFICIAL: ${{ steps.extract_data.outputs.isOfficial }}
USE_LATEST: ${{ steps.extract_data.outputs.useLatest }}
run: |
echo "::group::Import Process Details"
# Handle official images vs repository images
if [[ "$IS_OFFICIAL" == "true" ]]; then
SOURCE_IMAGE="${IMAGE_NAME}:${IMAGE_VERSION}"
else
SOURCE_IMAGE="${SOURCE_REPO}/${IMAGE_NAME}:${IMAGE_VERSION}"
fi
TARGET_IMAGE="ghcr.io/${{ github.repository_owner }}/dockerhub-${IMAGE_NAME}:${IMAGE_VERSION}"
echo "Source Image: ${SOURCE_IMAGE}"
echo "Target Image: ${TARGET_IMAGE}"
# Check if target image already exists
if docker manifest inspect "${TARGET_IMAGE}" > /dev/null 2>&1; then
echo "Target image already exists in GitHub Packages"
# If it's a 'latest' image, we should update it even if it exists
if [[ "$IMAGE_VERSION" == "latest" || "$USE_LATEST" == "true" ]]; then
echo "This is a 'latest' image request - updating the existing image"
echo "image_exists=true" >> $GITHUB_OUTPUT
echo "update_latest=true" >> $GITHUB_OUTPUT
echo "target_image=${TARGET_IMAGE}" >> $GITHUB_OUTPUT
# Get old digest before updating
OLD_TARGET_DIGEST=$(docker pull "${TARGET_IMAGE}" > /dev/null && docker inspect --format='{{index .RepoDigests 0}}' "${TARGET_IMAGE}" | cut -d '@' -f 2)
echo "old_target_digest=${OLD_TARGET_DIGEST}" >> $GITHUB_OUTPUT
# Proceed with the update process - force pull the latest
echo "Pulling latest ${SOURCE_IMAGE}..."
docker pull --no-cache "${SOURCE_IMAGE}"
else
# For non-latest images, we just mark as duplicate and exit
echo "::warning::Image ${TARGET_IMAGE} already exists in GitHub Packages"
echo "image_exists=true" >> $GITHUB_OUTPUT
echo "update_latest=false" >> $GITHUB_OUTPUT
echo "target_image=${TARGET_IMAGE}" >> $GITHUB_OUTPUT
exit 0
fi
else
# Image doesn't exist yet
echo "image_exists=false" >> $GITHUB_OUTPUT
echo "update_latest=false" >> $GITHUB_OUTPUT
# Pull source image
echo "Pulling ${SOURCE_IMAGE}..."
docker pull "${SOURCE_IMAGE}"
fi
# Get image digest
SOURCE_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' "${SOURCE_IMAGE}" | cut -d '@' -f 2)
echo "Source Image Digest: ${SOURCE_DIGEST}"
echo "source_digest=${SOURCE_DIGEST}" >> $GITHUB_OUTPUT
# Tag image for GitHub Packages
docker tag "${SOURCE_IMAGE}" "${TARGET_IMAGE}"
# Push to GitHub Packages
echo "Pushing to GitHub Packages as ${TARGET_IMAGE}..."
docker push "${TARGET_IMAGE}"
# Get target image digest
TARGET_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' "${TARGET_IMAGE}" | cut -d '@' -f 2)
echo "Target Image Digest: ${TARGET_DIGEST}"
echo "target_image=${TARGET_IMAGE}" >> $GITHUB_OUTPUT
echo "target_digest=${TARGET_DIGEST}" >> $GITHUB_OUTPUT
echo "::endgroup::"
- name: Update issue with results
uses: actions/github-script@v6
env:
IMAGE_EXISTS: ${{ steps.docker_pull_push.outputs.image_exists }}
UPDATE_LATEST: ${{ steps.docker_pull_push.outputs.update_latest }}
TARGET_IMAGE: ${{ steps.docker_pull_push.outputs.target_image }}
SOURCE_DIGEST: ${{ steps.docker_pull_push.outputs.source_digest }}
TARGET_DIGEST: ${{ steps.docker_pull_push.outputs.target_digest }}
OLD_TARGET_DIGEST: ${{ steps.docker_pull_push.outputs.old_target_digest }}
with:
script: |
const imageExists = process.env.IMAGE_EXISTS === 'true';
const updateLatest = process.env.UPDATE_LATEST === 'true';
const targetImage = process.env.TARGET_IMAGE;
const sourceDigest = process.env.SOURCE_DIGEST;
const targetDigest = process.env.TARGET_DIGEST;
const oldTargetDigest = process.env.OLD_TARGET_DIGEST;
const workflowRunUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
let commentBody = '';
let labels = [];
if (imageExists && !updateLatest) {
// Regular duplicate image case - no update needed
commentBody = `## ℹ️ Image Already Exists
The requested image already exists in GitHub Packages.
- **Image**: \`${targetImage}\`
- **Workflow Run**: [View Logs](${workflowRunUrl})
You can use this image in your workflows or deployments.`;
labels = ['import-request', 'duplicate', 'resolved'];
} else if (imageExists && updateLatest) {
// Latest image was updated
commentBody = `## 🔄 Latest Image Updated
Successfully updated the latest image in GitHub Packages.
- **Image**: \`${targetImage}\`
- **Previous Digest**: \`${oldTargetDigest}\`
- **Source Digest**: \`${sourceDigest}\`
- **New Target Digest**: \`${targetDigest}\`
- **Workflow Run**: [View Logs](${workflowRunUrl})
- **Update Timestamp**: ${new Date().toISOString()}
- **Updated by**: @${context.actor}
You can now use this updated image in your workflows or deployments.`;
labels = ['import-request', 'updated-latest', 'resolved'];
} else {
// New image was imported
commentBody = `## ✅ Import Complete
Successfully imported the image to GitHub Packages.
- **Image**: \`${targetImage}\`
- **Source Digest**: \`${sourceDigest}\`
- **Target Digest**: \`${targetDigest}\`
- **Workflow Run**: [View Logs](${workflowRunUrl})
- **Import Timestamp**: ${new Date().toISOString()}
- **Imported by**: @${context.actor}
You can now use this image in your workflows or deployments.`;
labels = ['import-request', 'imported', 'resolved'];
}
await github.rest.issues.createComment({
issue_number: context.payload.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: commentBody
});
// Close the issue with appropriate labels
await github.rest.issues.update({
issue_number: context.payload.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
state: 'closed',
labels: labels
});