Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
8312c00
First pass at abstracting packages
ryapric Aug 31, 2025
fedb9db
Start work on adding Delivery tasks, which caused a lot of reorg
ryapric Sep 1, 2025
c0bd02d
WIP to introduce oscar config file
ryapric Sep 2, 2025
53cc04a
Merge branch 'main' into feature/wip
ryapric Sep 2, 2025
d640080
Add to-dos to the Roadmap
ryapric Sep 4, 2025
9bfcd51
WIP
ryapric Sep 8, 2025
28e4f9d
big ol' wipper to add YAML CI and refactor to add ctx
ryapric Sep 9, 2025
162574f
Delete VERSION file, add Draft field for GH Release struct
ryapric Sep 14, 2025
7f63447
Get all kinds of stuff working after a slight refactor caused a casca…
ryapric Sep 15, 2025
eb1d789
Empty commit to trigger workflow
ryapric Sep 15, 2025
f9dacf1
Try bumping the mise version that GHA uses
ryapric Sep 15, 2025
859f9e3
Consolidate some banner-printing behavior
ryapric Sep 15, 2025
8c057dc
More consolidation etc
ryapric Sep 15, 2025
d020082
More tidying up
ryapric Sep 15, 2025
bc15718
Fix to allow ripgrep to look at hidden files and folders. Also rename…
ryapric Sep 15, 2025
65f9839
holy crap i got image build and push working
ryapric Sep 15, 2025
64da11a
Commit a bad YAML file to test git-diff in CI
ryapric Sep 20, 2025
251d608
jfc i dont even know how many changes were in here
ryapric Sep 21, 2025
ef78f55
Also have goGenerate run formatters to prevent Git diffs
ryapric Sep 21, 2025
8f03ec7
Print Git info at the start of runs
ryapric Sep 21, 2025
fb4535c
oh great heavens I was using a global Python
ryapric Sep 21, 2025
8a22deb
omfg gha
ryapric Sep 21, 2025
b31b437
aint no way this works
ryapric Sep 21, 2025
93295c0
Unreal but ok
ryapric Sep 21, 2025
887235e
Test a tweak because I'm an idiot
ryapric Sep 21, 2025
1e6da61
Maybe some finishing work before moving to GHA changes
ryapric Sep 21, 2025
8adcaa8
First try of conditionally checking out the repo in GHA
ryapric Sep 21, 2025
2a26af1
oops
ryapric Sep 21, 2025
5a3fa7c
Empty commit to trigger workflow
ryapric Sep 21, 2025
00af898
so stupid
ryapric Sep 21, 2025
82eab43
Pull up conditional for delivery tasks
ryapric Sep 21, 2025
87db84a
jfc
ryapric Sep 21, 2025
d906115
Ok now temp-test perms etc while it's not on the main branch
ryapric Sep 21, 2025
5ded2a7
oook
ryapric Sep 21, 2025
f969ff4
GHA says the image build & push succeeded but I have no idea where it…
ryapric Sep 21, 2025
d381688
Remove debug logs and see if an existing GH Package can be pushed to,…
ryapric Sep 21, 2025
399753a
k well maybe it's because it's not on the main branch, idk, I'll figu…
ryapric Sep 21, 2025
143d398
Tidy up README, for now
ryapric Sep 21, 2025
a166a5c
Tidy up what I found reviewing the PR diff
ryapric Sep 21, 2025
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: 0 additions & 3 deletions .dockerignore

This file was deleted.

122 changes: 64 additions & 58 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
@@ -1,75 +1,81 @@
# I mostly copied this straight from here:
# https://docs.github.com/en/actions/publishing-packages/publishing-docker-images

name: main
---
name: "main"

on:
push:
branches:
- main
- "main"
pull_request:
branches:
- main
types:
- "opened"
- "reopened"
- "synchronize"

env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
MISE_GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"

jobs:
ci:
runs-on: ubuntu-latest
runs-on: "ubuntu-latest"
permissions:
contents: read
packages: write

contents: "read"
steps:
- name: Checkout repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # release v5.0.0
- name: Install system packages
- name: "Checkout PR branch"
if: "github.event_name == 'pull_request'"
uses: "actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8" # v5.0.0
with:
fetch-depth: 0
ref: "${{ github.event.pull_request.head.ref }}"
- name: "Checkout main branch"
if: "github.ref == 'refs/heads/main'"
uses: "actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8" # v5.0.0
with:
fetch-depth: 0
- name: "Install system packages"
run: |
sudo apt-get update
sudo apt-get install -y \
make
- name: Set up mise
uses: jdx/mise-action@5ac50f778e26fac95da98d50503682459e86d566 # release v3.2.0
- name: "Set up mise"
uses: "jdx/mise-action@5ac50f778e26fac95da98d50503682459e86d566" # v3.2.0
with:
version: "2025.8.1"
version: "2025.9.10"
install: true # runs `mise install`
cache: true
- name: Run CI
run: make ci

# - name: Set up Docker Buildx
# uses: docker/setup-buildx-action@v2

# - name: Log in to GHCR
# uses: docker/login-action@v2
# with:
# registry: ghcr.io
# username: ${{ github.repository_owner }}
# password: ${{ secrets.GITHUB_TOKEN }}

# # Generate any tags we want for the images (https://github.com/docker/build-push-action/blob/master/docs/advanced/tags-labels.md)
# - name: Extract metadata (tags, labels) for OCI image
# id: meta
# uses: docker/metadata-action@v4
# with:
# images: ghcr.io/opensourcecorp/oscar
# tags: |
# type=sha

# # non-mainline
# - name: Build and push non-mainline OCI image
# if: github.ref != 'refs/heads/main'
# uses: docker/build-push-action@v3
# with:
# context: .
# file: Containerfile
# push: true
# tags: ${{ steps.meta.outputs.tags }}

# # mainline
# - name: Build and push mainline OCI image
# if: github.ref == 'refs/heads/main'
# uses: docker/build-push-action@v3
# with:
# context: .
# file: Containerfile
# push: true
# tags: ghcr.io/opensourcecorp/oscar:latest
- name: "Run CI Tasks"
run: "make ci"
deliver:
if: "github.ref == 'refs/heads/main'"
runs-on: "ubuntu-latest"
permissions:
contents: "write"
packages: "write"
steps:
- name: "Checkout PR branch"
if: "github.event_name == 'pull_request'"
uses: "actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8" # v5.0.0
with:
fetch-depth: 0
ref: "${{ github.event.pull_request.head.ref }}"
- name: "Checkout main branch"
if: "github.ref == 'refs/heads/main'"
uses: "actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8" # v5.0.0
with:
fetch-depth: 0
- name: "Install system packages"
run: |
sudo apt-get update
sudo apt-get install -y \
make
- name: "Set up mise"
uses: "jdx/mise-action@5ac50f778e26fac95da98d50503682459e86d566" # v3.2.0
with:
version: "2025.9.10"
install: true # runs `mise install`
cache: true
- name: "Set up Docker"
uses: "docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435" # v3.11.1
- name: "Run Delivery Tasks"
run: "make deliver"
12 changes: 6 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
.oscar/
.vscode/
*cache*
*.log

*.out
build/
dist/
*.tar.gz
*.zip

.oscar/
*cache*
build/
dist/
mise.*.toml
scratch/
32 changes: 24 additions & 8 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,37 @@

## Workstation setup

`oscar`'s development leans heavily into using the root-level Makefile.
`oscar`'s development is the most consistent if you use the following:

Development of `oscar` is the most consistent if your workstation has [`mise`](https://mise.jdx.dev)
available on your `$PATH`. However, the Makefile's targets are configured to also allow for working
with most tooling natively, such as Go, if they are available.
* The root-level Makefile.
* [`mise`](https://mise.jdx.dev), via the root-level `mise.toml`.

While not strictly required, you will have a much better time if you leverage those. However, the
Makefile's targets are configured to also allow for working with most tooling natively, such as Go,
if they are available.

`mise` does not manage Docker Engine, however, so for targets like `make image` you will need to
ensure that you have a container runtime available (like Docker or Podman, overridable via the
`DOCKER` Make variable).
ensure that you have a container runtime available (like the ones for Docker or Podman). The default
command the Makefile tries to run is `docker`, which you can override via the `DOCKER` Make
variable.

## Contribution philosophy

`oscar` welcomes contributions, so long as they adhere to a few key rules:

* As a reminder, `oscar`'s runtime behavior is ***intentionally designed to be rigid***. If there is
a language or tool you would like to see added, then those contributions are welcome. Fundamental
changes to how `oscar` intends to operate, e.g. allowing for wholesale override of various
linters' settings, are not.
changes to how `oscar` intends to operate, e.g. allowing for user override of a linter's
line-length checks, or which directory `oscar` builds binaries into, are not.

* `hEy tHeRe'S a LoT oF sHeLL cOdE iN hErE?!` -- Correct. "Shelling out" is an intentional design
decision, and `oscar` calls out `bash` as a dependency.

## Adding support for a new Tool

To add a new Tool to `oscar`, it must:

* Define a non-exported struct, which embeds `taskutil.Tool`.
* That struct must implement the `taskutil.Tasker` interface.

See examples across the various `internal/tasks/tools/{lang}/*.go` files.
23 changes: 16 additions & 7 deletions Containerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ ARG https_proxy

FROM docker.io/library/golang:${GO_VERSION} AS builder

RUN apt-get update && apt-get install -y \
RUN apt-get update && apt-get install --no-install-recommends -y \
bash \
ca-certificates \
make
make \
&& \
rm -rf /var/lib/apt*

COPY . /go/app
WORKDIR /go/app
Expand All @@ -26,14 +28,16 @@ FROM docker.io/library/debian:13-slim AS ci

COPY --from=builder /go/app/build/oscar /oscar

RUN apt-get update && apt-get install -y \
RUN apt-get update && apt-get install --no-install-recommends -y \
bash \
ca-certificates \
curl \
git \
gnupg2 \
make \
rename
rename \
&& \
rm -rf /var/lib/apt/*

COPY . /go/app
WORKDIR /go/app
Expand All @@ -54,13 +58,15 @@ COPY --from=builder /go/app/build/oscar /oscar

# NOTE: Docker BuildKit will skip stages it doesn't see as dependencies, so to enforce the "ci"
# stage above to run, we need to force a dependency here
COPY --from=ci /go/app/VERSION /VERSION
COPY --from=ci /go/app/LICENSE /LICENSE

RUN apt-get update && apt-get install -y \
RUN apt-get update && apt-get install --no-install-recommends -y \
bash \
ca-certificates \
git \
gnupg2
gnupg2 \
&& \
rm -rf /var/lib/apt/*

# NOTE: when creating some shims, mise refers to itself assuming it is on the $PATH, so we need to
# symlink it out so it can do that
Expand All @@ -77,4 +83,7 @@ VOLUME /home/oscar/app
# oscar's home directory, for caching on the host
VOLUME /home/oscar/.oscar

# So e.g. GitHub can tie the image to its source repo
LABEL org.opencontainers.image.source https://github.com/opensourcecorp/oscar

ENTRYPOINT ["/oscar"]
66 changes: 21 additions & 45 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,60 +11,33 @@ BINNAME := oscar
BINPATH := ./cmd/$(BINNAME)

DOCKER ?= docker
OCI_REGISTRY ?= ghcr.io
OCI_REGISTRY_OWNER ?= opensourcecorp
export IMAGE_REGISTRY ?= ghcr.io
export IMAGE_REGISTRY_OWNER ?= opensourcecorp
export IMAGE_NAME ?= $(BINNAME)
export IMAGE_TAG ?= latest
export IMAGE_URI ?= $(IMAGE_REGISTRY)/$(IMAGE_REGISTRY_OWNER)/$(IMAGE_NAME):$(IMAGE_TAG)

SHELL = /usr/bin/env bash -euo pipefail

.PHONY: %

all: ci

FORCE:

ci: clean
@$(RUN) go run ./cmd/$(BINNAME)/main.go ci

deliver:
@$(RUN) go run ./cmd/$(BINNAME)/main.go deliver

# test is just an alias for ci
test: ci

ci-container:
@$(DOCKER) build \
--build-arg http_proxy="$${http_proxy}" \
--build-arg https_proxy="$${https_proxy}" \
--build-arg GO_VERSION="$$(awk '/^go/ { print $$2 }' go.mod)" \
-f ./Containerfile \
-t $(BINNAME)-test:latest \
.

build: clean
@mkdir -p ./build/$$($(RUN) go env GOOS)-$$($(RUN) go env GOARCH)
@$(RUN) go build -o ./build/$(BINNAME) $(BINPATH)
@printf 'built to %s\n' ./build/$(BINNAME)
# NOTE: oscar builds itself IRL, but having a target here makes it easier to have the Containerfile
# have a stage-copiable output
build: FORCE
@$(RUN) go build -o ./build/oscar ./cmd/oscar

xbuild: clean
@for target in \
darwin-amd64 \
darwin-arm64 \
linux-amd64 \
linux-arm64 \
; \
do \
GOOS=$$(echo "$${target}" | cut -d'-' -f1) ; \
GOARCH=$$(echo "$${target}" | cut -d'-' -f2) ; \
outdir=build/"$${GOOS}-$${GOARCH}" ; \
mkdir -p "$${outdir}" ; \
printf "Building for %s-%s into build/ ...\n" "$${GOOS}" "$${GOARCH}" ; \
GOOS="$${GOOS}" GOARCH="$${GOARCH}" $(RUN) go build -o "$${outdir}"/$(BINNAME) $(BINPATH) ; \
done

package: xbuild
@mkdir -p dist
@cd build || exit 1; \
for built in * ; do \
printf 'Packaging for %s into dist/ ...\n' "$${built}" ; \
cd $${built} && tar -czf ../../dist/$(BINNAME)_$${built}.tar.gz * && cd - >/dev/null ; \
done

clean:
clean: FORCE
@rm -rf \
/tmp/$(BINNAME)-tests \
./*cache* \
Expand All @@ -78,7 +51,10 @@ clean:
image: clean
@export BUILDKIT_PROGRESS=plain && \
export GO_VERSION="$$(awk '/^go/ { print $$2 }' go.mod)" && \
$(DOCKER) compose build
$(RUN) $(DOCKER) compose build

run-image: FORCE
@$(RUN) $(DOCKER) compose run $(BINNAME)

run-image:
@$(DOCKER) compose run $(BINNAME)
generate: FORCE
@cd ./proto && $(RUN) buf generate
Loading