From 4a6a1c6674ae5cef5ad93aadd90f404f9660eeb6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Sep 2025 14:53:22 +0000 Subject: [PATCH 1/2] Initial plan From 949e0db1f437e3222bb48af430dd407bf2ab97a1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Sep 2025 15:02:55 +0000 Subject: [PATCH 2/2] Implement docker-release-action with prefixed images and reusable workflows Co-authored-by: l-you <32598874+l-you@users.noreply.github.com> --- .github/workflows/major-version.yml | 16 +++ .github/workflows/reusable.yml | 70 ++++++++++++ .github/workflows/test.yml | 36 ++++++ .gitignore | 23 ++++ Dockerfile | 3 + README.md | 166 +++++++++++++++++++++++++++- action.yml | 106 ++++++++++++++++++ examples/README.md | 36 ++++++ examples/basic-usage.yml | 16 +++ examples/docker-hub-usage.yml | 18 +++ examples/reusable-workflow.yml | 28 +++++ test/Dockerfile | 4 + 12 files changed, 520 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/major-version.yml create mode 100644 .github/workflows/reusable.yml create mode 100644 .github/workflows/test.yml create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 action.yml create mode 100644 examples/README.md create mode 100644 examples/basic-usage.yml create mode 100644 examples/docker-hub-usage.yml create mode 100644 examples/reusable-workflow.yml create mode 100644 test/Dockerfile diff --git a/.github/workflows/major-version.yml b/.github/workflows/major-version.yml new file mode 100644 index 0000000..7af6550 --- /dev/null +++ b/.github/workflows/major-version.yml @@ -0,0 +1,16 @@ +name: Update Major Version Tag + +on: + push: + tags: + - "v*" +permissions: + contents: write +jobs: + update-majorver: + name: Update Major Version Tag + runs-on: ubuntu-latest + steps: + - uses: nowactions/update-majorver@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/reusable.yml b/.github/workflows/reusable.yml new file mode 100644 index 0000000..77519d3 --- /dev/null +++ b/.github/workflows/reusable.yml @@ -0,0 +1,70 @@ +name: Reusable Docker Build and Push + +on: + workflow_call: + inputs: + image-name: + description: 'Name of the Docker image (without prefix)' + required: true + type: string + image-prefix: + description: 'Prefix to add to the image name' + required: false + type: string + default: '' + context: + description: 'Build context path' + required: false + type: string + default: '.' + dockerfile: + description: 'Path to Dockerfile' + required: false + type: string + default: './Dockerfile' + platforms: + description: 'Target platforms for build' + required: false + type: string + default: 'linux/amd64,linux/arm64' + registry: + description: 'Container registry to push to' + required: false + type: string + default: 'ghcr.io' + push: + description: 'Push the image to registry' + required: false + type: boolean + default: true + outputs: + image: + description: 'Full image name with tags' + value: ${{ jobs.docker-build.outputs.image }} + digest: + description: 'Image digest' + value: ${{ jobs.docker-build.outputs.digest }} + +jobs: + docker-build: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + attestations: write + id-token: write + outputs: + image: ${{ steps.docker-action.outputs.image }} + digest: ${{ steps.docker-action.outputs.digest }} + steps: + - name: Build and Push Docker Image + id: docker-action + uses: RevoTale/docker-release-action@v1 + with: + registry: ${{ inputs.registry }} + image-name: ${{ inputs.image-name }} + image-prefix: ${{ inputs.image-prefix }} + context: ${{ inputs.context }} + dockerfile: ${{ inputs.dockerfile }} + platforms: ${{ inputs.platforms }} + push: ${{ inputs.push }} \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..05658de --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,36 @@ +name: Test Action + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main ] + +jobs: + test-action: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Test action (build only) + uses: ./ + with: + image-name: test-app + image-prefix: test- + push: false + context: . + dockerfile: ./test/Dockerfile + + test-with-prefix: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Test action with prefix (build only) + uses: ./ + with: + image-name: my-app + image-prefix: myorg- + push: false \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..449196b --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +# Temporary files +*.tmp +*.temp +/tmp/ + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Editor files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# Logs +*.log \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..fd34c51 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,3 @@ +FROM alpine:latest +WORKDIR /app +CMD ["echo", "Hello from Docker Release Action!"] \ No newline at end of file diff --git a/README.md b/README.md index 455c863..0c632b7 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,164 @@ -# docker-release-action -A GitHub CI action to deploy multi-platform docker image. +# Docker Release Action + +A GitHub CI Action to deploy multi-platform Docker images with configurable prefixes and reusable workflows. + +## Features + +- 🐳 **Multi-platform builds** - Supports linux/amd64 and linux/arm64 by default +- 🏷️ **Configurable image prefixes** - Add custom prefixes to your image names +- 🔄 **Reusable workflows** - Easily integrate into any repository +- 🔐 **Flexible registry support** - Works with GitHub Container Registry, Docker Hub, and others +- ⚡ **Composite action** - Fast execution with minimal overhead + +## Usage + +### Basic Usage + +```yaml +name: Build and Push Docker Image +on: + release: + types: [published] + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - uses: RevoTale/docker-release-action@v1 + with: + image-name: my-app +``` + +### Advanced Usage with Prefix + +```yaml +name: Build and Push Docker Image +on: + release: + types: [published] + +jobs: + docker: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: RevoTale/docker-release-action@v1 + with: + registry: ghcr.io + image-name: my-app + image-prefix: my-org- + context: ./docker + dockerfile: ./docker/Dockerfile + platforms: linux/amd64,linux/arm64,linux/arm/v7 +``` + +### Multiple Images with Different Prefixes + +```yaml +name: Build Multiple Images +on: + release: + types: [published] + +jobs: + build-api: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: RevoTale/docker-release-action@v1 + with: + image-name: api + image-prefix: myproject- + context: ./api + dockerfile: ./api/Dockerfile + + build-frontend: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: RevoTale/docker-release-action@v1 + with: + image-name: frontend + image-prefix: myproject- + context: ./frontend + dockerfile: ./frontend/Dockerfile +``` + +## Inputs + +| Input | Description | Required | Default | +|-------|-------------|----------|---------| +| `registry` | Container registry to push to | No | `ghcr.io` | +| `image-name` | Name of the Docker image (without prefix) | Yes | - | +| `image-prefix` | Prefix to add to the image name | No | `""` | +| `context` | Build context path | No | `.` | +| `dockerfile` | Path to Dockerfile | No | `./Dockerfile` | +| `platforms` | Target platforms for build | No | `linux/amd64,linux/arm64` | +| `push` | Push the image to registry | No | `true` | +| `registry-username` | Username for registry authentication | No | `${{ github.actor }}` | +| `registry-password` | Password for registry authentication | No | `${{ github.token }}` | + +## Outputs + +| Output | Description | +|--------|-------------| +| `image` | Full image name with tags | +| `digest` | Image digest | + +## Examples + +### Using with Docker Hub + +```yaml +- uses: RevoTale/docker-release-action@v1 + with: + registry: docker.io + image-name: my-app + image-prefix: myusername/ + registry-username: ${{ secrets.DOCKERHUB_USERNAME }} + registry-password: ${{ secrets.DOCKERHUB_TOKEN }} +``` + +### Build Only (No Push) + +```yaml +- uses: RevoTale/docker-release-action@v1 + with: + image-name: my-app + push: false +``` + +### Custom Platforms + +```yaml +- uses: RevoTale/docker-release-action@v1 + with: + image-name: my-app + platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/ppc64le +``` + +## Image Naming + +The final image name is constructed as: `{registry}/{image-prefix}{image-name}` + +Examples: +- `ghcr.io/my-app` (no prefix) +- `ghcr.io/myorg-my-app` (with prefix "myorg-") +- `docker.io/myusername/my-app` (Docker Hub with username as prefix) + +## Examples + +For more usage examples, see the [examples directory](./examples/) which contains: +- [Basic usage](./examples/basic-usage.yml) +- [Reusable workflow example](./examples/reusable-workflow.yml) +- [Docker Hub usage](./examples/docker-hub-usage.yml) + +## License + +MIT License - see [LICENSE](LICENSE) file for details. diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..a4a7ec6 --- /dev/null +++ b/action.yml @@ -0,0 +1,106 @@ +name: Docker Release Action +description: GitHub CI Action to deploy multi-platform docker images with configurable prefixes and reusable workflows. +branding: + icon: 'package' + color: 'blue' +inputs: + registry: + description: 'Container registry to push to (e.g., ghcr.io, docker.io)' + required: false + default: 'ghcr.io' + image-name: + description: 'Name of the Docker image (without prefix)' + required: true + image-prefix: + description: 'Prefix to add to the image name (e.g., "my-org-")' + required: false + default: '' + context: + description: 'Build context path' + required: false + default: '.' + dockerfile: + description: 'Path to Dockerfile' + required: false + default: './Dockerfile' + platforms: + description: 'Target platforms for build' + required: false + default: 'linux/amd64,linux/arm64' + push: + description: 'Push the image to registry' + required: false + default: 'true' + registry-username: + description: 'Username for registry authentication' + required: false + default: '${{ github.actor }}' + registry-password: + description: 'Password for registry authentication' + required: false + default: '${{ github.token }}' + +outputs: + image: + description: 'Full image name with tags' + value: ${{ steps.meta.outputs.tags }} + digest: + description: 'Image digest' + value: ${{ steps.push.outputs.digest }} + +runs: + using: "composite" + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ inputs.registry }} + username: ${{ inputs.registry-username }} + password: ${{ inputs.registry-password }} + + - name: Generate image name with prefix + id: image-name + run: | + PREFIX="${{ inputs.image-prefix }}" + IMAGE_NAME="${{ inputs.image-name }}" + REGISTRY="${{ inputs.registry }}" + + if [ -n "$PREFIX" ]; then + FULL_IMAGE_NAME="${PREFIX}${IMAGE_NAME}" + else + FULL_IMAGE_NAME="${IMAGE_NAME}" + fi + + # Handle registry format - if it doesn't contain a slash, add the repository context + if [[ "$REGISTRY" == "ghcr.io" ]]; then + echo "full-name=${REGISTRY}/${{ github.repository_owner }}/${FULL_IMAGE_NAME}" >> $GITHUB_OUTPUT + else + echo "full-name=${REGISTRY}/${FULL_IMAGE_NAME}" >> $GITHUB_OUTPUT + fi + shell: bash + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: ${{ steps.image-name.outputs.full-name }} + + - name: Build and push Docker image + id: push + uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + with: + context: ${{ inputs.context }} + file: ${{ inputs.dockerfile }} + push: ${{ inputs.push }} + platforms: ${{ inputs.platforms }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..7335d99 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,36 @@ +# Examples + +This directory contains example workflows demonstrating different ways to use the Docker Release Action. + +## Available Examples + +### [basic-usage.yml](./basic-usage.yml) +Shows the simplest possible usage with minimal configuration. + +### [reusable-workflow.yml](./reusable-workflow.yml) +Demonstrates how to use the reusable workflow to build multiple images with consistent configuration. + +### [docker-hub-usage.yml](./docker-hub-usage.yml) +Shows how to configure the action for Docker Hub instead of GitHub Container Registry, including custom prefixes. + +## Usage + +To use any of these examples in your repository: + +1. Copy the desired example file to `.github/workflows/` in your repository +2. Modify the configuration as needed for your specific use case +3. Ensure you have the necessary permissions and secrets configured +4. Commit and push the workflow file + +## Required Permissions + +Most examples require these permissions: +```yaml +permissions: + contents: read + packages: write +``` + +For Docker Hub usage, you'll also need to set up these repository secrets: +- `DOCKERHUB_USERNAME` +- `DOCKERHUB_TOKEN` \ No newline at end of file diff --git a/examples/basic-usage.yml b/examples/basic-usage.yml new file mode 100644 index 0000000..af30326 --- /dev/null +++ b/examples/basic-usage.yml @@ -0,0 +1,16 @@ +# Example: Basic Usage +name: Docker Release +on: + release: + types: [published] + +jobs: + docker: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: RevoTale/docker-release-action@v1 + with: + image-name: my-app \ No newline at end of file diff --git a/examples/docker-hub-usage.yml b/examples/docker-hub-usage.yml new file mode 100644 index 0000000..874545d --- /dev/null +++ b/examples/docker-hub-usage.yml @@ -0,0 +1,18 @@ +# Example: Docker Hub usage with custom prefix +name: Docker Hub Release +on: + release: + types: [published] + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - uses: RevoTale/docker-release-action@v1 + with: + registry: docker.io + image-name: my-application + image-prefix: myorganization/ + registry-username: ${{ secrets.DOCKERHUB_USERNAME }} + registry-password: ${{ secrets.DOCKERHUB_TOKEN }} + platforms: linux/amd64,linux/arm64,linux/arm/v7 \ No newline at end of file diff --git a/examples/reusable-workflow.yml b/examples/reusable-workflow.yml new file mode 100644 index 0000000..9c59e11 --- /dev/null +++ b/examples/reusable-workflow.yml @@ -0,0 +1,28 @@ +# Example: Using reusable workflow +name: Build Multiple Images +on: + release: + types: [published] + +jobs: + api: + uses: RevoTale/docker-release-action/.github/workflows/reusable.yml@v1 + with: + image-name: api + image-prefix: mycompany- + context: ./api + dockerfile: ./api/Dockerfile + permissions: + contents: read + packages: write + + frontend: + uses: RevoTale/docker-release-action/.github/workflows/reusable.yml@v1 + with: + image-name: frontend + image-prefix: mycompany- + context: ./frontend + dockerfile: ./frontend/Dockerfile + permissions: + contents: read + packages: write \ No newline at end of file diff --git a/test/Dockerfile b/test/Dockerfile new file mode 100644 index 0000000..608d999 --- /dev/null +++ b/test/Dockerfile @@ -0,0 +1,4 @@ +FROM alpine:latest +WORKDIR /app +COPY . . +CMD ["echo", "Hello from Docker Release Action test!"] \ No newline at end of file