Merge pull request #1 from Frozen-Tapestry/develop

Initial release with: strict mode for bash, rootless podman build
This commit is contained in:
Foat 2024-12-18 17:56:35 +03:00 committed by GitHub
commit e53bcfcfef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 89 additions and 80 deletions

View file

@ -1,9 +1,12 @@
name: verify name: Container Action Tests
on: on:
push: push:
branches: branches:
- prime - prime
- develop
pull_request_review:
types: [submitted]
permissions: permissions:
contents: read contents: read
@ -30,14 +33,12 @@ jobs:
login_registry: ghcr.io login_registry: ghcr.io
login_username: ${{ github.actor }} login_username: ${{ github.actor }}
login_password: ${{ secrets.GITHUB_TOKEN }} login_password: ${{ secrets.GITHUB_TOKEN }}
tags: | tags: ghcr.io/frozen-tapestry/podman-action-verify:latest
ghcr.io/frozen-tapestry/podman-action-verify:latest
dockerfile: Dockerfile dockerfile: Dockerfile
build_args: | build_args: MY_ENV_VAR=Test MY_ENV_VAR2=Test2
MY_ENV_VAR=Test security: |
MY_ENV_VAR2=Test2 --security-opt=seccomp=unconfined
security: --security-opt=apparmor=unconfined
--security-opt seccomp=unconfined --security-opt apparmor=unconfined
push: true push: true
- name: Run Docker container and verify output - name: Run Docker container and verify output
id: verify-output id: verify-output

View file

@ -1,24 +1,23 @@
# Podman (Login,Build,Push) GitHub Action # Podman (Login, Build, Push) GitHub Action
This repository provides a GitHub Action to build and push container images using [Podman](https://podman.io/). It supports Podman login, building images from Dockerfiles, and pushing images to container registries. This repository provides a GitHub Action to build and push container images using [Podman](https://podman.io/). The action supports Podman login, building images from Dockerfiles, and pushing images to container registries. It is designed to work seamlessly within GitHub workflows to automate CI/CD pipelines.
## Features ## Features
- Build container images with Podman. - **Build and Push:** Build container images and optionally push them to a container registry.
- Push images to a container registry (e.g., `ghcr.io`, `quay.io`). - **Flexible Configuration:** Support for build arguments, labels, tags, and security options.
- Flexible support for build arguments, labels, tags, and security options. - **CI/CD Ready:** Designed for GitHub Actions workflows.
- Designed to run in GitHub workflows for CI/CD automation. - **Shared Storage Support:** Compatible with shared storage on self-hosted runners for caching.
- Supports Gitea Actions with a shared storage between runs.
## Directory Structure ## Directory Structure
```plaintext ```plaintext
podman-action container-action
├── LICENSE # License information (MIT) ├── LICENSE # License information (MIT)
├── README.md # This documentation ├── README.md # This documentation
├── .github ├── .github
│ └── workflows │ └── workflows
│ └── verify.yml # Example GitHub workflow for verification │ └── verify.yml # Example workflow for testing
├── scripts ├── scripts
│ └── run.sh # Core script to handle Podman operations │ └── run.sh # Core script to handle Podman operations
└── action.yml # GitHub Action definition └── action.yml # GitHub Action definition
@ -28,7 +27,7 @@ podman-action
### Example Workflow ### Example Workflow
Add the following workflow file to `.github/workflows/build.yml`: To use this action in a workflow, create a file `.github/workflows/build.yml` with the following content:
```yaml ```yaml
name: Build and Push Container Image name: Build and Push Container Image
@ -59,19 +58,18 @@ jobs:
### Inputs ### Inputs
| Input | Description | Required | Default | | Input | Description | Required | Default |
|------------------|--------------------------------------------------------------------------------------------------|----------|------------------| |------------------|---------------------------------------------------------------------------------------------------------|----------|------------------|
| `login_registry` | The container registry to push to (e.g., `ghcr.io`). | No | | | `login_registry` | Container registry to push to (e.g., `quay.io`). If not set, the image is only built locally. | No | |
| `login_username` | Registry username. | No | | | `login_username` | Registry username. | No | |
| `login_password` | Registry password (use GitHub secrets). | No | | | `login_password` | Registry password (GitHub secret recommended). | No | |
| `tags` | Tags for the image (space-separated or newline-separated). | No | | | `tags` | Tags for the image. Space-separated. e.g. `quay.io/podman/stable:latest quay.io/podman/stable:nightly`. | No | |
| `labels` | Additional metadata for the image (space-separated or newline-separated). | No | | | `labels` | List of additional metadata for an image. Space-separated. | No | |
| `build_args` | Build arguments (space-separated or newline-separated). | No | | | `build_args` | Optional build arguments. Space-separated. e.g. `MY_ENV_VAR=Test MY_ENV_VAR2=Test2`. | No | |
| `extra_args` | Extra arguments for the `podman build` command (newline-separated). | No | | | `extra_args` | Extra arguments to be passed to Podman. Space-separated. e.g. `-e=MY_ENV=Test -e=MY_ENV=Test2`. | No | |
| `dockerfile` | Path to the Dockerfile. If set, the build step is performed. | No | | | `dockerfile` | Path to the Dockerfile. If set, the build step is performed. | No | |
| `push` | Whether to push the image after building. | No | `false` | | `push` | Whether to push the image after building. | No | `false` |
| `shared_path` | Path to a shared folder for cache files on the host filesystem (useful for self-hosted runners). | No | `/tmp/shared` | | `security` | Security flags used for an intermediate container. Newline-separated. | No | `--network=host` |
| `security` | Security options for the intermediate container (space-separated). | No | `--network=host` |
## Development ## Development
@ -82,7 +80,7 @@ The `verify.yml` workflow tests the action by:
2. Building and pushing the container image. 2. Building and pushing the container image.
3. Running the container to validate its output. 3. Running the container to validate its output.
You can use this workflow as a template for testing your own usage. You can use this workflow as a template for testing your own usage. It is located at `.github/workflows/verify.yml`.
### Core Script ### Core Script
@ -97,4 +95,4 @@ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file
## Contributions ## Contributions
Contributions, issues, and feature requests are welcome! Feel free to open a pull request or issue in this repository. Contributions, issues, and feature requests are welcome! Feel free to open a pull request or issue in this repository.

5
RELEASES.md Normal file
View file

@ -0,0 +1,5 @@
# Container Action releases
### v1.0.0
- Initial release

View file

@ -16,19 +16,22 @@ inputs:
required: false required: false
tags: tags:
description: | description: |
Tag of the image (space-separated or newline-separated). Tags for the image. Space-separated. e.g.
e.g. quay.io/podman/stable:latest quay.io/podman/stable:latest quay.io/podman/stable:nightly
required: false required: false
labels: labels:
description: List of additional metadata for an image (space-separated or newline-separated). description: |
List of additional metadata for an image. Space-separated.
required: false required: false
build_args: build_args:
description: Optional build arguments (space-separated or newline-separated). description: |
Optional build arguments. Space-separated. e.g.
MY_ENV_VAR=Test MY_ENV_VAR2=Test2
required: false required: false
extra_args: extra_args:
description: | description: |
Extra args to be passed to podman bud. Extra args to be passed to podman. Space-separated. e.g.
Separate arguments by newline. -e=MY_ENV=Test -e=MY_ENV=Test2
required: false required: false
dockerfile: dockerfile:
description: Path to the Dockerfile. If set, build step is performed. description: Path to the Dockerfile. If set, build step is performed.
@ -37,49 +40,34 @@ inputs:
description: Whether to push the image after building. description: Whether to push the image after building.
default: 'false' default: 'false'
required: false required: false
shared_path:
description: |
Path to container shared folder for different cache files on the host filesystem.
Useful for self-hosted runners.
default: '/tmp/shared'
required: false
security: security:
description: Security flags that are used for an intermediate container. Space separated. description: Security flags that are used for an intermediate container. New line separated.
default: '--network=host' default: '--network=host'
required: false required: false
runs: runs:
using: composite using: composite
steps: steps:
- name: Convert composite args
id: convert
shell: bash
run: |
echo tags=$(echo "${{ inputs.tags }}" | xargs echo -n | tr -s ' \n' '+') >> $GITHUB_OUTPUT
echo labels=$(echo "${{ inputs.labels }}" | xargs echo -n | tr -s ' \n' '+') >> $GITHUB_OUTPUT
echo build_args=$(echo "${{ inputs.build_args }}" | xargs echo -n | tr -s ' \n' '+') >> $GITHUB_OUTPUT
echo extra_args=$(echo "${{ inputs.extra_args }}" | xargs echo -n | tr -s ' \n' '+') >> $GITHUB_OUTPUT
- name: Run container steps - name: Run container steps
uses: frozen-tapestry/docker-run-action@v5 uses: frozen-tapestry/docker-run-action@v6
with: with:
image: quay.io/podman/stable:latest image: quay.io/podman/stable:latest
mount_ws: true mount_ws: true
options: | options: |
${{ inputs.security }} ${{ inputs.security }}
-v ${{ inputs.shared_path }}/auth:/etc/containers/auth -v=${{ env.CACHE_SHARED_PATH }}/podman-auth:/home/podman/auth:rw
-v ${{ inputs.shared_path }}/storage:/var/lib/containers/storage -v=${{ env.CACHE_SHARED_PATH }}/podman-storage:/home/podman/.local/share/containers/storage:rw
-v ${{ github.action_path }}/scripts:/scripts -v=${{ github.action_path }}/scripts:/scripts:ro
-e REGISTRY_AUTH_FILE=/etc/containers/auth/auth.json -e=REGISTRY_AUTH_FILE=/home/podman/auth/auth.json
-e REGISTRY=${{ inputs.login_registry }} -e=REGISTRY=${{ inputs.login_registry }}
-e USERNAME=${{ inputs.login_username }} -e=USERNAME=${{ inputs.login_username }}
-e PASSWORD=${{ inputs.login_password }} -e=PASSWORD=${{ inputs.login_password }}
-e ACTION_TAGS=${{ steps.convert.outputs.tags }} -e=ACTION_TAGS=${{ inputs.tags }}
-e ACTION_LABELS=${{ steps.convert.outputs.labels }} -e=ACTION_LABELS=${{ inputs.labels }}
-e ACTION_BUILD_ARGS=${{ steps.convert.outputs.build_args }} -e=ACTION_BUILD_ARGS=${{ inputs.build_args }}
-e ACTION_EXTRA_ARGS=${{ steps.convert.outputs.extra_args }} -e=ACTION_EXTRA_ARGS=${{ inputs.extra_args }}
-e DOCKERFILE=${{ inputs.dockerfile }} -e=DOCKERFILE=${{ inputs.dockerfile }}
-e REVISION=${{ github.sha }} -e=REVISION=${{ github.sha }}
-e SOURCE=${{ github.server_url }}/${{ github.repository }} -e=SOURCE=${{ github.server_url }}/${{ github.repository }}
-e PUSH=${{ inputs.push }} -e=PUSH=${{ inputs.push }}
run: /bin/bash /scripts/run.sh run: /bin/bash /scripts/run.sh

View file

@ -1,10 +1,24 @@
#!/bin/bash #!/bin/bash
set -euo pipefail set -euo pipefail
IFS=$'\n\t ' IFS=$'\n\t'
REGISTRY=${REGISTRY:-}
USERNAME=${USERNAME:-}
PASSWORD=${PASSWORD:-}
DOCKERFILE=${DOCKERFILE:-}
PUSH=${PUSH:-}
PODMAN_USER="podman"
chown $PODMAN_USER:$PODMAN_USER /home/$PODMAN_USER/auth
chown $PODMAN_USER:$PODMAN_USER /home/$PODMAN_USER/.local/share/containers/storage
### LOGIN ### LOGIN
if [[ -n "$REGISTRY" && -n "$USERNAME" && -n "$PASSWORD" ]]; then if [[ -n "$REGISTRY" && -n "$USERNAME" && -n "$PASSWORD" ]]; then
podman login --storage-driver=overlay $REGISTRY -u $USERNAME -p $PASSWORD sudo -u $PODMAN_USER podman login \
--storage-driver=overlay \
--authfile="$REGISTRY_AUTH_FILE" \
"$REGISTRY" -u "$USERNAME" -p "$PASSWORD"
fi fi
generate_args() { generate_args() {
@ -12,8 +26,8 @@ generate_args() {
local prefix="$2" local prefix="$2"
local output="" local output=""
if [ -n "$input_args" ]; then if [[ -n "$input_args" ]]; then
output="$(echo "$input_args" | tr -s '+' ' ' | sed "s/[^ ]* */$prefix &/g")" output="$(echo "$input_args" | tr -s ' ' '\n' | sed "s/[^ ]* */$prefix&/g")"
fi fi
echo "$output" echo "$output"
@ -27,17 +41,18 @@ if [[ -n "$DOCKERFILE" ]]; then
echo "Main labels: $CREATED $REVISION $SOURCE" echo "Main labels: $CREATED $REVISION $SOURCE"
TAGS=$(generate_args "$ACTION_TAGS" "-t") TAGS=$(generate_args "$ACTION_TAGS" "-t=")
echo "Tags: $TAGS" echo "Tags: $TAGS"
LABELS=$(generate_args "$ACTION_LABELS" "--label") LABELS=$(generate_args "$ACTION_LABELS" "--label=")
echo "Labels: $LABELS" echo "Labels: $LABELS"
BUILD_ARGS=$(generate_args "$ACTION_BUILD_ARGS" "--build-arg") BUILD_ARGS=$(generate_args "$ACTION_BUILD_ARGS" "--build-arg=")
echo "Build args: $BUILD_ARGS" echo "Build args: $BUILD_ARGS"
EXTRA_ARGS=$(generate_args "$ACTION_EXTRA_ARGS" "") EXTRA_ARGS=$(generate_args "$ACTION_EXTRA_ARGS" "")
echo "Extra args: $EXTRA_ARGS" echo "Extra args: $EXTRA_ARGS"
podman build --platform="linux/amd64" \ sudo -u $PODMAN_USER podman build --platform="linux/amd64" \
--storage-driver=overlay \ --storage-driver=overlay \
--authfile="$REGISTRY_AUTH_FILE" \
--pull=true \ --pull=true \
--label image.created="$CREATED" \ --label image.created="$CREATED" \
--label image.revision="$REVISION" \ --label image.revision="$REVISION" \
@ -54,5 +69,7 @@ if [[ -n "$PUSH" && "$PUSH" == "true" ]]; then
TAGS=$(generate_args "$ACTION_TAGS" "") TAGS=$(generate_args "$ACTION_TAGS" "")
echo "Tags: $TAGS" echo "Tags: $TAGS"
podman push --storage-driver=overlay $TAGS sudo -u $PODMAN_USER podman push \
--storage-driver=overlay \
--authfile="$REGISTRY_AUTH_FILE" $TAGS
fi fi