Skip to content
Merged
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
3 changes: 2 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

# Include
!Dockerfile
!entrypoint.sh
!LICENSE
!README.md
!entrypoint.sh
!pip
3 changes: 2 additions & 1 deletion .github/workflows/auto-pull-request-create.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
name: (Auto) Pull Request Create
name: (Automatic) Pull Request Create

on:
push:
branches-ignore:
- master
- main
- release/**
- dependabot/**

permissions:
Expand Down
32 changes: 32 additions & 0 deletions .github/workflows/auto-release-create.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: (Automatic) Release Create

on:
push:
branches:
- master
- main
workflow_dispatch:
inputs:
release_branch:
description: Release branch to publish from (e.g. release/v1.3.0)
required: false
default: ''
type: string
release_version:
description: Explicit release version override (e.g. v1.3.0)
required: false
default: ''
type: string

permissions:
contents: write
pull-requests: read

jobs:
call:
uses: devops-infra/.github/.github/workflows/reusable-auto-release-create.yml@v1
with:
profile: actions
release-branch: ${{ inputs.release_branch }}
release-version: ${{ inputs.release_version }}
secrets: inherit
39 changes: 39 additions & 0 deletions .github/workflows/manual-release-branch-prepare.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: (Manual) Release Branch Prepare

on:
workflow_dispatch:
inputs:
type:
description: Bump type
required: false
default: patch
type: choice
options:
- patch
- minor
- major
- set
version:
description: Explicit version when type="set" (e.g., v1.2.3)
required: false
default: ''
build_only:
description: Build and push artifacts without version bump
required: false
default: false
type: boolean

permissions:
contents: write
packages: write
pull-requests: write

jobs:
call:
uses: devops-infra/.github/.github/workflows/reusable-manual-release-branch-prepare.yml@v1
with:
bump-type: ${{ inputs.type }}
explicit-version: ${{ inputs.version }}
build-and-push-only: ${{ inputs.build_only }}
profile: actions
secrets: inherit
9 changes: 8 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Intellij
/.idea/
.idea/
*.iml

# Custom
Expand All @@ -10,3 +10,10 @@
.envrc
.env
.tmp

# Python
build/
dist/
*.egg-info/
*.pyc
__py
203 changes: 12 additions & 191 deletions Taskfile.cicd.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
version: '3'

silent: true

vars:
PR_TEMPLATE: https://raw.githubusercontent.com/devops-infra/.github/refs/tags/v1/PULL_REQUEST_TEMPLATE.md
CONFIGS_BASE_URL: https://raw.githubusercontent.com/devops-infra/.github/refs/tags/v1/templates/actions/configs
TASKFILES_BASE_URL: https://raw.githubusercontent.com/devops-infra/.github/refs/tags/v1/templates/actions/taskfiles

tasks:
pre-commit:
desc: Run all pre-commit hooks
Expand All @@ -29,97 +26,32 @@ tasks:
lint:actionlint:
desc: Lint GitHub Actions workflows with actionlint
cmds:
- |
echo "▶️ Running actionlint..."
set +e
docker run --rm -i -v "$PWD:/work" -w /work rhysd/actionlint:latest -color
rc=$?
set -e
if [ "$rc" -eq 0 ]; then
echo "✅ actionlint passed"
else
echo "❌ actionlint failed"
exit $rc
fi
- task: scripts:lint:actionlint

lint:hadolint:
desc: Lint Dockerfile with hadolint
cmds:
- |
echo "▶️ Running hadolint..."
set +e
docker run --rm -i -v "$PWD:/work" -w /work hadolint/hadolint:latest-debian < Dockerfile
rc=$?
set -e
if [ "$rc" -eq 0 ]; then
echo "✅ hadolint passed"
else
echo "❌ hadolint failed"
exit $rc
fi
- task: scripts:lint:hadolint

lint:shellcheck:
desc: Lint shell scripts with shellcheck
cmds:
- |
echo "▶️ Running shellcheck..."
set +e
docker run --rm -i -v "$PWD:/work" -w /work koalaman/shellcheck:stable -x -S style entrypoint.sh
rc=$?
set -e
if [ "$rc" -eq 0 ]; then
echo "✅ shellcheck passed"
else
echo "❌ shellcheck failed"
exit $rc
fi
- task: scripts:lint:shellcheck

lint:yamllint:
desc: Lint YAML files with yamllint
cmds:
- |
echo "▶️ Running yamllint..."
set +e
docker run --rm -i -v "$PWD:/work" -w /work cytopia/yamllint -c .yamllint.yml .
rc=$?
set -e
if [ "$rc" -eq 0 ]; then
echo "✅ yamllint passed"
else
echo "❌ yamllint failed"
exit $rc
fi
- task: scripts:lint:yamllint

dependency:update:
desc: Check main dependency not covered by dependabot
desc: 'No-op: no dedicated dependency updater configured for this profile'
cmds:
- |
echo "ℹ️ No dedicated dependency updater configured for this repository."
echo "ℹ️ Dependabot handles GitHub Actions and package metadata updates."
echo "ℹ️ Docker build validation remains the runtime safety net."
- task: scripts:dependency:update

version:set:
desc: Update version in README.md and action.yml
cmds:
- |
if [ -z "{{.VERSION}}" ]; then
echo "❌ ERROR: VERSION is empty"
exit 1
fi
if ! echo "{{.VERSION}}" | grep -Eq '^v?[0-9]+\.[0-9]+\.[0-9]+$'; then
echo "❌ ERROR: VERSION '{{.VERSION}}' is not a valid semantic version (expected vX.Y.Z or X.Y.Z)"
exit 1
fi
- echo Updating full version from {{.VERSION_FROM_ACTION_YML}} to {{.VERSION}}
- echo Updating minor version from {{.MINOR_FROM_ACTION_YML}} to {{.VERSION_MINOR}}
- echo Updating major version from {{.MAJOR_FROM_ACTION_YML}} to {{.VERSION_MAJOR}}
- "{{.SED}} -i 's#{{.DOCKER_NAME}}:{{.VERSION_FROM_ACTION_YML}}#{{.DOCKER_NAME}}:{{.VERSION}}#g' action.yml"
- "{{.SED}} -i 's#{{.DOCKER_NAME}}@{{.VERSION_FROM_ACTION_YML}}#{{.DOCKER_NAME}}@{{.VERSION}}#g' README.md"
- "{{.SED}} -i 's#{{.GITHUB_NAME}}@{{.VERSION_FROM_ACTION_YML}}#{{.GITHUB_NAME}}@{{.VERSION}}#g' README.md"
- "{{.SED}} -i 's#{{.DOCKER_NAME}}@{{.MINOR_FROM_ACTION_YML}}#{{.DOCKER_NAME}}@{{.VERSION_MINOR}}#g' README.md"
- "{{.SED}} -i 's#{{.GITHUB_NAME}}@{{.MINOR_FROM_ACTION_YML}}#{{.GITHUB_NAME}}@{{.VERSION_MINOR}}#g' README.md"
- "{{.SED}} -i 's#{{.DOCKER_NAME}}@{{.MAJOR_FROM_ACTION_YML}}#{{.DOCKER_NAME}}@{{.VERSION_MAJOR}}#g' README.md"
- "{{.SED}} -i 's#{{.GITHUB_NAME}}@{{.MAJOR_FROM_ACTION_YML}}#{{.GITHUB_NAME}}@{{.VERSION_MAJOR}}#g' README.md"
- task: scripts:version:set

version:update:patch:
desc: Increment patch version (e.g., 1.2.3 -> 1.2.4)
Expand All @@ -139,135 +71,24 @@ tasks:
version:resolve-next:
desc: Resolve next version from bump type and profile
cmds:
- |
set -eu
bump_type="${BUMP_TYPE:-patch}"
input_version="${INPUT_VERSION:-}"

normalize_version() {
candidate="${1#v}"
if ! printf "%s" "${candidate}" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; then
return 1
fi
printf "v%s" "${candidate}"
}

current="$(task version:get 2>/dev/null || true)"

case "$bump_type" in
set)
[ -n "$input_version" ] || { echo "Missing version for type=set"; exit 1; }
next="$(normalize_version "$input_version")" || {
echo "Invalid explicit version: $input_version. Expected vX.Y.Z or X.Y.Z"
exit 1
}
;;
patch|minor|major)
[ -n "$current" ] || { echo "Current version not found or invalid. Expected vX.Y.Z"; exit 1; }
current="$(normalize_version "$current")" || { echo "Current version not found or invalid. Expected vX.Y.Z"; exit 1; }
no_v="${current#v}"
major="$(printf "%s" "$no_v" | awk -F. '{print $1}')"
minor="$(printf "%s" "$no_v" | awk -F. '{print $2}')"
patch="$(printf "%s" "$no_v" | awk -F. '{print $3}')"
case "$bump_type" in
patch) next="v${major}.${minor}.$((patch + 1))" ;;
minor) next="v${major}.$((minor + 1)).0" ;;
major) next="v$((major + 1)).0.0" ;;
esac
;;
*)
echo "Unknown type: $bump_type"
exit 1
;;
esac

printf "%s" "$next"
- task: scripts:version:resolve-next

version:tag-release:
desc: Create set of git tags
cmds:
- |
set -eu
if (set -o | grep -q pipefail) 2>/dev/null; then set -o pipefail; fi

REMOTE='origin'
FULL='{{.VERSION_FULL}}'
MINOR='{{.VERSION_MINOR}}'
MAJOR='{{.VERSION_MAJOR}}'

# Validate vX.Y.Z
if ! printf "%s" "$FULL" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
echo "❌ ERROR: VERSION '$FULL' must match vX.Y.Z" >&2
exit 1
fi

tag_sha() { git rev-parse "refs/tags/$1" 2>/dev/null || true; }
remote_tag_sha() { git ls-remote --tags "$REMOTE" "refs/tags/$1" 2>/dev/null | awk '{print $1}' || true; }

echo "ℹ️ INFO: Tags - Full: $FULL | Minor: $MINOR | Major: $MAJOR"

# Full tag: must NOT exist on remote; fail fast if it does
full_remote_sha="$(remote_tag_sha "$FULL")"
if [ -n "$full_remote_sha" ]; then
echo "❌ ERROR: Full tag '$FULL' already exists on remote; aborting" >&2
exit 1
fi

# Create full tag locally (if missing) and push
if git rev-parse --quiet --verify "refs/tags/$FULL" >/dev/null 2>&1; then
echo "ℹ️ INFO: Full tag '$FULL' exists locally but not on remote; pushing"
else
echo "ℹ️ INFO: Creating full tag '$FULL'"
git tag --annotate "$FULL" --message "$FULL"
fi
git push "$REMOTE" "refs/tags/$FULL"
echo "✅ OK: Pushed full tag '$FULL'"

# Minor tag: create or update
git tag --force --annotate "$MINOR" --message "$FULL"
minor_local_sha="$(tag_sha "$MINOR")"
minor_remote_sha="$(remote_tag_sha "$MINOR")"
if [ -z "$minor_remote_sha" ]; then
git push "$REMOTE" "refs/tags/$MINOR"
echo "✅ OK: Created and pushed minor tag '$MINOR' -> $minor_local_sha"
else
if [ "$minor_local_sha" != "$minor_remote_sha" ]; then
echo "⚠️ WARN: Updating remote minor tag '$MINOR' to $minor_local_sha (was $minor_remote_sha)"
git push --force "$REMOTE" "refs/tags/$MINOR"
else
echo "ℹ️ INFO: Minor tag '$MINOR' already up-to-date"
fi
fi

# Major tag: create or update
git tag --force --annotate "$MAJOR" --message "$FULL"
major_local_sha="$(tag_sha "$MAJOR")"
major_remote_sha="$(remote_tag_sha "$MAJOR")"
if [ -z "$major_remote_sha" ]; then
git push "$REMOTE" "refs/tags/$MAJOR"
echo "✅ OK: Created and pushed major tag '$MAJOR' -> $major_local_sha"
else
if [ "$major_local_sha" != "$major_remote_sha" ]; then
echo "⚠️ WARN: Updating remote major tag '$MAJOR' to $major_local_sha (was $major_remote_sha)"
git push --force "$REMOTE" "refs/tags/$MAJOR"
else
echo "ℹ️ INFO: Major tag '$MAJOR' already up-to-date"
fi
fi
- task: scripts:version:tag-release

git:get-pr-template:
desc: Get pull request template
cmds:
- mkdir -p .tmp
- curl -LsS {{.PR_TEMPLATE}} -o .tmp/PULL_REQUEST_TEMPLATE.md
- task: scripts:git:get-pr-template

git:set-config:
desc: Set git user config
cmds:
- git config user.name "github-actions[bot]"
- git config user.email "github-actions[bot]@users.noreply.github.com"
- task: scripts:git:set-config

version:get:
desc: Get current version
cmds:
- echo "{{.VERSION}}"
- task: scripts:version:get
Loading
Loading