Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
5 changes: 0 additions & 5 deletions .github/workflows/codeowners.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@ jobs:
with:
fetch-depth: 0

- name: 'Update action.yml to build locally'
run: |
sed -i "s/image: .*/image: 'Dockerfile'/" action.yml
cat action.yml

- name: 'Codeowners Plus'
id: codeowners-plus
uses: ./
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- name: 'Set up Go'
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
with:
go-version: '1.26'
go-version-file: go.mod

- name: 'Build'
run: go build -v ./...
Expand All @@ -37,7 +37,7 @@ jobs:
- name: 'Set up Go'
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
with:
go-version: '1.26'
go-version-file: go.mod

- name: 'Golangci-lint'
uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0
6 changes: 1 addition & 5 deletions .github/workflows/goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,11 @@ on:

permissions: {}

env:
DOCKER_BUILDKIT: 1

jobs:
goreleaser:
runs-on: ubuntu-latest
permissions:
contents: write
packages: write

steps:
- name: Checkout
Expand All @@ -25,7 +21,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
with:
go-version: 1.26
go-version-file: go.mod

- name: Run GoReleaser
uses: goreleaser/goreleaser-action@5daf1e915a5f0af01ddbcd89a43b8061ff4f1a89 # v7
Expand Down
34 changes: 0 additions & 34 deletions .github/workflows/publish.yml

This file was deleted.

25 changes: 0 additions & 25 deletions Dockerfile

This file was deleted.

85 changes: 83 additions & 2 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,88 @@ inputs:
outputs:
data:
description: 'JSON string containing all the codeowners data (success, message, file-owners, file-optional, still-required)'
value: ${{ steps.run.outputs.data }}

runs:
using: 'docker'
image: 'docker://ghcr.io/multimediallc/codeowners-plus:latest'
using: 'composite'
steps:
- name: 'Resolve codeowners-plus binary'
id: resolve
shell: bash
env:
# The release tag this commit belongs to. Non-empty only in release
# commits: set by scripts/prepare-release.sh and cleared by
# scripts/post-release.sh. When set, the action downloads that
# release's prebuilt binary; when empty (any non-release ref) it
# builds from the checked-out source.
RELEASE_VERSION: ''
run: |
set -euo pipefail
{
echo "release-version=${RELEASE_VERSION}"
echo "bin=${RUNNER_TEMP:-/tmp}/codeowners-plus-action/codeowners-plus"
} >>"$GITHUB_OUTPUT"

# RELEASE_VERSION not set -> not a release: build from source (cached).
- name: 'Restore cached built binary'
id: buildcache
if: steps.resolve.outputs.release-version == ''

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want to try to restore the cache regardless of if built from source or pulled from github.

uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ steps.resolve.outputs.bin }}
key: codeowners-plus-build-${{ github.action_ref || github.sha }}-${{ runner.os }}-${{ runner.arch }}

- name: 'Set up Go'
if: steps.resolve.outputs.release-version == '' && steps.buildcache.outputs.cache-hit != 'true'
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
with:
go-version-file: ${{ github.action_path }}/go.mod
cache-dependency-path: ${{ github.action_path }}/go.sum

- name: 'Build codeowners-plus from source'
if: steps.resolve.outputs.release-version == '' && steps.buildcache.outputs.cache-hit != 'true'
shell: bash
env:
ACTION_PATH: ${{ github.action_path }}
BIN: ${{ steps.resolve.outputs.bin }}
run: |
set -euo pipefail
mkdir -p "$(dirname "${BIN}")"
cd "${ACTION_PATH}"
CGO_ENABLED=0 \
go build -trimpath -buildvcs=false -ldflags="-s -w" -o "${BIN}" .

# RELEASE_VERSION set -> a release: download + verify the prebuilt binary (cached).
- name: 'Restore cached release binary'
id: bincache
if: steps.resolve.outputs.release-version != ''

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think caching after having built from source is the most impactful time to cache. Otherwise non-release shas need to build everytime.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added caching back to the builds - that was an oversight

uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ steps.resolve.outputs.bin }}
key: codeowners-plus-action-${{ steps.resolve.outputs.release-version }}-${{ runner.os }}-${{ runner.arch }}

Comment on lines +81 to +89

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need a separate cache action for build vs download, the cached path is the same.

- name: 'Download codeowners-plus release binary'
if: steps.resolve.outputs.release-version != '' && steps.bincache.outputs.cache-hit != 'true'
shell: bash
env:
REPO: ${{ github.action_repository }}
ACTION_PATH: ${{ github.action_path }}
TAG: ${{ steps.resolve.outputs.release-version }}
BIN: ${{ steps.resolve.outputs.bin }}
run: '"${ACTION_PATH}/scripts/install-action.sh"'

- name: 'Run codeowners-plus'
id: run
shell: bash
env:
# The hyphenated INPUT_GITHUB-TOKEN name is intentional: it mirrors
# what Docker actions export and is exactly what main.go reads via
# os.LookupEnv. Bash passes non-identifier env vars through to child
# processes untouched.
INPUT_GITHUB-TOKEN: ${{ inputs.github-token }}
INPUT_PR: ${{ inputs.pr }}
INPUT_REPOSITORY: ${{ inputs.repository }}
INPUT_VERBOSE: ${{ inputs.verbose }}
INPUT_QUIET: ${{ inputs.quiet }}
BIN: ${{ steps.resolve.outputs.bin }}
run: '"${BIN}"'
8 changes: 0 additions & 8 deletions entrypoint.sh

This file was deleted.

2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module github.com/multimediallc/codeowners-plus

go 1.25.0

toolchain go1.26.4

require (
github.com/bmatcuk/doublestar/v4 v4.10.0
github.com/boyter/gocodewalker v1.5.1
Expand Down
24 changes: 23 additions & 1 deletion goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,37 @@ builds:
goarch:
- amd64
- arm64
# The binary the GitHub Action downloads and runs (root main.go).
- id: "action"
main: .
binary: codeowners-plus-action
env:
- CGO_ENABLED=0
ldflags:
- -s
- -w
goos:
- linux
- darwin
goarch:
- amd64
- arm64
archives:
- name_template: >-
- id: "cli"
ids: ["cli"]
name_template: >-
{{ .ProjectName }}_{{ .Version }}_{{ title .Os }}_
{{- if eq .Arch "amd64" }}x86_64
{{- else if eq .Arch "386" }}i386
{{- else }}{{ .Arch }}{{ end }}
{{- if .Arm }}v{{ .Arm }}{{ end -}}
files:
- none*
- id: "action"
ids: ["action"]
name_template: "codeowners-plus-action_{{ .Os }}_{{ .Arch }}"
files:
- none*
checksum:
name_template: 'checksums.txt'
snapshot:
Expand Down
95 changes: 95 additions & 0 deletions scripts/install-action.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#! /usr/bin/env bash
# Installs the prebuilt codeowners-plus binary for the current platform,
# verified against the release's checksums.txt.
#
# Local use (all env vars optional):
# scripts/install-action.sh # latest release -> ./codeowners-plus
# VERSION=v1.9.1 scripts/install-action.sh # a specific release
# BIN=/usr/local/bin/codeowners-plus scripts/install-action.sh
# curl -fsSL https://raw.githubusercontent.com/multimediallc/codeowners-plus/main/scripts/install-action.sh | bash
#
# Overrides: REPO, VERSION (or TAG), OS, ARCH, BIN. action.yml passes
# REPO/TAG/BIN; OS and ARCH are detected here so the script is self-contained.

set -eu

REPO="${REPO:-multimediallc/codeowners-plus}"
BIN="${BIN:-./codeowners-plus}"
TAG="${TAG:-${VERSION:-}}"

# Detect OS unless overridden. Tokens match goreleaser's {{ .Os }}.
OS="${OS:-}"
if [ -z "${OS}" ]; then
case "$(uname -s)" in
Linux) OS="linux" ;;
Darwin) OS="darwin" ;;
*)
echo "Error: unsupported OS '$(uname -s)' (supported: linux, darwin)." >&2
exit 1
;;
esac
fi

# Detect ARCH unless overridden. Tokens match goreleaser's {{ .Arch }}.
ARCH="${ARCH:-}"
if [ -z "${ARCH}" ]; then
case "$(uname -m)" in
x86_64 | amd64) ARCH="amd64" ;;
arm64 | aarch64) ARCH="arm64" ;;
*)
echo "Error: unsupported arch '$(uname -m)' (supported: amd64, arm64)." >&2
exit 1
;;
esac
fi

# Default to the latest release when no version was requested.
if [ -z "${TAG}" ]; then
TAG="$(curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" \
| awk -F'"' '/"tag_name":/ {print $4; exit}')"
if [ -z "${TAG}" ]; then
echo "Error: could not determine the latest release of ${REPO}." >&2
exit 1
fi
fi

asset="codeowners-plus-action_${OS}_${ARCH}.tar.gz"
binname="codeowners-plus-action"
base="https://github.com/${REPO}/releases/download/${TAG}"
tmp="$(mktemp -d)"
trap 'rm -rf "${tmp}"' EXIT

echo "Downloading ${asset} from ${REPO} release ${TAG}" >&2
curl -fsSL --retry 3 -o "${tmp}/${asset}" "${base}/${asset}"
curl -fsSL --retry 3 -o "${tmp}/checksums.txt" "${base}/checksums.txt"

echo "Verifying ${asset} against checksums.txt" >&2
expected="$(awk -v a="${asset}" '$2 == a {print $1}' "${tmp}/checksums.txt")"
if [ -z "${expected}" ]; then
echo "Error: ${asset} not found in checksums.txt" >&2
exit 1
fi
# Guard against a malformed digest: '<checker> -c' treats an improperly
# formatted line as a skipped (passing) entry rather than a failure.
if ! printf '%s' "${expected}" | grep -Eq '^[0-9a-f]{64}$'; then
echo "Error: invalid checksum for ${asset} in checksums.txt" >&2
exit 1
fi
# sha256sum is GNU coreutils (Linux); macOS only ships shasum.
if command -v sha256sum >/dev/null 2>&1; then
verify=(sha256sum -c -)
else
verify=(shasum -a 256 -c -)
fi
if ! echo "${expected} ${tmp}/${asset}" | "${verify[@]}"; then
echo "Error: downloaded ${asset} does not match its release checksum" >&2
exit 1
fi

echo "Extracting ${binname} from ${asset}" >&2
tar -xzf "${tmp}/${asset}" -C "${tmp}" "${binname}"

mkdir -p "$(dirname "${BIN}")"
mv "${tmp}/${binname}" "${BIN}"
chmod +x "${BIN}"
echo "Installed codeowners-plus ${TAG} to ${BIN}" >&2
12 changes: 7 additions & 5 deletions scripts/post-release.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#! /usr/bin/env bash

set -e
set -u
set -eu

ACTIONS_FILE="action.yml"
CLI_TOOL_FILE="tools/cli/main.go"
README_FILE="README.md"

Expand Down Expand Up @@ -39,23 +39,25 @@ else
git checkout -b "${BRANCH_NAME}"
fi

echo "Updating ${CLI_TOOL_FILE} and ${README_FILE}..."
echo "Updating ${ACTIONS_FILE}, ${CLI_TOOL_FILE}, and ${README_FILE}..."

# sed -i works differently on macOS and Linux.
# For GNU sed (Linux), -i without an argument is fine.
# For BSD sed (macOS), -i requires an argument (even if empty string for no backup).
if sed --version 2>/dev/null | grep -q GNU; then # GNU sed
sed -i "s|RELEASE_VERSION: '.*'|RELEASE_VERSION: ''|g" "${ACTIONS_FILE}"
sed -i "s|Version: .*|Version: \"${DEV_TAG}\",|g" "${CLI_TOOL_FILE}"
sed -i "s|codeowners-plus@.*|codeowners-plus@${VERSION_TAG}|g" "${README_FILE}"
else # BSD sed (macOS)
sed -i '' "s|RELEASE_VERSION: '.*'|RELEASE_VERSION: ''|g" "${ACTIONS_FILE}"
sed -i '' "s|Version: .*|Version: \"${DEV_TAG}\",|g" "${CLI_TOOL_FILE}"
sed -i '' "s|codeowners-plus@.*|codeowners-plus@${VERSION_TAG}|g" "${README_FILE}"
fi
gofmt -w tools/cli
echo "${CLI_TOOL_FILE} and ${README_FILE} updated."
echo "${ACTIONS_FILE}, ${CLI_TOOL_FILE}, and ${README_FILE} updated."

echo "Committing changes..."
git add "${CLI_TOOL_FILE}" "${README_FILE}"
git add "${ACTIONS_FILE}" "${CLI_TOOL_FILE}" "${README_FILE}"
git commit -m "${VERSION_TAG}"

echo "--- Post release process completed successfully! ---"
Expand Down
Loading
Loading