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
16 changes: 16 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
name: Bug Report
about: Report a bug
labels: kind/bug

---

**What happened**:

**What you expected to happen**:

**How to reproduce it (as minimally and precisely as possible)**:

**Anything else we need to know**:

**Environment**:
10 changes: 10 additions & 0 deletions .github/ISSUE_TEMPLATE/enhancement_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
name: Enhancement Request
about: Suggest an enhancement
labels: kind/enhancement

---

**What would you like to be added**:

**Why is this needed**:
20 changes: 20 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
**What this PR does / why we need it**:

**Which issue(s) this PR fixes**:
Fixes #

**Special notes for your reviewer**:

**Release note**:
<!-- Write your release note:
1. Enter your release note in the below block.
2. If no release note is required, just write "NONE" within the block.

Format of block header: <category> <target_group>
Possible values:
- category: breaking|feature|bugfix|doc|other
- target_group: user|operator|developer|dependency
-->
```feature user

```
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# editor and IDE paraphernalia
/.vscode
/.idea
6 changes: 4 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

## Code of Conduct

All members of the project community must abide by the [SAP Open Source Code of Conduct](https://github.com/SAP/.github/blob/main/CODE_OF_CONDUCT.md).
All members of the project community must abide by the [SAP Open Source Code of Conduct](https://github.com/openmcp-project/.github/blob/main/CODE_OF_CONDUCT.md).
Only by respecting each other we can develop a productive, collaborative community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting [a project maintainer](.reuse/dep5).
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [[email protected]](mailto:[email protected]) (SAP Open Source Program Office). All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the reporter of any incident.

## Engaging in Our Project

Expand Down
12 changes: 12 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Use distroless as minimal base image to package the component binary
# Refer to https://github.com/GoogleContainerTools/distroless for more details
FROM gcr.io/distroless/static-debian12:nonroot
ARG TARGETOS
ARG TARGETARCH
ARG COMPONENT
WORKDIR /
COPY bin/$COMPONENT.$TARGETOS-$TARGETARCH /<component>
USER 65532:65532

# docker doesn't substitue args in ENTRYPOINT, so we replace this during the build script
ENTRYPOINT ["/<component>"]
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
%:
@echo "This repository uses task (https://taskfile.dev) instead of make."
@echo "Run 'go install github.com/go-task/task/v3/cmd/task@latest' to install the latest version."
@echo "Then run 'task -l' to list available tasks."
166 changes: 163 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,169 @@

OpenMCP build and CI scripts

## Requirements and Setup
The Kubernetes operators in the openmcp-project use mostly the same `make` targets and surrounding scripts. This makes sense, because this way developers do not have to think about in which repo they are working right now - `make tidy` will always tidy the go modules.
The drawback is that all `make` targets and scripts have to be kept in sync. If the `make` targets have the same name but a different behavior (conceptually, not code-wise), this will became more of an disadvantage than an advantage. This 'keeping it in sync' means that adding an improvement to any of the scripts required this improvement to be added to all of the script's copies in the different repositories, which is annoying and error-prone.

*Insert a short description what is required to get your project running...*
To improve this, the scripts that are shared between the different repositories have been moved into this repository, which is intended to be used as a git submodule in the actual operator repositories.

Instead of `make`, we have decided to use the [task](https://taskfile.dev/) tool.

## Requirements

It is strongly recommended to include this submodule under the `hack/common` path in the operator repositories. While most of the coding is designed to work from anywhere within the including repository, there are some workarounds for bugs in `task` which rely on the assumption that this repo is a submodule under `hack/common` in the including repository.

## Setup

To use this repository, first check it out via
```shell
git submodule add https://github.com/openmcp-project/build.git hack/common
```
and ensure that it is checked-out via
```shell
git submodule init
```

### Taskfile

To use the generic Taskfile contained in this repository, create a `Taskfile.yaml` in the including repository. It should look something like this:
```yaml
version: 3

vars:
NESTED_MODULES: api
API_DIRS: '{{.ROOT_DIR}}/api/core/v1alpha1/...'
MANIFEST_OUT: '{{.ROOT_DIR}}/api/crds/manifests'
CODE_DIRS: '{{.ROOT_DIR}}/cmd/... {{.ROOT_DIR}}/internal/... {{.ROOT_DIR}}/test/... {{.ROOT_DIR}}/api/constants/... {{.ROOT_DIR}}/api/errors/... {{.ROOT_DIR}}/api/install/... {{.ROOT_DIR}}/api/v1alpha1/... {{.ROOT_DIR}}/api/core/v1alpha1/...'
COMPONENTS: 'mcp-operator'
REPO_NAME: 'https://github.com/openmcp-project/mcp-operator'
GENERATE_DOCS_INDEX: "true"

includes:
shared:
taskfile: hack/common/Taskfile_controller.yaml
flatten: true
```

⚠️⚠️⚠️ There is currently a [bug](https://github.com/go-task/task/issues/2108) in the `task` tool which causes it to not propagate variables from the top-level `vars` field to the included Taskfiles properly. As a workaround, the variables have to be specified in `includes.*.vars` instead.

> `ROOT_DIR` is a task-internal variable that points to the directory of the root Taskfile.

Since the imported Taskfile is generic, there are a few variables that need to be set in order to configure the tasks correctly. Unless specified otherwise, the variables must not be specified if their respective purpose doesn't apply to the importing repository (e.g. `NESTED_MODULES` is not required if there are no nested modules).
- `NESTED_MODULES`
- List of nested modules, separated by spaces.
- Note that the module has to be located in a subfolder that matches its name.
- Required for multiple tools from the golang environment which are able to work on a single module only and therefore have to be called once per go module.
- `API_DIRS`
- List of files with API type definitions for which k8s CRDs should be generated.
- The `<directory>/...` syntax can be used to refer to all files in the directory and its subdirectories.
- This is fed into the k8s code generation tool for CRD generation.
- `MANIFEST_OUT`
- Directory where the generated CRDs should be put in.
- `CODE_DIRS`
- List of files with go code, separated by spaces.
- The `<directory>/...` syntax can be used to refer to all files in the directory and its subdirectories.
- Formatting and linting checks are executed on these files.
- This variable must always be specified.
- `COMPONENTS`
- A list of 'components' contained in this repository, separated by spaces.
- This is relevant for binary, image, chart, and OCM component building. Each entry will result in a separate build artifact for the respective builds.
- A 'component' specified here has some implications:
- A `cmd/<component>/main.go` file is expected for binary builds.
- A separate docker image will be built for each component.
- If the component has a helm chart, it is expected under `charts/<component>/`.
- Note that support for helm charts is not fully implemented yet.
- Each component will get its own OCM component.
- Note that support for OCM components is not implemented yet.
- Library repos will not have any component, operator repos will mostly contain just a single component (the operator itself).
- `REPO_URL`
- URL of the github repository that contains the Taskfile.
- This is used for building the OCM component, which will fail if it is not specified.
- `GENERATE_DOCS_INDEX`
- If this is set and its value is not `false`, the `generate:docs` target will generate a documentation index at `docs/README.md`. Otherwise, the task is skipped.
- See below for a short documentation of the the index generation.

There are two main Taskfiles, one of which should be included:
- `Taskfile_controller.yaml` is meant for operator repositories and contains task definitions for code generation and validation, binary builds, and image builds.
- `Taskfile_library.yaml` is meant for library repos and does not include the tasks for binary and image building.

A minimal Taskfile for a library repository could look like this:
```yaml
version: 3

vars:
CODE_DIRS: '{{.ROOT_DIR}}/pkg/...'

includes:
shared:
taskfile: hack/common/Taskfile_library.yaml
flatten: true
```

#### Overwriting and Excluding Task Definitions

Adding new specialized tasks in addition to the imported generic ones is straightforward: simply add the task definitions in the importing Taskfile.

It is also possible to exclude or overwrite generic tasks. The following example uses an `external-apis` task that should be executed as part of the generic `generate:code` task.

Overwriting basically works by excluding and re-defining the generic task that should be overwritten. If the generic task's logic should be kept as part of the overwritten definition, the generic file needs to be imported a second time with `internal: true`, so that the original task can be called.

```yaml
includes:
shared:
taskfile: hack/common/Taskfile_controller.yaml
flatten: true
excludes: # put task names in here which are overwritten in this file
- generate:code
common: # imported a second time so that overwriting task definitions can call the overwritten task with a 'c:' prefix
taskfile: hack/common/Taskfile_controller.yaml
internal: true
aliases:
- c

tasks:
generate:code: # overwrites shared code task to add external API fetching
desc: " Generate code (mainly DeepCopy functions) and fetches external APIs."
run: once
cmds:
- task: external-apis
- task: c:generate:code

external-apis:
desc: " Fetch external APIs."
<...>
```

### Makefile

This repo contains a dummy Makefile that for any command prints the instructions for installing `task`:
```
This repository uses task (https://taskfile.dev) instead of make.
Run 'go install github.com/go-task/task/v3/cmd/task@latest' to install the latest version.
Then run 'task -l' to list available tasks.
```

To re-use it, simply create a symbolic link from the importing repo:
```shell
ln -s ./hack/common/Makefile Makefile
```

## Documentation Index Generation

This repository contains a script for creating a index for the documentation of the importing repository. This script is not executed by default, only if the `GENERATE_DOCS_INDEX` variable is explicitly set to anything except `false` in the importing Taskfile. Doing so will not only activate the documentation index generation, but also a check whether it is up-to-date during the `validate:docs` task.

⚠️ Running the documentation index generation script will overwrite the `docs/README.md` file!

The script checks the `docs` folder in the importing repository for subdirectories and markdown files (*.md) contained within. Each directory that contains a special metadata file will result in a header, followed by a list where each entry links to one of the markdown files of the respective directory. Directories without the metadata file will be ignored.

The metadata file is named `.docnames` and is expected to be JSON-formatted, containing a single object with a field named `header`. The value of this field will determine the name of the header in the documentation index for this respective folder.

Additional fields in the JSON object can be used to manipulate the entries for markdown files within the directory: An entry `"foo.md": "Bar"` in the object causes the `foo.md` file in the directory to be displayed as `Bar` in the generated index. Setting the value of such an entry to the empty string removes the corresponding file from the index.

Markdown files whose name is not overwritten by a corresponding field in the metadata file are named according to the first line starting with `# ` in their content, or ignored if the name cannot be determined this way.

#### Limitations

The script is rather primitive and can only handle a single hierarchy level, nested folder structures are not supported. Manipulating or configuring the generated index apart from adapting the names is also not possible.

## Support, Feedback, Contributing

Expand All @@ -19,7 +179,7 @@ If you find any bug that may be a security problem, please follow our instructio

## Code of Conduct

We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone. By participating in this project, you agree to abide by its [Code of Conduct](https://github.com/SAP/.github/blob/main/CODE_OF_CONDUCT.md) at all times.
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone. By participating in this project, you agree to abide by its [Code of Conduct](https://github.com/openmcp-project/.github/blob/main/CODE_OF_CONDUCT.md) at all times.

## Licensing

Expand Down
67 changes: 67 additions & 0 deletions Taskfile_controller.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
version: 3

# This Taskfile is meant to be included for controller repos.
# In addition to the library tasks, it contains tasks for building binaries and images.

run: once
method: checksum

includes:
lib:
taskfile: Taskfile_library.yaml
flatten: true
build:
taskfile: tasks_build.yaml
aliases:
- bld
- b

tasks:

# The following tasks are non-namespaced aliases for the most important namespaced tasks.
# This helps with visibility on 'task -l'.

all:
desc: " Run code generation and validation, build all artifacts and push them to the respective registries."
summary: This is an alias for 'build:all'.
run: once
deps:
- build:all

build:
desc: " Build the binaries. Includes code generation and validation."
summary: This is an alias for 'build:bin:all'.
run: once
deps:
- build:bin:all

build-raw:
desc: " Like 'build', but skips code generation/validation tasks."
summary: This is an alias for 'build:bin:build-multi-raw'.
run: once
deps:
- build:bin:build-multi-raw

image:
desc: " Build and push the images. Includes binary build."
summary: This is an alias for 'build:img:all'.
run: once
deps:
- build:img:all

helm:
desc: " Package and push the helm charts."
summary: This is an alias for 'build:helm:all'.
aliases:
- chart
- helm-chart
run: once
deps:
- build:helm:all

ocm:
desc: " Build and push the OCM component."
summary: This is an alias for 'build:ocm:all'.
run: once
deps:
- build:ocm:all
Loading