diff --git a/.github/actions/build-and-push-dotnet/action.yaml b/.github/actions/build-and-push-dotnet/action.yaml new file mode 100644 index 0000000..ef0881b --- /dev/null +++ b/.github/actions/build-and-push-dotnet/action.yaml @@ -0,0 +1,183 @@ +name: Build and Push Docker Image (dotnet) +description: Build a Docker image and push to a registry (dotnet) +inputs: + registry: + description: Container registry hostname + required: true + image_name: + description: Full image name including registry + required: false + default: "" + tag: + description: Override image tag (defaults to standard tags) + required: false + default: "" + dockerfile: + description: Path to Dockerfile + required: false + default: Dockerfile + context: + description: Build context + required: false + default: . + push: + description: Push image after build + required: false + default: "true" + registry_username: + description: Registry username + required: true + registry_password: + description: Registry password or token + required: true + build_args: + description: Optional build args (newline-separated KEY=VALUE) + required: false + default: "" +runs: + using: "composite" + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Resolve image name + shell: bash + env: + REGISTRY: ${{ inputs.registry }} + IMAGE_NAME: ${{ inputs.image_name }} + REPO: ${{ gitea.repository != '' && gitea.repository || github.repository }} + run: | + if [ -z "${IMAGE_NAME}" ]; then + IMAGE_NAME="${REGISTRY}/${REPO}" + fi + echo "IMAGE_NAME=${IMAGE_NAME}" >> "$GITHUB_ENV" + + - name: Log in to container registry + uses: docker/login-action@v3 + with: + registry: ${{ inputs.registry }} + username: ${{ inputs.registry_username }} + password: ${{ inputs.registry_password }} + + - name: Validate registry configuration + shell: bash + env: + REGISTRY: ${{ inputs.registry }} + run: | + if [ -z "${REGISTRY}" ]; then + echo "::error::REGISTRY input is missing or empty" + exit 1 + fi + if [ -z "${IMAGE_NAME}" ] || [[ "${IMAGE_NAME}" == */ ]]; then + echo "::error::IMAGE_NAME is empty or malformed (resolved to '${IMAGE_NAME}')" + exit 1 + fi + + - name: Derive image tags + id: vars + shell: bash + env: + IMAGE_NAME: ${{ env.IMAGE_NAME }} + TAG_INPUT: ${{ inputs.tag }} + run: | + IMAGE="${IMAGE_NAME}" + TAGS=() + + if [ -n "${TAG_INPUT}" ]; then + TAGS+=("${IMAGE}:${TAG_INPUT}") + else + TAG_NAME="" + REF="${GITHUB_REF:-${GITEA_REF}}" + SHA="${GITHUB_SHA:-${GITEA_SHA}}" + BRANCH="" + SHORT_SHA="$(git rev-parse --short=7 "${SHA}")" + + # Extract tag name when we are on a tag ref (e.g. v1.4) + if [[ "${REF}" =~ refs/tags/(.+) ]]; then + TAG_NAME="${BASH_REMATCH[1]}" + fi + + if [[ "${REF}" =~ refs/heads/(.+) ]]; then + BRANCH="${BASH_REMATCH[1]}" + else + # Tag build: detect which branch contains the tagged commit + git fetch --no-tags --depth=1 origin main release develop || true + if git branch -r --contains "${SHA}" | grep -q "origin/main"; then + BRANCH="main" + elif git branch -r --contains "${SHA}" | grep -q "origin/release"; then + BRANCH="release" + elif git branch -r --contains "${SHA}" | grep -q "origin/develop"; then + BRANCH="develop" + fi + fi + + TAGS+=("${IMAGE}:${SHORT_SHA}") + [[ -n "${TAG_NAME}" ]] && TAGS+=("${IMAGE}:${TAG_NAME}") + + case "${BRANCH}" in + main) + TAGS+=("${IMAGE}:latest") + ;; + release*) + TAGS+=("${IMAGE}:latest-rc") + ;; + develop) + TAGS+=("${IMAGE}:latest-dev") + ;; + *) + TAGS+=("${IMAGE}:latest-snapshot") + ;; + esac + fi + + echo "Computed tags:" + printf '%s\n' "${TAGS[@]}" + { + echo "tags<> "$GITHUB_OUTPUT" + + - name: Show build summary + shell: bash + env: + IMAGE_NAME: ${{ env.IMAGE_NAME }} + run: | + echo "Commit: ${GITHUB_SHA:-${GITEA_SHA}}" + echo "Image: ${IMAGE_NAME}" + echo "Tags:" + printf '%s\n' "${{ steps.vars.outputs.tags }}" + + - name: Determine deploy target + id: deploy + shell: bash + run: | + REF="${GITHUB_REF:-${GITEA_REF}}" + SHA="${GITHUB_SHA:-${GITEA_SHA}}" + TARGET="dev" + if [[ "${REF}" == "refs/heads/main" ]]; then + TARGET="prod" + elif [[ "${REF}" =~ refs/tags/ ]]; then + # Tag builds deploy to prod only if the tagged commit is in main + git fetch --no-tags --depth=1 origin main || true + if git branch -r --contains "${SHA}" | grep -q "origin/main"; then + TARGET="prod" + fi + fi + echo "Deploy target: ${TARGET}" + echo "target=${TARGET}" >> "$GITHUB_OUTPUT" + + - name: Build and push image + uses: docker/build-push-action@v5 + with: + context: ${{ inputs.context }} + file: ${{ inputs.dockerfile }} + push: ${{ inputs.push }} + tags: ${{ steps.vars.outputs.tags }} + build-args: ${{ inputs.build_args }}