commit 46755db8f381f9975b8ac963776c92de412d1251 Author: Nick Alteen Date: Fri Dec 8 10:33:30 2023 -0500 Initial commit diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..9d98c2a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,21 @@ +version: 2 +updates: + - package-ecosystem: docker + directory: / + schedule: + interval: weekly + groups: + docker-minor: + update-types: + - minor + - patch + + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + groups: + actions-minor: + update-types: + - minor + - patch diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml new file mode 100644 index 0000000..6d79773 --- /dev/null +++ b/.github/linters/.markdown-lint.yml @@ -0,0 +1,7 @@ +# Unordered list style +MD004: + style: dash + +# Ordered list item prefix +MD029: + style: one diff --git a/.github/linters/.yaml-lint.yml b/.github/linters/.yaml-lint.yml new file mode 100644 index 0000000..c975a33 --- /dev/null +++ b/.github/linters/.yaml-lint.yml @@ -0,0 +1,10 @@ +rules: + document-end: disable + document-start: + level: warning + present: false + line-length: + level: warning + max: 80 + allow-non-breakable-words: true + allow-non-breakable-inline-mappings: true diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 0000000..7e7be9a --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,147 @@ +# When a PR is merged, or when run manually, this workflow will create a +# release and publish the container image to the GitHub Container Registry. Both +# will be labeled with the version specified in the manifest file. +name: Continuous Delivery + +on: + pull_request: + types: + - closed + branches: + - main + workflow_dispatch: + +env: + CONTAINER_REGISTRY: ghcr.io + CONTAINER_REGISTRY_USERNAME: ${{ github.actor }} + CONTAINER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }} + MANIFEST_PATH: .version + +permissions: + contents: write + packages: write + +jobs: + release: + name: Create Release + runs-on: ubuntu-latest + + # Ignore Dependabot pull requests. + if: | + (github.event_name == 'workflow_dispatch' || + github.event.pull_request.merged == true) && + github.actor != 'dependabot[bot]' + + outputs: + # Semantic version to use for tagging container images. + # E.g. `1.2.3` or `1.2.3-alpha.4` + version: ${{ steps.tag.outputs.version }} + + steps: + - name: Checkout + id: checkout + uses: actions/checkout@v4 + with: + fetch-tags: true + ref: main + + - name: Tag Version + id: tag + uses: issue-ops/semver@v0.3.2 + with: + manifest-path: ${{ env.MANIFEST_PATH }} + ref: main + workspace: ${{ github.workspace }} + + - name: Create Release + id: release + uses: issue-ops/releaser@v0.1.3 + with: + tag: v${{ steps.tag.outputs.version }} + + container: + name: Publish Container Image + runs-on: ubuntu-latest + + needs: release + + steps: + - name: Checkout + id: checkout + uses: actions/checkout@v4 + with: + fetch-tags: true + ref: main + + - name: Build, Scan, and Publish Container Image + id: build-scan-publish + uses: usps/fast-track-container-image-action@v1.0.0 + with: + # Container registry details + registry: ${{ env.CONTAINER_REGISTRY }} + username: ${{ env.CONTAINER_REGISTRY_USERNAME }} + password: ${{ env.CONTAINER_REGISTRY_PASSWORD }} + + # Other inputs + checkout: true + manifest-path: ${{ env.MANIFEST_PATH }} + version: ${{ needs.release.outputs.version }} + + # Create the list of image tags that will be published. If a prerelease is + # being published (e.g. `1.2.3-alpha.4`), only the prerelease tag will be + # published (`v1.2.3-alpha.4`). Otherwise, the following tags will be + # published: + # - `latest` + # - `v1.2.3` + # - `v1.2` + # - `v1` + - name: Set Image Tags + id: tags + uses: actions/github-script@v7 + with: + script: | + const version = '${{ needs.release.outputs.version }}' + + // Check if prerelease (e.g. 1.2.3-alpha.4) + if (version.includes('-')) { + // Only output the prerelease tag + core.setOutput('tags', `type=raw,value=v${version}`) + } else { + // Output all the tags + let tags = [ + 'type=raw,value=latest', + `type=raw,value=v${version}`, + `type=raw,value=v${version.split('.').slice(0, 2).join('.')}`, + `type=raw,value=v${version.split('.')[0]}` + ] + core.setOutput('tags', tags.join('\n')) + } + + # Get metadata to apply to image + - name: Extract Metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.CONTAINER_REGISTRY }}/${{ github.repository }} + tags: ${{ steps.tags.outputs.tags }} + + # Authenticate to the container registry + - name: Authenticate to Container Registry + id: login + uses: docker/login-action@v3 + with: + registry: ${{ env.CONTAINER_REGISTRY }} + username: ${{ env.CONTAINER_REGISTRY_USERNAME }} + password: ${{ env.CONTAINER_REGISTRY_PASSWORD }} + + # Publish the container image + - name: Publish Container Image + id: publish + uses: docker/build-push-action@v5 + env: + LABELS: ${{ steps.meta.outputs.labels }} + TAGS: ${{ steps.meta.outputs.tags }} + with: + labels: ${{ env.LABELS }} + push: true + tags: ${{ env.TAGS }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..530b719 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,54 @@ +name: Continuous Integration + +on: + pull_request: + push: + branches: + - main + +permissions: + contents: read + +jobs: + test: + name: Test Container Image + runs-on: ubuntu-latest + + # Run a local registry to push to + services: + registry: + image: registry:2 + ports: + - 5001:5000 + + env: + TEST_TAG: localhost:5001/actions/container-prebuilt-action:latest + + steps: + - name: Checkout + id: checkout + uses: actions/checkout@v4 + + - name: Setup Docker BuildX + id: setup-buildx + uses: docker/setup-buildx-action@v3 + with: + install: true + driver-opts: network=host + + - name: Build the Container + id: build + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: ${{ env.TEST_TAG }} + + - name: Run the Container + id: run + env: + INPUT_WHO_TO_GREET: Mona Lisa Octocat + run: | + docker run \ + --env INPUT_WHO_TO_GREET="${{ env.INPUT_WHO_TO_GREET }}" \ + --rm ${{ env.TEST_TAG }} diff --git a/.github/workflows/example.yml b/.github/workflows/example.yml new file mode 100644 index 0000000..854e753 --- /dev/null +++ b/.github/workflows/example.yml @@ -0,0 +1,25 @@ +name: Example Workflow + +on: + push: + branches: + - main + +permissions: + contents: read + +jobs: + test: + name: Test the Action + runs-on: ubuntu-latest + + steps: + - name: Run the Container Action + id: run + uses: actions/container-prebuilt-action@latest + with: + who-to-greet: Mona Lisa Octocat + + - name: Print Output + id: output + run: echo "${{ steps.test-action.outputs.greeting }}" diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml new file mode 100644 index 0000000..09a8374 --- /dev/null +++ b/.github/workflows/linter.yml @@ -0,0 +1,30 @@ +name: Lint Codebase + +on: + pull_request: + push: + branches: + - main + +permissions: + contents: read + packages: read + statuses: write + +jobs: + lint: + name: Lint Codebase + runs-on: ubuntu-latest + + steps: + - name: Checkout + id: checkout + uses: actions/checkout@v4 + + - name: Lint Codebase + id: super-linter + uses: super-linter/super-linter/slim@v5 + env: + DEFAULT_BRANCH: main + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + VALIDATE_ALL_CODEBASE: false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dcff431 --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# Logs +logs +*.log + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# dotenv environment variables file +.env +.env.test + +# OS metadata +.DS_Store +Thumbs.db + +# IDE files +.idea +.vscode +*.code-workspace diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..a378146 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,16 @@ +{ + "printWidth": 80, + "tabWidth": 2, + "useTabs": false, + "semi": false, + "singleQuote": true, + "quoteProps": "as-needed", + "jsxSingleQuote": false, + "trailingComma": "none", + "bracketSpacing": true, + "bracketSameLine": true, + "arrowParens": "avoid", + "proseWrap": "always", + "htmlWhitespaceSensitivity": "css", + "endOfLine": "lf" +} diff --git a/.version b/.version new file mode 100644 index 0000000..6c6aa7c --- /dev/null +++ b/.version @@ -0,0 +1 @@ +0.1.0 \ No newline at end of file diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..a9802d7 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,4 @@ +# Repository CODEOWNERS + +* @actions/actions-runtime +* @ncalteen diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6b92e63 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +# Set the base image to use for subsequent instructions +FROM alpine:3.18 + +# Set the working directory inside the container +WORKDIR /usr/src + +# Copy any source file(s) required for the action +COPY entrypoint.sh . + +# Configure the container to be run as an executable +ENTRYPOINT ["/usr/src/entrypoint.sh"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5f9e342 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright GitHub + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..9e5567f --- /dev/null +++ b/README.md @@ -0,0 +1,209 @@ +# Container Prebuilt Action Template + +[![GitHub Super-Linter](https://github.com/actions/container-prebuilt-action/actions/workflows/linter.yml/badge.svg)](https://github.com/super-linter/super-linter) +![CI](https://github.com/actions/container-prebuilt-action/actions/workflows/ci.yml/badge.svg) +![CD](https://github.com/actions/container-prebuilt-action/actions/workflows/cd.yml/badge.svg) + +Use this template to bootstrap the creation of a container action. :rocket: + +This template includes compilation support, tests, a validation workflow, +publishing, and versioning guidance. The core difference between this template +and [`actions/container-action`](https://github.com/actions/container-action) is +that this template does not build the container image on every action run. +Instead, the action pulls the image from +[GitHub Container Registry (ghcr.io)](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry). + +If you would like to use the +[GitHub Actions Toolkit](https://github.com/actions/toolkit) in your container +action, see the +[Container Toolkit Action](https://github.com/actions/container-toolkit-action) +repository. + +## Create Your Own Action + +To create your own action, you can use this repository as a template! Just +follow the below instructions: + +1. Click the **Use this template** button at the top of the repository +1. Select **Create a new repository** +1. Select an owner and name for your new repository +1. Click **Create repository** +1. Clone your new repository + +> [!IMPORTANT] +> +> Make sure to remove or update the [`CODEOWNERS`](./CODEOWNERS) file! For +> details on how to use this file, see +> [About code owners](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners). + +## Initial Setup + +After you've cloned the repository to your local machine or codespace, you'll +need to perform some initial setup steps before you can develop your action. + +> [!NOTE] +> +> You'll need to have a reasonably modern version of +> [Docker](https://www.docker.com/get-started/) handy (e.g. docker engine +> version 20 or later). + +1. :hammer_and_wrench: Build the container + + Make sure to replace `actions/container-prebuilt-action` with an appropriate + label for your container. + + ```bash + docker build -t actions/container-prebuilt-action . + ``` + +1. :white_check_mark: Test the container + + You can pass individual environment variables using the `--env` or `-e` flag. + + ```bash + $ docker run --env INPUT_WHO_TO_GREET="Mona Lisa Octocat" actions/container-prebuilt-action + ::notice file=entrypoint.sh,line=7::Hello, Mona Lisa Octocat! + ``` + + Or you can pass a file with environment variables using `--env-file`. + + ```bash + $ cat ./.env.test + INPUT_WHO_TO_GREET="Mona Lisa Octocat" + + $ docker run --env-file ./.env.test actions/container-prebuilt-action + ::notice file=entrypoint.sh,line=7::Hello, Mona Lisa Octocat! + ``` + +## Update the Action Metadata + +The [`action.yml`](action.yml) file defines metadata about your action, such as +input(s) and output(s). For details about this file, see +[Metadata syntax for GitHub Actions](https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions). + +When you copy this repository, update `action.yml` with the name, description, +inputs, and outputs for your action. + +> [!IMPORTANT] +> +> Make sure to update the `image` property to use your repository! +> +> ```yaml +> runs: +> using: docker +> image: docker://ghcr.io//: +> ``` + +## Update the Action Code + +In this template, the container action runs a shell script, +[`entrypoint.sh`](./entrypoint.sh), when the container is launched. Since you +can choose any base Docker image and language you like, you can change this to +suite your needs. There are a few main things to remember when writing code for +container actions: + +- Inputs are accessed using argument identifiers or environment variables + (depending on what you set in your `action.yml`). For example, the first input + to this action, `who-to-greet`, can be accessed in the entrypoint script using + the `$INPUT_WHO_TO_GREET` environment variable. + + ```bash + GREETING="Hello, $INPUT_WHO_TO_GREET!" + ``` + +- GitHub Actions supports a number of different workflow commands such as + creating outputs, setting environment variables, and more. These are + accomplished by writing to different `GITHUB_*` environment variables. For + more information, see + [Workflow commands](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions). + + | Scenario | Example | + | --------------------- | ----------------------------------------------- | + | Set environment vars | `echo "MY_VAR=my-value" >> "$GITHUB_ENV"` | + | Set outputs | `echo "greeting=$GREETING" >> "$GITHUB_OUTPUT"` | + | Prepend to `PATH` | `echo "$HOME/.local/bin" >> "$GITHUB_PATH"` | + | Set `pre`/`post` vars | `echo "MY_VAR=my-value" >> "$GITHUB_STATE"` | + | Set step summary | `echo "{markdown}" >> "$GITHUB_STEP_SUMMARY"` | + + You can write multiline strings using the following syntax: + + ```bash + { + echo "JSON_RESPONSE<> "$GITHUB_ENV" + ``` + +- Make sure that the script being run is executable! + + ```bash + git add entrypoint.sh + git update-index --chmod=+x entrypoint.sh + ``` + +So, what are you waiting for? Go ahead and start customizing your action! + +1. Create a new branch + + ```bash + git checkout -b releases/v1 + ``` + +1. Replace the contents of `entrypoint.sh` with your action code +1. Build and test the container + + ```bash + docker build -t actions/container-prebuilt-action . + docker run actions/container-prebuilt-action "Mona Lisa Octocat" + ``` + +1. Commit your changes + + ```bash + git add . + git commit -m "My first action is ready!" + ``` + +1. Push them to your repository + + ```bash + git push -u origin releases/v1 + ``` + +1. Create a pull request and get feedback on your action +1. Merge the pull request into the `main` branch + +Your action is now published! :rocket: + +For information about versioning your action, see +[Versioning](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md) +in the GitHub Actions toolkit. + +## Usage + +After testing, you can create version tag(s) that developers can use to +reference different stable versions of your action. For more information, see +[Versioning](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md) +in the GitHub Actions toolkit. + +To include the action in a workflow in another repository, you can use the +`uses` syntax with the `@` symbol to reference a specific branch, tag, or commit +hash. + +```yaml +steps: + - name: Checkout + id: checkout + uses: actions/checkout@v3 + + - name: Test Local Action + id: test-action + uses: actions/container-prebuilt-action@v1 # Commit with the `v1` tag + with: + who-to-greet: Mona Lisa Octocat + + - name: Print Output + id: output + run: echo "${{ steps.test-action.outputs.greeting }}" +``` diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..b6348b4 --- /dev/null +++ b/action.yml @@ -0,0 +1,22 @@ +name: The name of your action here +description: Provide a description here +author: Your name or organization here + +# Define your inputs here. +inputs: + who-to-greet: + description: Your input description here + required: true + default: World + +# Define your outputs here. +outputs: + greeting: + description: Your output description here + +# Update the image repository and tag below. +runs: + using: docker + image: docker://ghcr.io/actions/container-prebuilt-action:latest + env: + INPUT_WHO_TO_GREET: ${{ inputs.who-to-greet }} diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..22c9865 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,12 @@ +#!/bin/sh -l + +# Use INPUT_ to get the value of an input +GREETING="Hello, $INPUT_WHO_TO_GREET!" + +# Use workflow commands to do things like set debug messages +echo "::notice file=entrypoint.sh,line=7::$GREETING" + +# Write outputs to the $GITHUB_OUTPUT file +echo "greeting=$GREETING" >> "$GITHUB_OUTPUT" + +exit 0