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
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
8 changes: 2 additions & 6 deletions .github/workflows/goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,15 @@ name: goreleaser

on:
release:
types: [draft, published]
types: [draft]

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
Loading
Loading