├── .github
└── workflows
│ ├── link_check.yml
│ └── update_images.yml
├── README.md
├── base
├── Containerfile
├── README.md
├── entrypoint.sh
├── get-runner-release.sh
├── get_github_app_token.sh
├── register.sh
└── uid.sh
├── build-images.sh
├── buildah
├── Containerfile
└── README.md
├── docs
├── github-app-authentication.md
└── runner-token.md
├── dotnet-6.0
├── Containerfile
└── README.md
├── java
├── Containerfile
└── README.md
├── k8s-tools
├── Containerfile
├── README.md
└── install-tools.sh
├── node
├── Containerfile
└── README.md
└── pat-creation.png
/.github/workflows/link_check.yml:
--------------------------------------------------------------------------------
1 | name: Link checker
2 | on:
3 | push:
4 | paths:
5 | - '**.md'
6 | pull_request:
7 | paths:
8 | -'**.md'
9 |
10 | jobs:
11 | markdown-link-check:
12 | name: Check links in markdown
13 | runs-on: ubuntu-20.04
14 | steps:
15 | - uses: actions/checkout@v2
16 | - uses: gaurav-nelson/github-action-markdown-link-check@v1
17 | with:
18 | use-verbose-mode: true
19 |
--------------------------------------------------------------------------------
/.github/workflows/update_images.yml:
--------------------------------------------------------------------------------
1 | name: Update Runner Images
2 | on:
3 | push:
4 | pull_request:
5 | workflow_dispatch:
6 |
7 |
8 | env:
9 | REGISTRY_URL: quay.io/redhat-github-actions
10 |
11 | BASE_IMG_NAME: runner
12 | BASE_IMG_DIR: base
13 |
14 | BUILDAH_IMG_NAME: buildah-runner
15 | BUILDAH_IMG_DIR: buildah
16 |
17 | K8S_TOOLS_IMG_NAME: k8s-tools-runner
18 | K8S_TOOLS_IMG_DIR: k8s-tools
19 |
20 | NODE_IMG_NAME: node-runner-14
21 | NODE_IMG_DIR: node
22 |
23 | JAVA_IMG_NAME: java-runner-11
24 | JAVA_IMG_DIR: java
25 |
26 | jobs:
27 | update_images:
28 | name: Update images
29 | runs-on: ubuntu-20.04
30 |
31 | steps:
32 | - uses: actions/checkout@v2
33 |
34 | - uses: redhat-actions/common/commit-data@v1
35 | id: commit_data
36 |
37 | - uses: lots0logs/gh-action-get-changed-files@2.1.4
38 | id: get_changed_files
39 | with:
40 | token: ${{ secrets.GITHUB_TOKEN }}
41 |
42 | - name: Determine changed directories
43 | id: is_dir_changed
44 | uses: actions/github-script@v4
45 | with:
46 | script: |
47 | const changedFiles = ${{ steps.get_changed_files.outputs.all }};
48 | console.log(`Changed files: ${JSON.stringify(changedFiles)}`);
49 |
50 | // console.log(`payload ${JSON.stringify(context.payload)}`);
51 | // console.log(`eventName ${JSON.stringify(context.eventName)}`);
52 |
53 | const BASE = "base";
54 | const dirsChanged = {
55 | [BASE]: false,
56 | buildah: false,
57 | "k8s-tools": false,
58 | java: false,
59 | node: false,
60 | };
61 |
62 | Object.keys(dirsChanged).forEach((dir) => {
63 | const changed = changedFiles.find((changedFile) => changedFile.startsWith(dir + "/")) != null;
64 | dirsChanged[dir] = changed;
65 | });
66 |
67 | let rebuildAll = false;
68 | if (context.ref.startsWith("refs/tags/")) {
69 | console.log(`Tag build; all images will be rebuilt.`);
70 | rebuildAll = true;
71 | }
72 | else if (context.eventName === "workflow_dispatch") {
73 | console.log(`Workflow triggered by workflow_dispatch; all images will be rebuilt`);
74 | rebuildAll = true;
75 | }
76 | else if (dirsChanged[BASE]) {
77 | console.log("Base image changed; all images will be rebuilt.");
78 | rebuildAll = true;
79 | }
80 |
81 | Object.keys(dirsChanged).forEach((dir) => {
82 | const changed = rebuildAll || dirsChanged[dir];
83 |
84 | const outputName = (dir + "_changed").toUpperCase();
85 | console.log(`${outputName}=${changed}`)
86 | core.exportVariable(outputName, changed);
87 | });
88 |
89 | // const anyChanged = Object.entries(dirsChanged).find(([k, v] => dirsChanged[k]));
90 | return dirsChanged;
91 |
92 | - name: Determine image tag
93 | shell: bash
94 | run: |
95 | export IMG_TAGS=latest
96 | export GIT_TAG="${{ steps.commit_data.outputs.tag }}"
97 | export BRANCH="${{ steps.commit_data.outputs.branch }}"
98 |
99 | if [[ -n "$GIT_TAG" ]]; then
100 | IMG_TAGS="$GIT_TAG"
101 | elif [[ -n "$BRANCH" ]]; then
102 | if [[ "$BRANCH" == "main" ]]; then
103 | IMG_TAGS="latest"
104 | else
105 | IMG_TAGS=$BRANCH
106 | fi
107 | else
108 | IMG_TAGS="${{ steps.commit_data.outputs.short_sha }}"
109 | fi
110 |
111 | echo "IMG_TAGS=$IMG_TAGS" >> $GITHUB_ENV
112 | echo "BRANCH=$BRANCH" >> $GITHUB_ENV
113 | echo "Tagging images with '$IMG_TAGS'"
114 |
115 | # The child image builds are done on the same machine so that
116 | # it doesn't have to pull the updated base image; it's already there locally.
117 | - name: Determine parent image name and tag
118 | shell: bash
119 | run: |
120 | export FIRST_TAG=$(echo "${{ env.IMG_TAGS }}" | awk '{ print $1 }')
121 |
122 | # export BASE_IMG=${{ env.REGISTRY_URL }}/${{ env.BASE_IMG_NAME }}:$FIRST_TAG
123 | export BASE_IMG=${{ env.BASE_IMG_NAME }}:$FIRST_TAG
124 | echo "Base image is '$BASE_IMG'"
125 | echo BASE_IMG=$BASE_IMG >> $GITHUB_ENV
126 |
127 | - name: Build base image
128 | if: env.BASE_CHANGED == 'true'
129 | uses: redhat-actions/buildah-build@v2
130 | id: build_base_img
131 | with:
132 | image: ${{ env.BASE_IMG_NAME }}
133 | tags: ${{ env.IMG_TAGS }}
134 | oci: true
135 | context:
136 | ${{ env.BASE_IMG_DIR }}
137 | dockerfiles:
138 | ${{ env.BASE_IMG_DIR }}/Containerfile
139 |
140 | - name: Push base image
141 | if: steps.commit_data.outputs.is_pr == 'false' && env.BASE_CHANGED == 'true'
142 | uses: redhat-actions/push-to-registry@v2
143 | with:
144 | image: ${{ env.BASE_IMG_NAME }}
145 | tags: ${{ env.IMG_TAGS }}
146 | registry: ${{ env.REGISTRY_URL }}
147 | username: ${{ secrets.REGISTRY_USER }}
148 | password: ${{ secrets.REGISTRY_PASSWORD }}
149 |
150 | - name: Determine if child images should be built
151 | run: |
152 | export BUILD_BASE_OUTCOME="${{ steps.build_base_img.outcome }}"
153 |
154 | if [[ $BUILD_BASE_OUTCOME == "success" ]] || [[ $BUILD_BASE_OUTCOME == "skipped" ]]; then
155 | echo "Base image was built or did not need to be built"
156 | echo "Child images will be built"
157 | export BUILD_CHILDREN=true
158 | else
159 | export BUILD_CHILDREN=false
160 | echo "Base image build failed"
161 | echo "Child image builds will be skipped."
162 | fi
163 | echo "BUILD_CHILDREN=$BUILD_CHILDREN" >> $GITHUB_ENV
164 |
165 | - name: Build buildah image
166 | if: |
167 | always() &&
168 | env.BUILDAH_CHANGED == 'true' &&
169 | env.BUILD_CHILDREN == 'true'
170 | id: build_buildah
171 | uses: redhat-actions/buildah-build@v2
172 | with:
173 | image: ${{ env.BUILDAH_IMG_NAME }}
174 | tags: ${{ env.IMG_TAGS }}
175 | oci: true
176 | context:
177 | ${{ env.BUILDAH_IMG_DIR }}
178 | dockerfiles:
179 | ${{ env.BUILDAH_IMG_DIR }}/Containerfile
180 | build-args: |
181 | BASE_IMG=${{ env.BASE_IMG }}
182 |
183 | - name: Push buildah image
184 | if: |
185 | steps.build_buildah.outcome == 'success' &&
186 | steps.commit_data.outputs.is_pr == 'false'
187 | uses: redhat-actions/push-to-registry@v2
188 | with:
189 | image: ${{ env.BUILDAH_IMG_NAME }}
190 | tags: ${{ env.IMG_TAGS }}
191 | registry: ${{ env.REGISTRY_URL }}
192 | username: ${{ secrets.REGISTRY_USER }}
193 | password: ${{ secrets.REGISTRY_PASSWORD }}
194 |
195 | - name: Build K8s tools image
196 | if: |
197 | always() &&
198 | env.K8S-TOOLS_CHANGED == 'true' &&
199 | env.BUILD_CHILDREN == 'true'
200 | uses: redhat-actions/buildah-build@v2
201 | id: build_k8s
202 | with:
203 | image: ${{ env.K8S_TOOLS_IMG_NAME }}
204 | tags: ${{ env.IMG_TAGS }}
205 | oci: true
206 | context:
207 | ${{ env.K8S_TOOLS_IMG_DIR }}
208 | dockerfiles:
209 | ${{ env.K8S_TOOLS_IMG_DIR }}/Containerfile
210 | build-args: |
211 | BASE_IMG=${{ env.BASE_IMG }}
212 |
213 | - name: Push K8s tools image
214 | if: |
215 | steps.build_k8s.outcome == 'success' &&
216 | steps.commit_data.outputs.is_pr == 'false'
217 | uses: redhat-actions/push-to-registry@v2
218 | with:
219 | image: ${{ env.K8S_TOOLS_IMG_NAME }}
220 | tags: ${{ env.IMG_TAGS }}
221 | registry: ${{ env.REGISTRY_URL }}
222 | username: ${{ secrets.REGISTRY_USER }}
223 | password: ${{ secrets.REGISTRY_PASSWORD }}
224 |
225 | - name: Build Node image
226 | if: |
227 | always() &&
228 | env.NODE_CHANGED == 'true' &&
229 | env.BUILD_CHILDREN == 'true'
230 | id: build_node
231 | uses: redhat-actions/buildah-build@v2
232 | with:
233 | image: ${{ env.NODE_IMG_NAME }}
234 | tags: ${{ env.IMG_TAGS }}
235 | oci: true
236 | context:
237 | ${{ env.NODE_IMG_DIR }}
238 | dockerfiles:
239 | ${{ env.NODE_IMG_DIR }}/Containerfile
240 | build-args: |
241 | BASE_IMG=${{ env.BASE_IMG }}
242 |
243 | - name: Push Node image
244 | if: |
245 | steps.build_node.outcome == 'success' &&
246 | steps.commit_data.outputs.is_pr == 'false'
247 | uses: redhat-actions/push-to-registry@v2
248 | with:
249 | image: ${{ env.NODE_IMG_NAME }}
250 | tags: ${{ env.IMG_TAGS }}
251 | registry: ${{ env.REGISTRY_URL }}
252 | username: ${{ secrets.REGISTRY_USER }}
253 | password: ${{ secrets.REGISTRY_PASSWORD }}
254 |
255 | - name: Build Java image
256 | if: |
257 | always() &&
258 | env.JAVA_CHANGED == 'true' &&
259 | env.BUILD_CHILDREN == 'true'
260 | id: build_java
261 | uses: redhat-actions/buildah-build@v2
262 | with:
263 | image: ${{ env.JAVA_IMG_NAME }}
264 | tags: ${{ env.IMG_TAGS }}
265 | oci: true
266 | context:
267 | ${{ env.JAVA_IMG_DIR }}
268 | dockerfiles:
269 | ${{ env.JAVA_IMG_DIR }}/Containerfile
270 | build-args: |
271 | BASE_IMG=${{ env.BASE_IMG }}
272 |
273 | - name: Push Java image
274 | if: |
275 | steps.build_java.outcome == 'success' &&
276 | steps.commit_data.outputs.is_pr == 'false'
277 | uses: redhat-actions/push-to-registry@v2
278 | with:
279 | image: ${{ env.JAVA_IMG_NAME }}
280 | tags: ${{ env.IMG_TAGS }}
281 | registry: ${{ env.REGISTRY_URL }}
282 | username: ${{ secrets.REGISTRY_USER }}
283 | password: ${{ secrets.REGISTRY_PASSWORD }}
284 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OpenShift GitHub Actions Runners
2 |
3 | [](https://github.com/redhat-actions/openshift-actions-runner/actions/workflows/update_images.yml)
4 | [](https://github.com/redhat-actions/openshift-actions-runner/actions/workflows/link_check.yml)
5 |
6 | [](https://github.com/redhat-actions/openshift-actions-runner/tags)
7 | [](https://quay.io/organization/redhat-github-actions)
8 |
9 | This repository contains Containerfiles for building container images that act as [self-hosted GitHub Action runners](https://docs.github.com/en/free-pro-team@latest/actions/hosting-your-own-runners/about-self-hosted-runners) that work on OpenShift.
10 |
11 | The [**OpenShift Actions Runner Chart**](https://github.com/redhat-actions/openshift-actions-runner-chart) is used to deploy these images into a cluster, and the [**OpenShift Actions Runner Installer**](https://github.com/redhat-actions/openshift-actions-runner-installer) is an Action to automate the chart install.
12 |
13 | ## Runners
14 | 1. The [**base runner**](./base) is based on Fedora. It is intended to have a fairly minimal tool set to keep the image size as small as possible. It has all the GitHub Actions Runner needs, plus a limited number of popular Unix command-line tools.
15 | 2. The [**buildah runner**](./buildah) extends the base runner to add `buildah` and `podman`. This runner requires permissions that are disabled for by default on OpenShift. See [the buildah image README](./buildah/#README.md) for details.
16 | 3. The [**K8s tools runner**](./k8s-tools) installs a set of CLIs used to work with Kubernetes.
17 | 4. The [**Node.js runner**](./node) includes a Node.js runtime.
18 | 5. The [**Java runner**](./java) includes a JDK and JRE.
19 |
20 | The idea is that the base runner can be extended to build larger, more complex images that have additional capabilities. Refer to [Creating your own runner image](./base#creating-your-own-runner-image).
21 |
22 | The images are hosted at [quay.io/redhat-github-actions](https://quay.io/redhat-github-actions/).
23 |
24 | While these images are developed for and tested on OpenShift, they do not contain any OpenShift specific code and should be compatible with any Kubernetes platform.
25 |
26 | ## Installing into a cluster
27 | Use the [**OpenShift Actions Runner Chart**](https://github.com/redhat-actions/openshift-actions-runner-chart) to deploy these runners into your cluster.
28 |
29 |
30 | ## Creating a Personal Access Token
31 | To register themselves with GitHub, the runners require a [GitHub Personal Access Token](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token) (PAT) which has the `repo` permission scope. This is provided to the container through the `GITHUB_PAT` environment variable.
32 | - The user who created the token must have administrator permission on the organization/repository the runner will be added to.
33 | - If the runner will be for an organization, the token must also have the `admin:org` permission scope.
34 | - [See an example](./pat-creation.png).
35 |
36 | ## Building your own runner image
37 | See the [base image README](./base/#own-image).
38 |
39 | ## Running Locally
40 | You can run the images locally to test and develop.
41 |
42 | To launch and connect a runner to `redhat-actions/openshift-actions-runner` with the labels `local` and `podman`:
43 | ```sh
44 | podman run \
45 | --env GITHUB_PAT=$GITHUB_PAT \
46 | --env GITHUB_OWNER=redhat-actions \
47 | --env GITHUB_REPOSITORY=openshift-actions-runner \
48 | --env RUNNER_LABELS="local,podman" \
49 | quay.io/redhat-github-actions/runner:latest
50 | ```
51 |
52 | Or, to run a shell for debugging:
53 | ```sh
54 | podman run -it --entrypoint=/bin/bash quay.io/redhat-github-actions/runner:latest
55 | ```
56 |
57 | ## Authenticating with a Runner Token
58 | A Runner Token can be used as an alternative to PAT or GitHub App authentication.
59 |
60 | Refer to [Authenticating with a Runner Token](./docs/runner-token.md).
61 |
62 | ## Running with Github App Authentication
63 |
64 | If you are able to use a GitHub App it is highly recommended over the PAT because you have greater control of the API permissions granted to it and you do not need a bot or service account.
65 |
66 | Refer to [Authenticating with GitHub App Authentication](./docs/github-app-authentication.md).
67 |
68 |
69 |
70 | ## GitHub Enterprise Support
71 | You can use any of the runners on your GitHub Enterprise server by overriding `GITHUB_DOMAIN` in the environment, using `podman run --env` or using the [chart](https://github.com/redhat-actions/openshift-actions-runner-chart).
72 |
73 | For example, if you set:
74 | ```
75 | GITHUB_DOMAIN=github.mycompany.com
76 | ```
77 |
78 | the runner entrypoint will then try and register itself with
79 |
80 | ```
81 | https://github.mycompany.com/$GITHUB_OWNER/$GITHUB_REPOSITORY
82 | ```
83 |
84 | and use the GitHub API at
85 |
86 | ```
87 | https://github.mycompany.com/api/v3/
88 | ```
89 |
90 | ## Troubleshooting
91 | If the containers crash on startup, it is usually because one of the environment variables is missing or misconfigured. Make sure to read the container logs carefully to make sure the variables' values are set as expected.
92 |
93 | - If the container crashes with an HTTP 403 error, the `GITHUB_PAT` does not have the appropriate permissions. Refer to the [PAT guidelines](#pat-guidelines).
94 | - If the container crashes with an HTTP 404 error, the `GITHUB_OWNER` or `GITHUB_REPOSITORY` is incorrect or misspelled.
95 | - This will also happen if a private repository is selected which the `GITHUB_PAT` does not have permission to view.
96 |
97 | If you encounter any other issues, please [open an issue](https://github.com/redhat-actions/openshift-actions-runner/issues) and we will help you work through it.
98 |
99 | ## Credits
100 | This repository builds on the work done in [bbrowning/github-runner](https://github.com/bbrowning/github-runner), which is forked from [SanderKnape/github-runner](https://github.com/SanderKnape/github-runner).
101 |
102 | The Github App creation tutorial is heavily based on the excellent README in [actions-runner-controller/actions-runner-controller](https://github.com/actions-runner-controller/actions-runner-controller)
103 |
--------------------------------------------------------------------------------
/base/Containerfile:
--------------------------------------------------------------------------------
1 | FROM fedora:35
2 |
3 | # Adapted from https://github.com/bbrowning/github-runner/blob/master/Dockerfile
4 | RUN dnf -y upgrade --security && \
5 | dnf -y --setopt=skip_missing_names_on_install=False install \
6 | curl git jq hostname procps findutils which openssl && \
7 | dnf clean all
8 |
9 | # The UID env var should be used in child Containerfile.
10 | ENV UID=1000
11 | ENV GID=0
12 | ENV USERNAME="runner"
13 |
14 | # Create our user and their home directory
15 | RUN useradd -m $USERNAME -u $UID
16 | # This is to mimic the OpenShift behaviour of adding the dynamic user to group 0.
17 | RUN usermod -G 0 $USERNAME
18 | ENV HOME /home/${USERNAME}
19 | WORKDIR /home/${USERNAME}
20 |
21 | # Override these when creating the container.
22 | ENV GITHUB_PAT ""
23 | ENV GITHUB_APP_ID ""
24 | ENV GITHUB_APP_INSTALL_ID ""
25 | ENV GITHUB_APP_PEM ""
26 | ENV GITHUB_OWNER ""
27 | ENV GITHUB_REPOSITORY ""
28 | ENV RUNNER_WORKDIR /home/${USERNAME}/_work
29 | ENV RUNNER_GROUP ""
30 | ENV RUNNER_LABELS ""
31 | ENV EPHEMERAL ""
32 |
33 | # Allow group 0 to modify these /etc/ files since on openshift, the dynamically-assigned user is always part of group 0.
34 | # Also see ./uid.sh for the usage of these permissions.
35 | RUN chmod g+w /etc/passwd && \
36 | touch /etc/sub{g,u}id && \
37 | chmod -v ug+rw /etc/sub{g,u}id
38 |
39 | COPY --chown=${USERNAME}:0 get-runner-release.sh ./
40 | RUN ./get-runner-release.sh
41 | RUN ./bin/installdependencies.sh
42 |
43 | # Set permissions so that we can allow the openshift-generated container user to access home.
44 | # https://docs.openshift.com/container-platform/3.3/creating_images/guidelines.html#openshift-container-platform-specific-guidelines
45 | RUN chown -R ${USERNAME}:0 /home/${USERNAME}/ && \
46 | chgrp -R 0 /home/${USERNAME}/ && \
47 | chmod -R g=u /home/${USERNAME}/
48 |
49 | COPY --chown=${USERNAME}:0 entrypoint.sh uid.sh register.sh get_github_app_token.sh ./
50 |
51 | USER $UID
52 |
53 | ENTRYPOINT ./entrypoint.sh
54 |
55 | # Test comment
56 |
--------------------------------------------------------------------------------
/base/README.md:
--------------------------------------------------------------------------------
1 | # Base Actions Runner
2 |
3 | [](https://quay.io/repository/redhat-github-actions/runner)
4 |
5 | The base actions runner is meant to be minimal. It is build from [`fedora:35`](https://hub.docker.com/_/fedora), and contains the [GitHub Actions Runner](https://github.com/actions/runner/) and all its dependencies. At image build time, the latest runner version [is downloaded](./get-runner-release.sh), and the runner self-updates when it is connected to GitHub.
6 |
7 | On OpenShift, containers run as a dynamically assigned user ID You can read about this on [the OpenShift blog](https://www.openshift.com/blog/a-guide-to-openshift-and-uids). This image contains logic to assign that user ID to the `runner` user and make sure the home directory and other required files are have the necessary permissions.
8 |
9 | The [`entrypoint.sh`](./entrypoint.sh) acquires a GitHub Self Hosted Runner token using your GitHub PAT. The token is used to register the runner with GitHub, and connect to start listening for jobs on the organization or repository you specify.
10 |
11 | Some basic CLI tools are installed in addition to what's in the parent Fedora image.
12 |
13 | - `curl`
14 | - `findutils` (`find`)
15 | - `git`
16 | - `hostname`
17 | - `jq`
18 | - `openssl`
19 | - `procps` (`ps`, `pgrep`)
20 | - `which`
21 |
22 |
23 | ## Building your own runner image
24 |
25 | You can create your own runner image based on this one, and install any runtimes and tools your workflows need.
26 |
27 | 1. Create your own Containerfile, with `FROM quay.io/redhat-github-actions/runner:`.
28 | 2. Edit the Containerfile to install and set up your tools, environment, etc.
29 | - If you have to use root in your Containerfile, use `USER root` and convert back to `USER $UID` before the end of the Containerfile.
30 | - The `UID` environment variable is set in the base Containerfile.
31 | - Do not override the `ENTRYPOINT`.
32 | 3. Build and push your new runner image.
33 | 4. Install the [OpenShift Action Runner Chart](https://github.com/redhat-actions/openshift-actions-runner-chart). Set the value `runnerImage` to your image, and `runnerTag` to your tag.
34 |
35 | Remember to pull the base image before running the container build to make sure you are building from an up-to-date image.
36 |
37 | For example, one could build a runner image that includes a Node runtime in just four lines.
38 | ```Dockerfile
39 | FROM quay.io/redhat-github-actions/runner:latest as runner
40 |
41 | USER root
42 | RUN dnf module install -y nodejs:14/default
43 | USER $UID
44 | ```
45 |
46 | Just like that, we have created the [Node runner image](../node/).
47 |
--------------------------------------------------------------------------------
/base/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Based on https://github.com/bbrowning/github-runner/blob/master/entrypoint.sh
3 |
4 | ./uid.sh > /tmp/uid.sh.log
5 |
6 | set -eE
7 |
8 | CREDS_FILE="${PWD}/.credentials"
9 |
10 | # Assume registration artifacts have been persisted from a previous start
11 | # if no PAT or TOKEN is provided, and simply attempt to start.
12 | if [ -n "${GITHUB_PAT:-}" ] || [ -n "${RUNNER_TOKEN:-}" ] || [ -n "${GITHUB_APP_ID:-}" ]; then
13 | source ./register.sh
14 | elif [ -e "${CREDS_FILE}" ]; then
15 | echo "No GITHUB_PAT or RUNNER_TOKEN provided. Using existing credentials file ${CREDS_FILE}."
16 | else
17 | echo "No saved credentials found in ${CREDS_FILE}."
18 | echo "Fatal: GITHUB_PAT or RUNNER_TOKEN must be set in the environment."
19 | exit 1
20 | fi
21 |
22 | if [ -n "${GITHUB_PAT:-}" ]; then
23 | trap 'remove; exit 130' INT
24 | trap 'remove; exit 143' TERM
25 | elif [ -n "${GITHUB_APP_ID:-}" ]; then
26 | trap 'remove_github_app; exit 130' INT
27 | trap 'remove_github_app; exit 143' TERM
28 | else
29 | trap 'exit 130' INT
30 | trap 'exit 143' TERM
31 | fi
32 |
33 | set -x
34 | ./bin/runsvc.sh --once &
35 | svc_pid=$!
36 |
37 | wait $svc_pid
38 |
--------------------------------------------------------------------------------
/base/get-runner-release.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Use the GitHub API to find the latest release of the GitHub Action runner,
4 | # then download and extract the tarball for that release.
5 |
6 | set -eE -o pipefail
7 |
8 | release_file=/tmp/latest-runner-release.json
9 | releases_api=https://api.github.com/repos/actions/runner/releases/latest
10 |
11 | echo "Fetching latest release from $releases_api"
12 |
13 | if [ ! $GITHUB_PAT = '' ]; then
14 | # Set this to work around rate-limiting issues
15 | echo "GITHUB_PAT is set; using for GitHub API"
16 | auth_header="Authorization: token $GITHUB_PAT"
17 | fi
18 |
19 | curl -sSLf -H "$auth_header" -H 'Accept: application/json' -o $release_file $releases_api
20 |
21 | latest_tag=$(jq -r '.tag_name' $release_file)
22 | echo "Latest runner is ${latest_tag}"
23 | echo $latest_tag >> ".RUNNER_VERSION"
24 | rm $release_file
25 |
26 | tag_without_v=$(echo $latest_tag | cut -c 2-)
27 |
28 | os="linux" # could be "win" or "osx"
29 | arch="x64" # for linux os, could be "arm" or "arm64"
30 |
31 | runner_tar="actions-runner-${os}-${arch}-${tag_without_v}.tar.gz"
32 | runner_url="https://github.com/actions/runner/releases/download/${latest_tag}/${runner_tar}"
33 |
34 | set -x
35 | curl -sSLf -O ${runner_url}
36 | tar fxzp ${runner_tar}
37 | rm ${runner_tar}
38 |
--------------------------------------------------------------------------------
/base/get_github_app_token.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Adapted from https://stackoverflow.com/a/62646786 and
3 | # Github's docs: https://docs.github.com/en/developers/apps/building-github-apps/authenticating-with-github-apps#authenticating-as-a-github-app
4 |
5 | get_github_app_token() {
6 | NOW=$( date +%s )
7 | IAT=$((${NOW} - 60))
8 | EXP=$((${NOW} + 540))
9 | HEADER_RAW='{"alg":"RS256"}'
10 | HEADER=$( echo -n "${HEADER_RAW}" | openssl base64 | tr -d '=' | tr '/+' '_-' | tr -d '\n' )
11 | PAYLOAD_RAW='{"iat":'"${IAT}"',"exp":'"${EXP}"',"iss":'"${GITHUB_APP_ID}"'}'
12 | PAYLOAD=$( echo -n "${PAYLOAD_RAW}" | openssl base64 | tr -d '=' | tr '/+' '_-' | tr -d '\n' )
13 | HEADER_PAYLOAD="${HEADER}"."${PAYLOAD}"
14 |
15 | # Making a tmp directory here because /bin/sh doesn't support process redirection <()
16 | tmp_dir=/tmp/github_app_tmp
17 | mkdir "${tmp_dir}"
18 | echo -n "${GITHUB_APP_PEM}" > "${tmp_dir}/github.pem"
19 | echo -n "${HEADER_PAYLOAD}" > "${tmp_dir}/header"
20 | SIGNATURE=$( openssl dgst -sha256 -sign "${tmp_dir}/github.pem" "${tmp_dir}/header" | openssl base64 | tr -d '=' | tr '/+' '_-' | tr -d '\n' )
21 | rm -rf "${tmp_dir}"
22 |
23 | JWT="${HEADER_PAYLOAD}"."${SIGNATURE}"
24 | INSTALL_URL="https://${GITHUB_API_SERVER}/app/installations/${GITHUB_APP_INSTALL_ID}/access_tokens"
25 | INSTALL_TOKEN_PAYLOAD=$(curl -sSfLX POST -H "Authorization: Bearer ${JWT}" -H "Accept: application/vnd.github.v3+json" "${INSTALL_URL}")
26 | INSTALL_TOKEN=$(echo ${INSTALL_TOKEN_PAYLOAD} | jq .token --raw-output)
27 |
28 | echo "${INSTALL_TOKEN}"
29 | }
--------------------------------------------------------------------------------
/base/register.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Based on https://github.com/bbrowning/github-runner/blob/master/entrypoint.sh
3 |
4 | set -eE
5 |
6 | # Load Github app authentication helper function
7 | source ./get_github_app_token.sh
8 |
9 | if [ -z "${GITHUB_OWNER:-}" ]; then
10 | echo "Fatal: \$GITHUB_OWNER must be set in the environment"
11 | exit 1
12 | fi
13 |
14 | if [ -z "${GITHUB_DOMAIN:-}" ]; then
15 | echo "Connecting to public GitHub"
16 | GITHUB_DOMAIN="github.com"
17 | GITHUB_API_SERVER="api.github.com"
18 | else
19 | echo "Connecting to GitHub server at '$GITHUB_DOMAIN'"
20 | GITHUB_API_SERVER="${GITHUB_DOMAIN}/api/v3"
21 | fi
22 |
23 | echo "GitHub API server is '$GITHUB_API_SERVER'"
24 |
25 | if [ -z "${GITHUB_REPOSITORY:-}" ] && [ -n "${GITHUB_REPO:-}" ]; then
26 | GITHUB_REPOSITORY=$GITHUB_REPO
27 | fi
28 |
29 | # https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#create-a-registration-token-for-an-organization
30 |
31 | registration_url="https://${GITHUB_DOMAIN}/${GITHUB_OWNER}${GITHUB_REPOSITORY:+/$GITHUB_REPOSITORY}"
32 |
33 | if [ -z "${GITHUB_PAT:-}" ] && [ -z "${GITHUB_APP_ID:-}" ]; then
34 | echo "Neither GITHUB_PAT nor the GITHUB_APP variables are set in the environment. Automatic runner removal will be disabled."
35 | echo "Visit ${registration_url}/settings/actions/runners to manually force removal of runner."
36 | fi
37 |
38 | if [ -z "${RUNNER_TOKEN:-}" ]; then
39 | if [ -z "${GITHUB_REPOSITORY:-}" ]; then
40 | echo "Runner is scoped to organization '${GITHUB_OWNER}'"
41 | echo "View runner status at https://${GITHUB_DOMAIN}/organizations/${GITHUB_OWNER}/settings/actions"
42 |
43 | token_url="https://${GITHUB_API_SERVER}/orgs/${GITHUB_OWNER}/actions/runners/registration-token"
44 | else
45 | echo "Runner is scoped to repository '${GITHUB_OWNER}/${GITHUB_REPOSITORY}'"
46 | echo "View runner status at https://${GITHUB_DOMAIN}/${GITHUB_OWNER}/${GITHUB_REPOSITORY}/settings/actions"
47 |
48 | token_url="https://${GITHUB_API_SERVER}/repos/${GITHUB_OWNER}/${GITHUB_REPOSITORY}/actions/runners/registration-token"
49 | fi
50 | echo "Obtaining runner token from ${token_url}"
51 |
52 | if [ -n "${GITHUB_APP_ID:-}" ] && [ -n "${GITHUB_APP_INSTALL_ID:-}" ] && [ -n "${GITHUB_APP_PEM:-}" ]; then
53 | echo "GITHUB_APP environment variables are set. Using GitHub App authentication."
54 | app_token=$(get_github_app_token)
55 | payload=$(curl -sSfLX POST -H "Authorization: token ${app_token}" ${token_url})
56 | else
57 | echo "Using GITHUB_PAT for authentication."
58 | payload=$(curl -sSfLX POST -H "Authorization: token ${GITHUB_PAT}" ${token_url})
59 | fi
60 |
61 | export RUNNER_TOKEN=$(echo $payload | jq .token --raw-output)
62 | echo "Obtained registration token"
63 | else
64 | echo "Using RUNNER_TOKEN from environment"
65 | fi
66 |
67 | labels_arg=""
68 | if [ -n "${RUNNER_LABELS:-}" ]; then
69 | labels_arg="--labels $RUNNER_LABELS"
70 | else
71 | echo "No labels provided"
72 | fi
73 |
74 | runner_group_arg=""
75 | # Runner groups are only valid for organization-wide runners
76 | if [ -n "${RUNNER_GROUP:-}" ]; then
77 | if [ -z "${GITHUB_REPOSITORY:-}" ]; then
78 | runner_group_arg="--runnergroup $RUNNER_GROUP"
79 | else
80 | echo "Not applying runner group '${RUNNER_GROUP}' - Runner groups are not valid for repository-scoped runners."
81 | fi
82 | else
83 | echo "No runner group provided"
84 | fi
85 |
86 | ephemeral_arg=""
87 | if [ -n "${EPHEMERAL:-}" ]; then
88 | ephemeral_arg="--ephemeral"
89 | fi
90 |
91 | if [ -n "${RUNNER_TOKEN:-}" ]; then
92 | set -x
93 | ./config.sh \
94 | --name $(hostname) \
95 | --token ${RUNNER_TOKEN} \
96 | --url ${registration_url} \
97 | --work ${RUNNER_WORKDIR} \
98 | ${labels_arg} \
99 | ${runner_group_arg} \
100 | ${ephemeral_arg} \
101 | --unattended \
102 | --replace
103 | set +x
104 | fi
105 |
106 | remove() {
107 | payload=$(curl -sSfLX POST -H "Authorization: token ${GITHUB_PAT}" ${token_url%/registration-token}/remove-token)
108 | export REMOVE_TOKEN=$(echo $payload | jq .token --raw-output)
109 |
110 | ./config.sh remove --unattended --token "${REMOVE_TOKEN}"
111 | }
112 |
113 | remove_github_app() {
114 | app_token=$(get_github_app_token)
115 | payload=$(curl -sSfLX POST -H "Authorization: token ${app_token}" ${token_url%/registration-token}/remove-token)
116 | export REMOVE_TOKEN=$(echo $payload | jq .token --raw-output)
117 |
118 | ./config.sh remove --unattended --token "${REMOVE_TOKEN}"
119 | }
--------------------------------------------------------------------------------
/base/uid.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Ensure that dynamically-assigned uid has an entry in /etc/passwd on container startup.
4 |
5 | # https://docs.openshift.com/container-platform/3.3/creating_images/guidelines.html#openshift-container-platform-specific-guidelines
6 | # https://www.openshift.com/blog/jupyter-on-openshift-part-6-running-as-an-assigned-user-id
7 |
8 | set -eEu
9 |
10 | uid=$(id -u)
11 | gid=$(id -g)
12 | username=${USERNAME:-default}
13 |
14 | echo "Current user has ID ${uid} and GID ${gid}"
15 |
16 | if ! whoami &> /dev/null; then
17 | if [ -w /etc/passwd ]; then
18 | echo "Creating passwd entry for $username"
19 | echo "${username}:x:${uid}:0:${username} user:${HOME}:/sbin/nologin" >> /etc/passwd
20 | echo -n "New passwd entry: "
21 | tail -n 1 /etc/passwd
22 | else
23 | echo "No write permission to /etc/passwd!" 1>&2
24 | fi
25 | else
26 | echo "User already has passwd entry"
27 | fi
28 |
29 | echo "whoami=$(whoami)"
30 | echo "groups=$(groups 2>/dev/null)"
31 |
32 | set +x
33 | echo "Creating sub{u,g}id entries for $username"
34 | subuids_start=$(expr $uid + 1000)
35 | subgids_start=$(expr $gid + 1000)
36 |
37 | # Do not allocate too many.
38 | # https://github.com/containers/buildah/issues/3053
39 | no_subids=50000
40 |
41 | echo "${username}:${subuids_start}:${no_subids}" | tee /etc/subuid
42 | echo "${username}:${subgids_start}:${no_subids}" | tee /etc/subgid
43 |
44 | # set -x
45 | # tail -n +1 /etc/sub{u,g}id
46 |
--------------------------------------------------------------------------------
/build-images.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -eEu -o pipefail
4 |
5 | # Replace with your username. Don't push your dev images to redhat-github-actions.
6 | REGISTRY=${RUNNERS_REGISTRY:-quay.io/tetchell}
7 | TAG=${RUNNERS_TAG:-latest}
8 |
9 | BASE_IMG=${REGISTRY}/runner:${TAG}
10 | BUILDAH_IMG=${REGISTRY}/buildah-runner:${TAG}
11 | K8S_TOOLS_IMG=${REGISTRY}/k8s-tools-runner:${TAG}
12 |
13 | echo "Base img tag $BASE_IMG"
14 |
15 | enabled() {
16 | [[ $1 == *$2* ]]
17 | }
18 |
19 | cd $(dirname $0)
20 |
21 | if enabled "$*" base; then
22 | echo "Building base image..."
23 | docker build -f ./base/Containerfile -t $BASE_IMG ./base
24 | fi
25 |
26 | if enabled "$*" buildah; then
27 | echo "Building buildah image..."
28 | docker build -f ./buildah/Containerfile -t $BUILDAH_IMG ./buildah
29 | fi
30 | if enabled "$*" k8s; then
31 | echo "Building K8s image..."
32 | docker build -f ./k8s-tools/Containerfile -t $K8S_TOOLS_IMG ./k8s-tools
33 | fi
34 |
35 | if enabled "$*" push; then
36 | echo "Pushing..."
37 | docker push $BASE_IMG
38 |
39 | if enabled "$*" buildah; then
40 | docker push $BUILDAH_IMG
41 | fi
42 | if enabled "$*" k8s; then
43 | docker push $K8S_TOOLS_IMG
44 | fi
45 | else
46 | echo "Not pushing. Pass 'push' to push"
47 | fi
48 |
49 | echo "$BASE_IMG"
50 | if enabled "$*" buildah; then
51 | echo "$BUILDAH_IMG"
52 | fi
53 | if enabled "$*" k8s; then
54 | echo "$K8S_TOOLS_IMG"
55 | fi
56 |
57 | cd - > /dev/null
58 |
--------------------------------------------------------------------------------
/buildah/Containerfile:
--------------------------------------------------------------------------------
1 | ARG BASE_IMG=quay.io/redhat-github-actions/runner:latest
2 | FROM $BASE_IMG AS buildah-runner
3 |
4 | USER root
5 |
6 | # https://github.com/containers/buildah/blob/main/docs/tutorials/05-openshift-rootless-build.md
7 | # https://github.com/containers/buildah/blob/master/contrib/buildahimage/stable/Dockerfile
8 | # https://github.com/containers/buildah/issues/1011
9 | # https://github.com/containers/buildah/issues/3053
10 |
11 | RUN dnf -y update && \
12 | dnf -y install xz slirp4netns buildah podman fuse-overlayfs shadow-utils --exclude container-selinux && \
13 | dnf -y reinstall shadow-utils && \
14 | dnf clean all
15 |
16 | ARG OC_VERSION=4.7.4
17 | RUN curl -sSLf https://mirror.openshift.com/pub/openshift-v4/x86_64/clients/ocp/${OC_VERSION}/openshift-client-linux.tar.gz \
18 | | tar --exclude=README.md -xzvf - &&\
19 | mv kubectl oc /usr/local/bin/
20 |
21 | ENV BUILDAH_ISOLATION=chroot
22 | ENV BUILDAH_LAYERS=true
23 |
24 | ADD https://raw.githubusercontent.com/containers/buildah/master/contrib/buildahimage/stable/containers.conf /etc/containers/
25 |
26 | RUN chgrp -R 0 /etc/containers/ && \
27 | chmod -R a+r /etc/containers/ && \
28 | chmod -R g+w /etc/containers/
29 |
30 | # Use VFS since fuse does not work
31 | # https://github.com/containers/buildah/blob/master/vendor/github.com/containers/storage/storage.conf
32 | RUN mkdir -vp /home/${USERNAME}/.config/containers && \
33 | printf '[storage]\ndriver = "vfs"\n' > /home/${USERNAME}/.config/containers/storage.conf && \
34 | chown -Rv ${USERNAME} /home/${USERNAME}/.config/
35 |
36 | USER $UID
37 |
--------------------------------------------------------------------------------
/buildah/README.md:
--------------------------------------------------------------------------------
1 | ## Buildah/Podman Actions Runner
2 |
3 | [](https://quay.io/repository/redhat-github-actions/buildah-runner)
4 |
5 | The Buildah/Podman Actions Runner extends the [base runner](../base) to include Buildah, Podman, and the dependencies they need to run in a rootless, containerized environment.
6 |
7 | In order for OpenShift containers to run Buildah and Podman, the user or ServiceAccount that deploys the pod must have permission to deploy using the `anyuid` SecurityContextConstraint (SCC).
8 |
9 | Buildah has a [very good tutorial](https://github.com/containers/buildah/blob/main/docs/tutorials/05-openshift-rootless-build.md) detailing how to run buildah in OpenShift.
10 |
11 | You can also refer to the OpenShift documentation [Managing Security Context Constraints](https://docs.openshift.com/container-platform/4.6/authentication/managing-security-context-constraints.html), and [this blog post](https://www.openshift.com/blog/managing-sccs-in-openshift).
12 |
13 | ## Deploying the buildah pod
14 |
15 | It is recommended to deploy the pod using a ServiceAccount specifically configured to have the required permissions. An administrator must run:
16 |
17 | ```bash
18 | # Create the ServiceAccount (if needed)
19 | $ oc create -f - <
37 | ```
38 |
39 | ## Podman run
40 | `podman run` doesn't work unless the pod is created with the `privileged` SCC.
41 |
42 | If you need to use `podman run`, run the `oc adm policy` commands as above, but substitute `privileged` for `anyuid`.
43 |
--------------------------------------------------------------------------------
/docs/github-app-authentication.md:
--------------------------------------------------------------------------------
1 | ## Setting up a GitHub App for Runner Registration
2 |
3 | You can create a GitHub App for your user account, or any organization.
4 |
5 | The following app permissions are required for each supported type of runner:
6 |
7 | _Note: Links are provided further down to create an app for your logged in user account or an organization with the permissions for all runner types set in each link's query string_
8 |
9 | **Required Permissions for Repository Runners:**
10 | **Repository Permissions**
11 |
12 | * Actions (read)
13 | * Administration (read / write)
14 | * Metadata (read)
15 |
16 | **Required Permissions for Organization Runners:**
17 | **Repository Permissions**
18 |
19 | * Actions (read)
20 | * Metadata (read)
21 |
22 | **Organization Permissions**
23 | * Self-hosted runners (read / write)
24 |
25 |
26 | _Note: All API routes mapped to their permissions can be found [here](https://docs.github.com/en/rest/reference/permissions-required-for-github-apps) if you wish to review_
27 |
28 | ---
29 |
30 | **Setup Steps**
31 |
32 | If you want to create a GitHub App for your account, open the following link to the creation page, enter any unique name in the "GitHub App name" field, and hit the "Create GitHub App" button at the bottom of the page.
33 |
34 |
35 | - [Create GitHub Apps on your account](https://github.com/settings/apps/new?url=https://github.com/redhat-actions/openshift-actions-runners&webhook_active=false&public=false&administration=write&actions=read)
36 |
37 | If you want to create a GitHub App for your organization, replace the `:org` part of the following URL with your organization name before opening it. Then enter any unique name in the "GitHub App name" field, and hit the "Create GitHub App" button at the bottom of the page to create a GitHub App.
38 |
39 |
40 | - [Create GitHub Apps on your organization](https://github.com/organizations/:org/settings/apps/new?url=https://github.com/redhat-actions/openshift-actions-runners&webhook_active=false&public=false&administration=write&organization_self_hosted_runners=write&actions=read)
41 |
42 | You will see an *App ID* on the page of the GitHub App you created. You will need the value of this App ID later.
43 |
44 | Download the private key file by pushing the "Generate a private key" button at the bottom of the GitHub App page. This file will also be used later.
45 |
46 | Go to the "Install App" tab on the left side of the page and install the GitHub App that you created for your account or organization.
47 |
48 | When the installation is complete, you will be taken to a URL in one of the following formats. The number at the end of the URL will be used as the Installation ID later.
49 |
50 | For example, if the URL ends in `settings/installations/12345`, then the Installation ID is `12345`.
51 |
52 | - `https://github.com/settings/installations/${INSTALLATION_ID}`
53 | - `https://github.com/organizations/eventreactor/settings/installations/${INSTALLATION_ID}`
54 |
55 | ### Running Locally with GitHub App Authentication
56 |
57 | You need to set the `GITHUB_APP_ID`, `GITHUB_APP_INSTALL_ID`, and `GITHUB_APP_PEM` env variables and pass them to your container.
58 |
59 | The easiest way to get the private key in the correct form is to copy paste it into the environment variable. Newlines must be preserved.
60 |
61 | To launch and connect a runner to `redhat-actions/openshift-actions-runner` with the labels `local` and `podman`:
62 |
63 | ```sh
64 | podman run \
65 | --env GITHUB_APP_ID \
66 | --env GITHUB_APP_INSTALL_ID \
67 | --env GITHUB_APP_PEM \
68 | --env GITHUB_OWNER=redhat-actions \
69 | --env GITHUB_REPOSITORY=openshift-actions-runner \
70 | --env RUNNER_LABELS="local,podman" \
71 | quay.io/redhat-github-actions/runner:latest
72 | ```
73 |
--------------------------------------------------------------------------------
/docs/runner-token.md:
--------------------------------------------------------------------------------
1 | ## Authenticating with a Runner Token
2 |
3 | If you're not comfortable persisting a PAT with access to all of your repositories, it is possible to manually generate a runner registration token and use that.
4 |
5 | You can create a runner token with [the GitHub API](https://docs.github.com/en/rest/reference/actions#create-a-registration-token-for-an-organization) or through the repository or organization's Settings. Navigate to `Settings` > `Actions` > `Runners`, click `Add Runner`, and copy out the `--token` argument from the `config.sh` call.
6 |
7 | Note that these tokens are only good for 60 minutes, so you must keep the local files created upon registration (after running `config.sh`) in order to be able to restart your runner. A similar process may be especially useful in Kubernetes, so that Pods can be recreated without manual intervention.
8 |
9 | ```sh
10 | # Create volume to persist authentication and configuration
11 | podman volume create runner
12 | # Perform registration, and copy artifacts to volume
13 | podman run \
14 | --env RUNNER_TOKEN=$RUNNER_TOKEN \
15 | --env GITHUB_OWNER=redhat-actions \
16 | --env GITHUB_REPOSITORY=openshift-actions-runner \
17 | --env RUNNER_LABELS="local,podman" \
18 | --rm -v runner:/persistence \
19 | --entrypoint='' \
20 | quay.io/redhat-github-actions/runner:latest \
21 | bash -c "./register.sh && cp -rT . /persistence"
22 | # Run container with volume mounted over runner home directory
23 | podman run \
24 | --rm -v runner:/home/runner \
25 | quay.io/redhat-github-actions/runner:latest
26 | ```
27 |
--------------------------------------------------------------------------------
/dotnet-6.0/Containerfile:
--------------------------------------------------------------------------------
1 | ARG BASE_IMG=quay.io/redhat-github-actions/runner:latest
2 | FROM $BASE_IMG AS dotnet-6.0-runner
3 |
4 | USER root
5 |
6 | RUN dnf install -y dotnet-sdk-6.0
7 |
8 | USER $UID
9 |
--------------------------------------------------------------------------------
/dotnet-6.0/README.md:
--------------------------------------------------------------------------------
1 | # .NET 6.0 Runner
2 |
3 | This runner is the [base runner](../base/) extended to include the .NET 6.0 SDK for building .NET 6 applications.
4 |
5 | .NET 6 is only supported on Fedora 34 and higher. [More info from Microsoft](https://docs.microsoft.com/en-us/dotnet/core/install/linux-fedora)
6 |
--------------------------------------------------------------------------------
/java/Containerfile:
--------------------------------------------------------------------------------
1 | ARG BASE_IMG=quay.io/redhat-github-actions/runner:latest
2 | FROM $BASE_IMG AS java-runner
3 |
4 | USER root
5 |
6 | RUN dnf install -y java-11-openjdk-devel.x86_64
7 |
8 | USER $UID
9 |
--------------------------------------------------------------------------------
/java/README.md:
--------------------------------------------------------------------------------
1 | # Java Runner
2 |
3 | [](https://quay.io/repository/redhat-github-actions/java-11-runner)
4 |
5 | This runner is the [base runner](../base) extended to include a OpenJDK and JRE for building and running your Java projects.
6 |
7 | This image includes Java 11, as the newer of the two current LTS versions.
8 |
--------------------------------------------------------------------------------
/k8s-tools/Containerfile:
--------------------------------------------------------------------------------
1 | ARG BASE_IMG=quay.io/redhat-github-actions/runner:latest
2 | FROM $BASE_IMG AS k8s-tools-runner
3 |
4 | USER root
5 |
6 | ARG HELM_VERSION="3.5.0"
7 | ENV HELM_VERSION=${HELM_VERSION}
8 |
9 | ARG KN_VERSION="0.19.1"
10 | ENV KN_VERSION=${KN_VERSION}
11 |
12 | ARG OC_VERSION="4.6.18"
13 | ENV OC_VERSION=${OC_VERSION}
14 |
15 | ARG TKN_VERSION="0.15.0"
16 | ENV TKN_VERSION=${TKN_VERSION}
17 |
18 | ARG YQ_VERSION="4.6.0"
19 | ENV YQ_VERSION=${YQ_VERSION}
20 |
21 | COPY ./install-tools.sh .
22 |
23 | RUN ./install-tools.sh
24 | RUN rm ./install-tools.sh
25 |
26 | USER $UID
27 |
--------------------------------------------------------------------------------
/k8s-tools/README.md:
--------------------------------------------------------------------------------
1 | # Kubernetes Tools Runner
2 |
3 | [](https://quay.io/repository/redhat-github-actions/k8s-tools-runner)
4 |
5 |
6 | The Kubernetes tools runner is the [base runner](../base) plus a set of CLIs used to work with OpenShift/Kubernetes clusters.
7 |
8 | The version of each tool to install can be edited using a Docker `--build-arg`. View the [Containerfile](./Containerfile) to see the build args to use.
9 |
10 | Since most tools are installed from the [OpenShift V4 mirror](https://mirror.openshift.com/pub/openshift-v4/clients/), make sure the desired version is available there first. Refer to the [install-tools](./install-tools.sh) script to see where each CLI is fetched from.
11 |
12 | Note that `kubectl` is packaged together with `oc`.
13 |
14 | | Tool | Version |
15 | | ---- | ------- |
16 | | helm | 3.5.0 |
17 | | kn | 0.19.1 |
18 | | oc | 4.6.18 |
19 | | tkn | 0.15.0 |
20 | | yq | 4.6.0 |
21 |
--------------------------------------------------------------------------------
/k8s-tools/install-tools.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | INSTALLER_TMP=/tmp/tool-installer/
4 | INSTALL_TARGET_DIR=/usr/local/bin/
5 |
6 | if [[ -n $DEV_INSTALL_TARGET_DIR ]]; then
7 | # Use this for testing the script without installing into your system dirs
8 | echo "Using override install target $DEV_INSTALL_TARGET_DIR"
9 | INSTALL_TARGET_DIR=$DEV_INSTALL_TARGET_DIR
10 | fi
11 |
12 | die() {
13 | echo >&2 "Error: $1"
14 | exit 1
15 | }
16 |
17 | assert_env_var() {
18 | local var=$1
19 | local value=$(eval echo "\$$var")
20 | echo "${var}=${value}"
21 | if [[ -z $value ]]; then
22 | die "$var not specified in environment"
23 | fi
24 | }
25 |
26 | extract() {
27 | extract_result=""
28 |
29 | local archive_name=$1
30 | local executable_name=$2
31 | local extract_dir=${INSTALLER_TMP}${executable_name}
32 |
33 | mkdir -vp $extract_dir
34 |
35 | if [[ $archive_name == *.tar* ]]; then
36 | echo "Extracting $archive_name"
37 | # -o is required due to https://discuss.circleci.com/t/tar-cannot-change-ownership/28766
38 | tar -axvof $archive_name -C $extract_dir
39 | elif [[ $archive_name =~ *\.zip ]]; then
40 | echo "Extracting $archive_name"
41 | unzip $archive_name -d $extract_dir
42 | else
43 | die "Unrecognized zip file '$archive_name'"
44 | exit 1
45 | fi
46 |
47 | # Return using global var
48 | extract_result=$(find $extract_dir -type f -iname "$executable_name*")
49 |
50 | if [[ -z $extract_result ]]; then
51 | die "Could not find $executable_name in $extract_dir after extraction"
52 | fi
53 | }
54 |
55 | move_executable() {
56 | local executable_path=$1
57 | local executable_name=$2
58 | chmod a+x $executable_path
59 | mv -v $executable_path $INSTALL_TARGET_DIR$executable_name
60 |
61 | echo "Installed $executable_name to $INSTALL_TARGET_DIR"
62 | }
63 |
64 | install() {
65 | local executable_name=$1
66 | local url=$2
67 | local download_filename=$(basename $url)
68 | echo "Downloading $2 to $download_filename ..."
69 | curl -fLsSO $url
70 |
71 | local extname=${download_filename#*.}
72 |
73 | if [[ $extname == $download_filename ]]; then
74 | # if extname == download_filename then there is no extension, we got just the executable
75 | if [[ $download_filename != $executable_name ]]; then
76 | mv -v $download_filename $executable_name
77 | fi
78 | local executable_path=$executable_name
79 | else
80 | # otherwise, we have to extract it
81 | extract $download_filename $executable_name
82 |
83 | # Global extract_result is the set in extract
84 | local executable_path=$extract_result
85 |
86 | if [[ $executable_name == "oc" ]]; then
87 | # special case for oc targz which also contains kubectl
88 | local oc_path=$extract_result
89 |
90 | extract $download_filename "kubectl"
91 | local kubectl_path=$extract_result
92 | move_executable $kubectl_path "kubectl"
93 |
94 | # Reset
95 | extract_result=$oc_path
96 | fi
97 | fi
98 |
99 | move_executable $executable_path $executable_name
100 | rm -fv $download_filename
101 |
102 | echo
103 | echo "========================================"
104 | }
105 |
106 | # set -x
107 | set -eEu -o pipefail
108 |
109 | MIRROR="https://mirror.openshift.com/pub/openshift-v4/x86_64/clients"
110 |
111 | mkdir -vp $INSTALLER_TMP
112 |
113 | assert_env_var "HELM_VERSION"
114 | install helm ${MIRROR}/helm/${HELM_VERSION}/helm-linux-amd64.tar.gz
115 |
116 | assert_env_var "KN_VERSION"
117 | install kn ${MIRROR}/serverless/${KN_VERSION}/kn-linux-amd64-${KN_VERSION}.tar.gz
118 |
119 | assert_env_var "OC_VERSION"
120 | install oc ${MIRROR}/ocp/${OC_VERSION}/openshift-client-linux.tar.gz
121 |
122 | assert_env_var "TKN_VERSION"
123 | install tkn ${MIRROR}/pipeline/${TKN_VERSION}/tkn-linux-amd64-${TKN_VERSION}.tar.gz
124 |
125 | assert_env_var "YQ_VERSION"
126 | install yq https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/yq_linux_amd64.tar.gz
127 |
128 | echo "Removing $INSTALLER_TMP"
129 | rm -rf $INSTALLER_TMP
130 |
--------------------------------------------------------------------------------
/node/Containerfile:
--------------------------------------------------------------------------------
1 | ARG BASE_IMG=quay.io/redhat-github-actions/runner:latest
2 | FROM $BASE_IMG AS node-runner
3 |
4 | USER root
5 |
6 | # https://nodejs.org/en/download/package-manager/#centos-fedora-and-red-hat-enterprise-linux
7 | # 14 is LTS
8 | RUN dnf module install -y nodejs:14
9 |
10 | USER $UID
11 |
--------------------------------------------------------------------------------
/node/README.md:
--------------------------------------------------------------------------------
1 | # Node.js Runner
2 |
3 | [](https://quay.io/repository/redhat-github-actions/node-14-runner)
4 |
5 | This runner is the [base runner](../base/) extended to include a Node.js runtime for building and running your Node.js projects.
6 |
7 | This image includes Node.js 14, as the newest current LTS version.
8 |
--------------------------------------------------------------------------------
/pat-creation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-actions/openshift-actions-runners/ce6d8a6548637d2e190ae56162530888a1258bf3/pat-creation.png
--------------------------------------------------------------------------------