Skip to content
Open
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
78 changes: 78 additions & 0 deletions .github/actions/docker-publish-action/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<!--
SPDX-License-Identifier: Apache-2.0
SPDX-FileCopyrightText: 2026 The Linux Foundation
-->

# Docker Publish Action

A composite GitHub Action that builds and pushes Docker images tagged with branch names and git tags.

## Description

Builds Docker images using `make docker-build` and pushes them with `make docker-push`. Images are tagged with the current branch name and any git tags pointing at HEAD. Golang-style version tags (e.g., `v1.2.3`) have the leading `v` stripped automatically.

## Usage

```yaml
- uses: ./.github/actions/docker-publish-action
with:
docker-registry: "docker.io"
docker-repository: "myorg"
image-name: "myapp"
docker-username: ${{ secrets.DOCKER_USERNAME }}
docker-password: ${{ secrets.DOCKER_PASSWORD }}
```

### Inputs

| Input | Required | Default | Description |
|-------|----------|---------|-------------|
| `docker-registry` | Yes | — | Docker registry URL |
| `docker-repository` | Yes | — | Docker repository prefix |
| `image-name` | Yes | — | Name of the Docker image |
| `extra-environment-vars` | No | `""` | Extra environment variables for make commands |
| `docker-username` | Yes | — | Docker registry username |
| `docker-password` | Yes | — | Docker registry password |
Comment on lines +28 to +35

### Example Workflow

```yaml
name: Publish Docker Image

on:
push:
branches: [main]
tags: ["v*"]

jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: ./.github/actions/docker-publish-action
with:
docker-registry: "docker.io"
docker-repository: "voltha"
image-name: "voltha-northbound"
extra-environment-vars: "GOFLAGS=-buildvcs=false"
docker-username: ${{ secrets.DOCKER_USERNAME }}
docker-password: ${{ secrets.DOCKER_PASSWORD }}
```

## How It Works

1. Logs in to the configured Docker registry.
2. Discovers git tags pointing at the current HEAD commit.
3. Runs `make docker-build` with `DOCKER_TAG` set to the branch name.
4. Runs `make docker-build` for each git tag (stripping the `v` prefix).
5. Runs `make docker-push` for the branch tag and each git tag.
6. Logs out of the Docker registry.

## Requirements

- The repository must have a `Makefile` with `docker-build` and `docker-push` targets.
- These targets must respect `DOCKER_TAG`, `DOCKER_REGISTRY`, `DOCKER_REPOSITORY`, and `IMAGE_NAME` environment variables.
- The checkout step should use `fetch-depth: 0` to ensure git tags are available.
142 changes: 142 additions & 0 deletions .github/actions/docker-publish-action/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
---
# SPDX-FileCopyrightText: 2026 The Linux Foundation
# SPDX-License-Identifier: Apache-2.0

name: Docker Publish
description: "Build and push Docker images tagged with branch name and git tags"

inputs:
docker-registry:
description: "Docker registry URL"
required: false
default: "docker.io"
docker-repository:
description: "Docker repository prefix"
required: true
image-name:
description: "Name of the Docker image"
required: true
extra-environment-vars:
description: "Extra environment variables for make commands"
required: false
default: ""
docker-username:
description: "Docker registry username"
required: true
docker-password:
description: "Docker registry password"
required: true

runs:
using: "composite"
steps:
- name: Log in to Docker registry
uses: docker/login-action@v3
with:
# yamllint disable-line rule:line-length
registry: ${{ inputs.docker-registry }}
username: ${{ inputs.docker-username }}
password: ${{ inputs.docker-password }}

- name: Get git tags on HEAD
id: git-tags
shell: bash
run: |
set -eu -o pipefail
TAGS=$(git tag --points-at HEAD || true)
echo "tags<<EOF" >> "$GITHUB_OUTPUT"
echo "$TAGS" >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"

- name: Build Docker image with branch tag
shell: bash
run: |
set -eu -o pipefail
BRANCH_NAME="${GITHUB_REF_NAME}"
DOCKER_REGISTRY="${{ inputs.docker-registry }}"
DOCKER_REPOSITORY="${{ inputs.docker-repository }}"
IMAGE_NAME="${{ inputs.image-name }}"

echo "Building image with branch tag: ${BRANCH_NAME}"
${{ inputs.extra-environment-vars }} \
DOCKER_TAG="${BRANCH_NAME}" \
DOCKER_REGISTRY="${DOCKER_REGISTRY}" \
DOCKER_REPOSITORY="${DOCKER_REPOSITORY}" \
IMAGE_NAME="${IMAGE_NAME}" \
make docker-build
Comment on lines +51 to +66

- name: Build Docker images for git tags
shell: bash
run: |
set -eu -o pipefail
DOCKER_REGISTRY="${{ inputs.docker-registry }}"
DOCKER_REPOSITORY="${{ inputs.docker-repository }}"
IMAGE_NAME="${{ inputs.image-name }}"

TAGS='${{ steps.git-tags.outputs.tags }}'
if [ -z "$TAGS" ]; then
echo "No git tags on HEAD, skipping tag builds"
exit 0
fi

while IFS= read -r tag; do
[ -z "$tag" ] && continue
# Strip leading 'v' from golang-style version tags
DOCKER_TAG="${tag#v}"
echo "Building image with tag: ${DOCKER_TAG}"
${{ inputs.extra-environment-vars }} \
DOCKER_TAG="${DOCKER_TAG}" \
DOCKER_REGISTRY="${DOCKER_REGISTRY}" \
DOCKER_REPOSITORY="${DOCKER_REPOSITORY}" \
IMAGE_NAME="${IMAGE_NAME}" \
make docker-build
done <<< "$TAGS"

- name: Push Docker image with branch tag
shell: bash
run: |
set -eu -o pipefail
BRANCH_NAME="${GITHUB_REF_NAME}"
DOCKER_REGISTRY="${{ inputs.docker-registry }}"
DOCKER_REPOSITORY="${{ inputs.docker-repository }}"
IMAGE_NAME="${{ inputs.image-name }}"

echo "Pushing image with branch tag: ${BRANCH_NAME}"
${{ inputs.extra-environment-vars }} \
DOCKER_TAG="${BRANCH_NAME}" \
DOCKER_REGISTRY="${DOCKER_REGISTRY}" \
DOCKER_REPOSITORY="${DOCKER_REPOSITORY}" \
IMAGE_NAME="${IMAGE_NAME}" \
make docker-push
Comment on lines +95 to +110

- name: Push Docker images for git tags
shell: bash
run: |
set -eu -o pipefail
DOCKER_REGISTRY="${{ inputs.docker-registry }}"
DOCKER_REPOSITORY="${{ inputs.docker-repository }}"
IMAGE_NAME="${{ inputs.image-name }}"

TAGS='${{ steps.git-tags.outputs.tags }}'
if [ -z "$TAGS" ]; then
echo "No git tags on HEAD, skipping tag pushes"
exit 0
fi

while IFS= read -r tag; do
[ -z "$tag" ] && continue
# Strip leading 'v' from golang-style version tags
DOCKER_TAG="${tag#v}"
echo "Pushing image with tag: ${DOCKER_TAG}"
${{ inputs.extra-environment-vars }} \
DOCKER_TAG="${DOCKER_TAG}" \
DOCKER_REGISTRY="${DOCKER_REGISTRY}" \
DOCKER_REPOSITORY="${DOCKER_REPOSITORY}" \
IMAGE_NAME="${IMAGE_NAME}" \
make docker-push
done <<< "$TAGS"

- name: Log out of Docker registry
if: always()
shell: bash
run: docker logout "${{ inputs.docker-registry }}"
68 changes: 68 additions & 0 deletions .github/actions/github-release-action/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<!--
SPDX-License-Identifier: Apache-2.0
SPDX-FileCopyrightText: 2026 The Linux Foundation
-->

# GitHub Release Action

A composite GitHub Action that creates GitHub releases with artifacts using the `gh` CLI tool.

## Description

Builds release artifacts via `make`, generates SHA256 checksums, and creates a GitHub release with all artifacts attached. Supports draft releases for pre-release versions.

## Usage

```yaml
- uses: ./.github/actions/github-release-action
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
```

### Inputs

| Input | Description | Required | Default |
|-------|-------------|----------|---------|
| `release-targets` | Make targets to build release artifacts | No | `release` |
| `artifact-glob` | Glob pattern for release artifacts | No | `release/*` |
| `github-token` | GitHub token for authentication | Yes | — |
| `draft` | Create a draft release | No | `false` |

Comment on lines +24 to +30
### Example Workflow

```yaml
name: Release
on:
push:
tags:
- "v*"

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: ./.github/actions/github-release-action
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
release-targets: "build package"
artifact-glob: "dist/*"
```

## How It Works

1. Finds a SemVer tag on HEAD (`vX.Y.Z`, `X.Y.Z`, or `vX.Y.Z-devN`)
2. Builds release artifacts using `make <release-targets>`
3. Generates SHA256 checksums for all matched artifacts
4. Creates a GitHub release with artifacts and checksums attached
5. Marks the release as draft if the tag contains `-dev` or `draft` input is `true`

## Requirements

- Repository must have a SemVer tag on the current commit
- A `Makefile` with the specified release target(s)
- `gh` CLI (pre-installed on GitHub Actions runners)
- `GITHUB_TOKEN` with permissions to create releases
80 changes: 80 additions & 0 deletions .github/actions/github-release-action/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
# SPDX-FileCopyrightText: 2026 The Linux Foundation
# SPDX-License-Identifier: Apache-2.0

name: "GitHub Release Action"
description: "Creates GitHub releases with artifacts using the gh CLI tool"

inputs:
release-targets:
description: "Make targets to build release artifacts"
required: false
default: "release"
artifact-glob:
description: "Glob pattern for release artifacts"
required: false
default: "release/*"
github-token:
description: "GitHub token for authentication"
required: true
draft:
description: "Create a draft release"
required: false
default: "false"

runs:
using: "composite"
steps:
- name: Create GitHub Release
shell: bash
env:
GITHUB_TOKEN: ${{ inputs.github-token }}
RELEASE_TARGETS: ${{ inputs.release-targets }}
ARTIFACT_GLOB: ${{ inputs.artifact-glob }}
DRAFT_INPUT: ${{ inputs.draft }}
run: |
set -eu -o pipefail

# Determine version from git tags on HEAD
VERSION=""
for tag in $(git tag --points-at HEAD); do
if echo "$tag" | grep -qE '^v?[0-9]+\.[0-9]+\.[0-9]+(-dev[0-9]+)?$'; then
VERSION="$tag"
break
fi
done

if [ -z "$VERSION" ]; then
echo "ERROR: No SemVer tag (vX.Y.Z, X.Y.Z, or vX.Y.Z-devN) found on HEAD"
exit 1
fi

echo "Version: $VERSION"

# Build release artifacts
make $RELEASE_TARGETS

# Generate SHA256 checksums for all artifacts
CHECKSUM_FILE="checksums-sha256.txt"
sha256sum $ARTIFACT_GLOB > "$CHECKSUM_FILE"
echo "Generated checksums:"
cat "$CHECKSUM_FILE"
Comment on lines +54 to +61

# Determine if this should be a draft release
DRAFT_FLAG=""
if [[ "$VERSION" == *"-dev"* ]] || [[ "$DRAFT_INPUT" == "true" ]]; then
DRAFT_FLAG="--draft"
echo "Creating draft release"
fi

# Get release notes from latest commit message
RELEASE_NOTES="$(git log -1 --pretty=%B)"

# Create GitHub release
gh release create "$VERSION" \
$ARTIFACT_GLOB \
"$CHECKSUM_FILE" \
--title "$VERSION" \
--notes "$RELEASE_NOTES" \
--generate-notes \
$DRAFT_FLAG
Comment on lines +74 to +80
Loading