Skip to content

Commit

Permalink
added support for build-args
Browse files Browse the repository at this point in the history
  • Loading branch information
rgaudin committed Jan 5, 2021
1 parent 3036cf1 commit 70b6e59
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 19 deletions.
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,22 +44,25 @@ jobs:
hub-password: ${{ secrets.DOCKERHUB_PASSWORD }}
ghcr-username: ${{ secrets.GHCR_USERNAME }}
ghcr-token: ${{ secrets.GHCR_TOKEN }}

build-args:
VERSION={version}
ARCH=amd64
```
**Note**: th top-part `on` is just a filter on running that workflow. You can omit it but it's safer to not run it on refs that you know won't trigger anything. See [documentation](https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#on).

| Input | Usage |
| :--- | :--- |
| `image-path` | **Name of your image on the registry** (without the version part).<br />Ex.: `openzim/zimit` would refer to [this image](https://hub.docker.com/r/openzim/zimit).<br />The same name is pushed on **both registries**. |
| `image-path`<font color=red>\*</font> | **Name of your image on the registry** (without the version part).<br />Ex.: `openzim/zimit` would refer to [this image](https://hub.docker.com/r/openzim/zimit).<br />The same name is pushed on **both registries**. |
| `hub-username`<font color=red>\*</font> and `hub-password`<font color=red>\*</font> | **Docker Hub user credentials to push images with** |
| `ghcr-username`<font color=red>\*</font> and `ghcr-token`<font color=red>\*</font> | **Github user credentials to push images with**<br />Token is a [PAT](https://github.com/settings/tokens) with `repo, workflow, write:packages` permissions.|
| `context` | **Path in the repository to use as build context**<br />Relative to repository root. Defaults to `.`. Ex: `dnscache` or `workers/slave`. |
| `dockerfile` | **Path to the Dockerfile recipe, relative to context**<br />Defaults to `Dockerfile`. Use `../` syntax if dockerfile is outside context. |
| `on-master` | **Tag to apply for every commit on default branch**.<br />Omit it if you don't want to push an image for non-tagged commits.<br />Only applies to commits on your default branch (`master` or `main`) |
| `tag-pattern` | **Regular expression to match tags with**.<br />Only git tags matching this regexp will trigger a build+push to the corresponding docker tag.<br />If not specifying a group, whole git tag is used as is on docker. |
| `latest-on-tag` | **Whether to push to docker tag `:latest` on every matched tag** (see `tag-pattern`)<br />Value must be `true` or `false`. Defaults to `false`. |
| `restrict-to` | **Don't push if action is run for a different repository**<br />Specify as `{owner}/{repository}`. |
| `hub-username` and `hub-password` | **Docker Hub user credentials to push images with** |
| `ghcr-username` and `ghcr-token` | **Github user credentials to push images with**<br />Token is a [PAT](https://github.com/settings/tokens) with `repo, workflow, write:packages` permissions.|
| `build-args` | **Arguments for `docker build --build-arg`**<br />Special value `{version}` will be replaced with the tag to set.<br />Use the `name=value` format and separate each by a space or new line.|


⚠️ After your initial run creating your image, you need to manually **make it public** via Github's UI (see packages) if you intend to pull images without authenticating.
14 changes: 14 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,27 @@ inputs:
ghcr-token:
description: GHCR token to push image
required: true
build-args:
description: optional key/value pairs to pass as build arguments. {version} replaced with found version/latest (if any)
required: false

runs:
using: composite
steps:
- run: echo "IMAGE_TAGS=" >> $GITHUB_ENV
shell: bash

- name: save build-args to env
run: |
import os
import json
build_args = dict([item.split("=") if "=" in item else (item, "") for item in os.getenv("BUILD_ARGS", "").split()])
with open(os.getenv("GITHUB_ENV"), "a") as fh:
fh.write("BUILD_ARGS={}\n".format(json.dumps(build_args)))
shell: python
env:
BUILD_ARGS: ${{ inputs.build-args }}

- name: Compute Image Tags
run: python3 $GITHUB_ACTION_PATH/compute_tags.py
shell: bash
Expand Down
41 changes: 30 additions & 11 deletions build_push.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,23 @@

import os
import sys
import itertools
import json
import subprocess

tags = [t for t in os.getenv("IMAGE_TAGS", "").strip().split(",") if t]
tags_args = list(itertools.chain(*[["-t", tag] for tag in tags]))
tags = [t for t in os.getenv("VERSION_TAGS", "").strip().split(",") if t]

if not tags:
print("No tags to push to, skipping.")
sys.exit(0)

context = os.getenv("CONTEXT", ".")
dockerfile = os.path.join(context, os.getenv("DOCKERFILE", "Dockerfile"))
build_args = json.loads(os.getenv("BUILD_ARGS", "{}"))
image_path = os.getenv("IMAGE_PATH")

if not image_path:
print("missing image_path, exiting.")
sys.exit(1)

# login to dockerhub
print("Logging into Docker hub…")
Expand Down Expand Up @@ -54,24 +59,38 @@

print("Successfuly logged in to GHCR!")

# sys.exit(0)
all_tags = []

# looping over tags so we can create tag-aware build-arg.
for tag in tags:
# build list of --build-arg
build_args_arg = []
for arg, value in build_args.items():
if value == "{version}":
value = tag
build_args_arg += ["--build-arg", f"{arg}={value}"]

# tag it for both registries
tags_args = ["--tag", f"{image_path}:{tag}", "--tag", f"ghcr.io/{image_path}:{tag}"]

# build image
build = subprocess.run(["docker", "build", context, "-f", dockerfile] + tags_args)
if build.returncode != 0:
print(f"Unable to build image: {build.returncode}")
sys.exit(build.returncode)
# build image
cmd = ["docker", "build", context, "-f", dockerfile] + build_args_arg + tags_args
print(cmd)
build = subprocess.run(cmd)
if build.returncode != 0:
print(f"Unable to build image: {build.returncode}")
sys.exit(build.returncode)
all_tags += tags_args

# push image
has_failure = False
for tag in tags:
for tag in all_tags:
print(f"Pushing to {tag}")
push = subprocess.run(["docker", "push", tag])
if push.returncode != 0:
print(f"Unable to push image to {tag}: {push.returncode}")
has_failure = True


# logout from registries
subprocess.run(["docker", "logout", "ghcr.io"])
subprocess.run(["docker", "logout"])
Expand Down
2 changes: 2 additions & 0 deletions compute_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,6 @@

# write image_tags to env so it's available to future steps
with open(os.getenv("GITHUB_ENV"), "a") as fh:
fh.write("VERSION_TAGS={}\n".format(",".join(version_tags)))
fh.write("IMAGE_TAGS={}\n".format(",".join(image_tags)))
fh.write("IMAGE_PATH={}\n".format(image_path))
12 changes: 8 additions & 4 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,22 @@ def get_env(
}


def extract_result(fpath):
def extract_result(fpath, name):
with open(fpath, "r") as fh:
return [a for a in fh.read().strip().split("=", 1)[-1].split(",") if a.strip()]
for line in fh.readlines():
if line.startswith(name + "="):
tags = line.strip().split("=", 1)[-1]
return tags.split(",") if tags else []
return []


def launch_and_retrieve(**kwargs):
def launch_and_retrieve(name="IMAGE_TAGS", **kwargs):
import pprint

pprint.pprint(kwargs)
subprocess.run([sys.executable, "./compute_tags.py"], env=kwargs)
try:
return extract_result(kwargs.get("GITHUB_ENV", "-"))
return extract_result(kwargs.get("GITHUB_ENV", "-"), name)
except Exception:
return []

Expand Down

0 comments on commit 70b6e59

Please sign in to comment.