diff --git a/aws/aws-cli/Dockerfile b/aws/aws-cli/Dockerfile new file mode 100644 index 0000000..3090647 --- /dev/null +++ b/aws/aws-cli/Dockerfile @@ -0,0 +1,7 @@ +# Container image that runs your code +FROM amazon/aws-cli:2.9.15 + +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/aws/aws-cli/action.yaml b/aws/aws-cli/action.yaml new file mode 100644 index 0000000..d55eef6 --- /dev/null +++ b/aws/aws-cli/action.yaml @@ -0,0 +1,28 @@ +name: aws-cli +description: "Run aws cli commands." +inputs: + args: + description: "Arguments to pass into the aws cli." + required: true + accessKey: + description: "AWS access key." + required: true + secretKey: + description: "AWS secret key." + required: true + region: + description: "AWS region." + required: true + default: us-gov-west-1 +outputs: + console: + description: "The console output of the aws command." +runs: + using: docker + image: Dockerfile + env: + AWS_ACCESS_KEY_ID: ${{ inputs.accessKey }} + AWS_SECRET_ACCESS_KEY: ${{ inputs.secretKey }} + AWS_DEFAULT_REGION: ${{ inputs.region }} + args: + - ${{ inputs.args }} \ No newline at end of file diff --git a/aws/aws-cli/entrypoint.sh b/aws/aws-cli/entrypoint.sh new file mode 100644 index 0000000..34ef6b8 --- /dev/null +++ b/aws/aws-cli/entrypoint.sh @@ -0,0 +1,16 @@ +#!/bin/sh +ARGS="$@" + +OUTPUT=$(bash -c "aws $ARGS") +RESULT=$? +echo "$OUTPUT" + +#Output multiline strings. +#https://trstringer.com/github-actions-multiline-strings/ +if [[ -n "$OUTPUT" ]]; then + echo "console<> "$GITHUB_OUTPUT" + echo "$OUTPUT" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" +fi + +exit $RESULT \ No newline at end of file diff --git a/aws/aws-s3-cp/action.yaml b/aws/aws-s3-cp/action.yaml new file mode 100644 index 0000000..895f7ab --- /dev/null +++ b/aws/aws-s3-cp/action.yaml @@ -0,0 +1,29 @@ +name: aws-s3-cp +description: "Copy files to or from s3." +inputs: + target: + description: "Target file." + required: true + dest: + description: "Destination file." + required: true + accessKey: + description: "AWS access key." + required: true + secretKey: + description: "AWS secret key." + required: true + region: + description: "AWS region." + required: true + default: us-gov-west-1 +runs: + using: "composite" + steps: + - name: "Copy files to/from S3." + uses: act/common/aws/aws-cli@master + with: + args: s3 cp "${{ inputs.target }}" "${{ inputs.dest }}" --recursive + accessKey: ${{ inputs.accessKey }} + secretKey: ${{ inputs.secretKey }} + region: ${{ inputs.region }} diff --git a/distros/busybox/Dockerfile b/distros/busybox/Dockerfile index a5caa7a..de6e90e 100644 --- a/distros/busybox/Dockerfile +++ b/distros/busybox/Dockerfile @@ -4,4 +4,4 @@ FROM busybox:1.36.0 COPY entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh -ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file +ENTRYPOINT ["/entrypoint.sh"] diff --git a/distros/debian/Dockerfile b/distros/debian/Dockerfile new file mode 100644 index 0000000..01b52d2 --- /dev/null +++ b/distros/debian/Dockerfile @@ -0,0 +1,11 @@ +# Container image that runs your code +FROM debian:12.0 + +RUN apt update && apt upgrade -y +RUN apt install -y \ + gridsite-clients + +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/distros/debian/action.yaml b/distros/debian/action.yaml new file mode 100644 index 0000000..104803b --- /dev/null +++ b/distros/debian/action.yaml @@ -0,0 +1,14 @@ +name: debian +description: "Run Debian commands." +inputs: + args: + description: "Shell arguments to pass into Debian." + required: true +outputs: + console: + description: "The console output of the command." +runs: + using: docker + image: Dockerfile + args: + - "${{ inputs.args }}" \ No newline at end of file diff --git a/distros/debian/entrypoint.sh b/distros/debian/entrypoint.sh new file mode 100644 index 0000000..585ce6d --- /dev/null +++ b/distros/debian/entrypoint.sh @@ -0,0 +1,16 @@ +#!/bin/bash +ARGS="$@" + +OUTPUT=$(bash -c "$ARGS") +RESULT=$? +echo "$OUTPUT" + +#Output multiline strings. +#https://trstringer.com/github-actions-multiline-strings/ +if [[ -n "$OUTPUT" ]]; then + echo "console<> "$GITHUB_OUTPUT" + echo "$OUTPUT" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" +fi + +exit $RESULT diff --git a/distros/rockylinux/Dockerfile b/distros/rockylinux/Dockerfile new file mode 100644 index 0000000..7113e20 --- /dev/null +++ b/distros/rockylinux/Dockerfile @@ -0,0 +1,19 @@ +# Container image that runs your code +FROM rockylinux:9.1 + +RUN dnf install -y \ + rpm-sign \ + unzip \ + pinentry \ + wget \ + uuid \ + gettext + +COPY setup_gpg.sh /setup_gpg.sh +RUN chmod +x /setup_gpg.sh +RUN /setup_gpg.sh + +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/distros/rockylinux/action.yaml b/distros/rockylinux/action.yaml new file mode 100644 index 0000000..c227b42 --- /dev/null +++ b/distros/rockylinux/action.yaml @@ -0,0 +1,14 @@ +name: rockylinux +description: "Run rockylinux commands." +inputs: + args: + description: "Shell arguments to pass into Rocky Linux." + required: true +outputs: + console: + description: "The console output of the command." +runs: + using: docker + image: Dockerfile + args: + - "${{ inputs.args }}" diff --git a/distros/rockylinux/entrypoint.sh b/distros/rockylinux/entrypoint.sh new file mode 100644 index 0000000..31fa785 --- /dev/null +++ b/distros/rockylinux/entrypoint.sh @@ -0,0 +1,16 @@ +#!/bin/sh +ARGS="$@" + +OUTPUT=$(bash -c "$ARGS") +RESULT=$? +echo "$OUTPUT" + +#Output multiline strings. +#https://trstringer.com/github-actions-multiline-strings/ +if [[ -n "$OUTPUT" ]]; then + echo "console<> "$GITHUB_OUTPUT" + echo "$OUTPUT" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" +fi + +exit $RESULT diff --git a/distros/rockylinux/setup_gpg.sh b/distros/rockylinux/setup_gpg.sh new file mode 100644 index 0000000..9508525 --- /dev/null +++ b/distros/rockylinux/setup_gpg.sh @@ -0,0 +1,29 @@ +#!/bin/bash +#Importing gpg key via cli +#https://d.sb/2016/11/gpg-inappropriate-ioctl-for-device-errors +GPG_CONF="$HOME/.gnupg/gpg.conf" +GPG_AGENT_CONF="$HOME/.gnupg/gpg-agent.conf" + +function create_file +{ + FILE_PATH="$1" + CONTENTS="$2" + DIR=$(dirname "$FILE_PATH") + + mkdir -p "$DIR" + chmod 700 "$DIR" + echo "$CONTENTS" > "$FILE_PATH" +} + +create_file "$GPG_CONF" "$(cat <> "$GITHUB_OUTPUT" + shell: bash + - name: "Restore NuGet packages." + if: ${{ steps.nuget.outputs.restoreMode == 'true' }} + uses: act/common/dotnet/dotnet@master + with: + program: nugetforunity + command: restore "${{ inputs.projectPath }}" + - name: "Own artifacts." + if: ${{ steps.nuget.outputs.restoreMode == 'true' }} + uses: act/common/utils/chown@master + with: + file: ${{ inputs.projectPath }}/Assets/Packages diff --git a/dotnet/dotnet-push/action.yaml b/dotnet/dotnet-push/action.yaml new file mode 100644 index 0000000..4db5e3e --- /dev/null +++ b/dotnet/dotnet-push/action.yaml @@ -0,0 +1,24 @@ +name: dotnet-push +description: "Push a nuget package with dotnet." +inputs: + nupkg: + description: "Path to the .nupkg to push." + required: true + url: + description: "URL of the nuget repository to push to." + required: true + default: ${{ github.server_url }}/_registry/nuget/${{ github.repository_owner }}/index.json + apiKey: + description: "ApiKey of the nuget repository to push to." + required: true + default: ${{ github.token }} + options: + description: "Additional options when pushing the .nupkg." + required: false +runs: + using: "composite" + steps: + - name: "Push the NuGet package." + uses: act/common/dotnet/dotnet@master + with: + command: nuget push ${{ inputs.nupkg }} -s ${{ inputs.url }} -k ${{ inputs.apiKey }} ${{ inputs.options }} \ No newline at end of file diff --git a/dotnet/dotnet/Dockerfile b/dotnet/dotnet/Dockerfile new file mode 100644 index 0000000..b3169bc --- /dev/null +++ b/dotnet/dotnet/Dockerfile @@ -0,0 +1,14 @@ +ARG VERSION=7.0 +FROM mcr.microsoft.com/dotnet/sdk:$VERSION + +RUN apt update +RUN apt install curl -y + +# Add tools to Path. +RUN echo 'export PATH="$PATH:$HOME/.dotnet/tools/"' | tee -a "$HOME/.bashrc" > /dev/null +# Install NugetForUnity tool: https://github.com/GlitchEnzo/NuGetForUnity +RUN dotnet tool install --global NuGetForUnity.Cli + +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/dotnet/dotnet/action.yaml b/dotnet/dotnet/action.yaml new file mode 100644 index 0000000..d9927cd --- /dev/null +++ b/dotnet/dotnet/action.yaml @@ -0,0 +1,21 @@ +name: dotnet +description: "Run a dotnet command." +inputs: + command: + description: "Dotnet command to run." + required: false + program: + description: "Program to run instead of dotnet. Default: dotnet" + required: false + default: "dotnet" + catchErrors: + description: "Whether or not errors should be handled." + required: false +runs: + env: + PROGRAM: ${{ inputs.program }} + CATCH_ERRORS: ${{ inputs.catchErrors }} + using: 'docker' + image: 'Dockerfile' + args: + - ${{ inputs.command }} \ No newline at end of file diff --git a/dotnet/dotnet/entrypoint.sh b/dotnet/dotnet/entrypoint.sh new file mode 100644 index 0000000..88743f2 --- /dev/null +++ b/dotnet/dotnet/entrypoint.sh @@ -0,0 +1,25 @@ +#!/bin/bash +COMMAND="$@" +set -o pipefail + +# Add root tools to Path. +export PATH="$PATH:/root/.dotnet/tools/" + +PROGRAM=${PROGRAM:-"dotnet"} +exec 5>&1 +OUTPUT=$(bash -c "$PROGRAM $COMMAND" | tee /dev/fd/5) +RESULT=$? + +#Output multiline strings. +#https://trstringer.com/github-actions-multiline-strings/ +if [[ -n "$OUTPUT" ]]; then + echo "console<> "$GITHUB_OUTPUT" + echo "$OUTPUT" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" +fi + +echo "exitCode=$RESULT" >> "$GITHUB_OUTPUT" + +if [[ "$CATCH_ERRORS" != "true" ]]; then + exit $RESULT +fi \ No newline at end of file diff --git a/gitea/gitea-get-next-branched-version/action.yaml b/gitea/gitea-get-next-branched-version/action.yaml new file mode 100644 index 0000000..d386cc6 --- /dev/null +++ b/gitea/gitea-get-next-branched-version/action.yaml @@ -0,0 +1,89 @@ +name: gitea-get-next-branched-version +description: "Get the next version of a Gitea package based on the current branch status." +inputs: + name: + description: "The name of the package." + required: true + defaultVersion: + description: "Default version to use." + required: true + default: 1.0.0 + url: + description: "Url of the Gitea server instance." + required: true + default: ${{ github.server_url }} + organization: + description: "Organization to search." + required: true + default: ${{ github.repository_owner }} + apiToken: + description: "Api Token for Gitea." + required: true + default: ${{ github.token }} + type: + description: "The type of package to search for." + required: false + default: "" + page: + description: "The page number of results to return." + required: false + default: "" + limit: + description: "The page size of results." + required: false + default: "" + prerelease: + description: "Query prerelease packages. Values: true, false." + required: false + default: "${{ github.event_name == 'pull_request' }}" +outputs: + latestVersion: + description: "The current latest version for the .nupkg." + value: ${{ steps.version.outputs.version || steps.packageFallback.outputs.version }} + nextVersion: + description: "The next version for the .nupkg file." + value: ${{ steps.version.outputs.nextVersion }} +runs: + using: "composite" + steps: + - name: "Get the base version for the package." + uses: act/common/utils/version-increment-branch@master + id: base + with: + version: ${{ inputs.defaultVersion }} + - run: echo "${{ steps.base.outputs.majorMinorPatchVersion }}" + - name: "Get versions." + id: package + uses: act/common/gitea/gitea-query-package-versions-latest@master + with: + url: ${{ inputs.url }} + organization: ${{ inputs.organization }} + apiToken: ${{ inputs.apiToken }} + type: ${{ inputs.type }} + page: ${{ inputs.page }} + limit: ${{ inputs.limit }} + name: ${{ inputs.name }} + filter: ^${{ steps.base.outputs.baseVersion }} + prerelease: ${{ inputs.prerelease }} + - name: "If no version is found, get the latest version for the package if we didn't already look for it." + uses: act/common/gitea/gitea-query-package-versions-latest@master + id: packageFallback + if: ${{ steps.version.outputs.version == '' && inputs.prerelease != 'false' }} + with: + url: ${{ inputs.url }} + organization: ${{ inputs.organization }} + apiToken: ${{ inputs.apiToken }} + type: ${{ inputs.type }} + page: ${{ inputs.page }} + limit: ${{ inputs.limit }} + name: ${{ inputs.name }} + filter: ^${{ steps.base.outputs.majorMinorPatchVersion }} + prerelease: false + - run: echo "${{ steps.version.outputs.version == '' }}" AND "${{ inputs.prerelease != 'false' }}" + - if: ${{ steps.version.outputs.version == '' && inputs.prerelease != 'false' }} + run: echo "${{ steps.packageFallback.outputs.version }}" + - name: "Get the next version for the package." + uses: act/common/utils/version-increment-branch@master + id: version + with: + version: ${{ steps.package.outputs.version || steps.packageFallback.outputs.version || inputs.defaultVersion }} diff --git a/gitea/gitea-query-package-versions-latest/action.yaml b/gitea/gitea-query-package-versions-latest/action.yaml new file mode 100644 index 0000000..29d3ab2 --- /dev/null +++ b/gitea/gitea-query-package-versions-latest/action.yaml @@ -0,0 +1,71 @@ +name: gitea-query-package-versions-latest +description: "Get the latest version of a package." +inputs: + url: + description: "Url of the Gitea server instance." + required: true + default: ${{ github.server_url }} + organization: + description: "Organization to search." + required: true + default: ${{ github.repository_owner }} + apiToken: + description: "Api Token for Gitea." + required: true + default: ${{ github.token }} + type: + description: "The type of package to search for." + required: false + default: "" + page: + description: "The page number of results to return." + required: false + default: "" + limit: + description: "The page size of results." + required: false + default: "" + prerelease: + description: "Whether to include prerelease packages. Values: true, false." + required: false + default: "false" + name: + description: "Name of a specific package." + required: true + filter: + description: "String to filter by." + required: false + filterIsExpression: + description: "Is the first filter a Regular Expression? Values: true, false." + required: false + default: "false" + additionalArgs: + description: "Additional arguments to pass into curl." + required: false +outputs: + version: + description: "The latest version of the specified package." + value: ${{ steps.parse.outputs.version }} +runs: + using: "composite" + steps: + - name: "Get versions." + id: versions + uses: act/common/gitea/gitea-query-package-versions@master + with: + url: ${{ inputs.url }} + organization: ${{ inputs.organization }} + apiToken: ${{ inputs.apiToken }} + type: ${{ inputs.type }} + page: ${{ inputs.page }} + limit: ${{ inputs.limit }} + name: ${{ inputs.name }} + additionalArgs: ${{ inputs.additionalArgs }} + - name: "Parse query result." + id: parse + uses: act/common/utils/get-latest-version@master + with: + versions: ${{ steps.versions.outputs.versions }} + filter: ${{ inputs.filter }} + filterIsExpression: ${{ inputs.filterIsExpression }} + stripPrerelease: ${{ inputs.prerelease == 'false' }} diff --git a/gitea/gitea-query-package-versions/action.yaml b/gitea/gitea-query-package-versions/action.yaml new file mode 100644 index 0000000..cce3bd5 --- /dev/null +++ b/gitea/gitea-query-package-versions/action.yaml @@ -0,0 +1,58 @@ +name: github-query-nuget-versions +description: "Change the language format of a file." +inputs: + url: + description: "Url of the GitHub server repository." + required: true + default: ${{ github.server_url }} + organization: + description: "Organization to search." + required: true + default: ${{ github.repository_owner }} + apiToken: + description: "Api Token to for GitHub." + required: true + default: ${{ github.token }} + type: + description: "The type of package to search for." + required: false + default: "" + page: + description: "The page number of results to return." + required: false + default: "" + limit: + description: "The page size of results." + required: false + default: "" + name: + description: "Name of a specific package." + required: true + additionalArgs: + description: "Additional arguments to pass into curl." + required: false +outputs: + versions: + description: "The versions of the specified package." + value: ${{ steps.parse.outputs.result }} +runs: + using: "composite" + steps: + - name: "Build and run query." + id: query + uses: act/common/gitea/gitea-query-packages@master + with: + url: ${{ inputs.url }} + organization: ${{ inputs.organization }} + apiToken: ${{ inputs.apiToken }} + type: ${{ inputs.type }} + page: ${{ inputs.page }} + limit: ${{ inputs.limit }} + name: ${{ inputs.name }} + additionalArgs: ${{ inputs.additionalArgs }} + - name: "Parse query result." + id: parse + uses: act/common/yq/yq-expression@master + with: + expression: .[] | select(.name == "${{ inputs.name }}").version + input: ${{ steps.query.outputs.query }} diff --git a/gitea/gitea-query-packages/action.yaml b/gitea/gitea-query-packages/action.yaml new file mode 100644 index 0000000..821831b --- /dev/null +++ b/gitea/gitea-query-packages/action.yaml @@ -0,0 +1,73 @@ +name: gitea-query-packages +description: "Change the language format of a file." +inputs: + url: + description: "Url of the Gitea server repository." + required: true + default: ${{ github.server_url }} + organization: + description: "Organization to search." + required: true + default: ${{ github.repository_owner }} + apiToken: + description: "Api Token to for Gitea." + required: true + default: ${{ github.token }} + type: + description: "The type of package to search for." + required: false + default: "" + page: + description: "The page number of results to return." + required: false + default: "" + limit: + description: "The page size of results." + required: false + default: "" + name: + description: "Name of a specific package." + required: false + default: "" + additionalArgs: + description: "Additional arguments to pass into curl." + required: false +outputs: + query: + description: "The query result." + value: ${{ steps.query.outputs.query }} +runs: + using: "composite" + steps: + - name: "Build route." + id: route + run: | + ROUTE="/api/v1/packages/${{ inputs.organization }}?" + NAME="${{ inputs.name }}" + TYPE="${{ inputs.type }}" + PAGE="${{ inputs.page }}" + LIMIT="${{ inputs.limit }}" + + if [[ -n "$NAME" ]]; then + ROUTE="${ROUTE}q=$NAME&" + fi + if [[ -n "$TYPE" ]]; then + ROUTE="${ROUTE}type=$TYPE&" + fi + if [[ -n "$PAGE" ]]; then + ROUTE="${ROUTE}page=$PAGE&" + fi + if [[ -n "$LIMIT" ]]; then + ROUTE="${ROUTE}limit=$LIMIT&" + fi + + echo "route=$ROUTE" >> "$GITHUB_OUTPUT" + shell: bash + - name: "Build and run query." + id: query + uses: act/common/github/github-query@master + with: + url: ${{ inputs.url }} + route: ${{ steps.route.outputs.route }} + apiToken: ${{ inputs.apiToken }} + additionalArgs: ${{ inputs.additionalArgs }} diff --git a/gitea/gitea-upload-generic-package/action.yaml b/gitea/gitea-upload-generic-package/action.yaml new file mode 100644 index 0000000..07906bf --- /dev/null +++ b/gitea/gitea-upload-generic-package/action.yaml @@ -0,0 +1,69 @@ +name: gitea-upload-generic-package +description: "Upload a generic package to Gitea." +inputs: + url: + description: "Url of the Gitea server repository." + required: true + default: ${{ github.server_url }} + organization: + description: "Organization to upload the package to." + required: true + default: ${{ github.repository_owner }} + apiToken: + description: "Api Token to for Gitea." + required: true + default: ${{ github.token }} + version: + description: "The version of package to upload." + required: false + default: "" + name: + description: "Name of the package." + required: false + default: "" + file: + description: "Path of the file to upload." + required: false + default: "" + filename: + description: "Name to upload the file as. Defaults to the basename of the file." + required: false + default: "" + additionalArgs: + description: "Additional arguments to pass into curl." + required: false +outputs: + query: + description: "The query result." + value: ${{ steps.query.outputs.query }} +runs: + using: "composite" + steps: + - name: "Get filename." + id: file + run: | + FILE="${{ inputs.filename }}" + if [[ -z "$FILE" ]]; then + FILE="${{ inputs.file }}" + fi + FILE=$(basename "$FILE") + echo "file=$FILE" >> "$GITHUB_OUTPUT" + shell: bash + - uses: act/common/utils/urlencode@master + id: url + with: + input: ${{ steps.file.outputs.file }} + - name: "Build route." + id: route + run: | + ROUTE="/api/packages/${{ inputs.organization }}/generic/${{ inputs.name }}/${{ inputs.version }}/${{ steps.url.outputs.result }}" + echo "route=$ROUTE" >> "$GITHUB_OUTPUT" + shell: bash + - name: "Build and run query." + id: query + uses: act/common/github/github-query@master + with: + url: ${{ inputs.url }} + route: ${{ steps.route.outputs.route }} + apiToken: ${{ inputs.apiToken }} + additionalArgs: --upload-file "${{ inputs.file }}" ${{ inputs.additionalArgs }} diff --git a/github/github-query-nuget-versions-latest/action.yaml b/github/github-query-nuget-versions-latest/action.yaml new file mode 100644 index 0000000..c908b23 --- /dev/null +++ b/github/github-query-nuget-versions-latest/action.yaml @@ -0,0 +1,56 @@ +name: github-query-nuget-versions-latest +description: "Get the latest version of a NuGet package." +inputs: + url: + description: "Url of the GitHub server instance." + required: true + default: ${{ github.server_url }} + organization: + description: "Organization to search." + required: true + default: ${{ github.repository_owner }} + apiToken: + description: "Api Token for GitHub." + required: true + default: ${{ github.token }} + prerelease: + description: "Show prerelease packages. Values: true, false." + required: false + default: "false" + name: + description: "Name of a specific package." + required: true + filter: + description: "String to filter by." + required: false + filterIsExpression: + description: "Is the first filter a Regular Expression? Values: true, false." + required: false + default: "false" + additionalArgs: + description: "Additional arguments to pass into curl." + required: false +outputs: + version: + description: "The latest version of the specified package." + value: ${{ steps.parse.outputs.version }} +runs: + using: "composite" + steps: + - name: "Get versions." + id: versions + uses: act/common/github/github-query-nuget-versions@master + with: + url: ${{ inputs.url }} + organization: ${{ inputs.organization }} + apiToken: ${{ inputs.apiToken }} + prerelease: ${{ inputs.prerelease }} + name: ${{ inputs.name }} + additionalArgs: ${{ inputs.additionalArgs }} + - name: "Parse query result." + id: parse + uses: act/common/utils/get-latest-version@master + with: + versions: ${{ steps.versions.outputs.versions }} + filter: ${{ inputs.filter }} + filterIsExpression: ${{ inputs.filterIsExpression }} \ No newline at end of file diff --git a/github/github-query-nuget-versions/action.yaml b/github/github-query-nuget-versions/action.yaml new file mode 100644 index 0000000..f2469ee --- /dev/null +++ b/github/github-query-nuget-versions/action.yaml @@ -0,0 +1,48 @@ +name: github-query-nuget-versions +description: "Get the versions of a NuGet package." +inputs: + url: + description: "Url of the GitHub server repository." + required: true + default: ${{ github.server_url }} + organization: + description: "Organization to search." + required: true + default: ${{ github.repository_owner }} + apiToken: + description: "Api Token to for GitHub." + required: true + default: ${{ github.token }} + prerelease: + description: "Show prerelease packages. Values: true, false." + required: false + default: "false" + name: + description: "Name of a specific package." + required: true + additionalArgs: + description: "Additional arguments to pass into curl." + required: false +outputs: + versions: + description: "The versions of the specified package." + value: ${{ steps.parse.outputs.result }} +runs: + using: "composite" + steps: + - name: "Build and run query." + id: query + uses: act/common/github/github-query-nuget@master + with: + url: ${{ inputs.url }} + organization: ${{ inputs.organization }} + apiToken: ${{ inputs.apiToken }} + prerelease: ${{ inputs.prerelease }} + name: ${{ inputs.name }} + additionalArgs: ${{ inputs.additionalArgs }} + - name: "Parse query result." + id: parse + uses: act/common/yq/yq-expression@master + with: + expression: .data[] | select(.id == "${{ inputs.name }}").versions[].version + input: ${{ steps.query.outputs.query }} diff --git a/github/github-query-nuget/action.yaml b/github/github-query-nuget/action.yaml new file mode 100644 index 0000000..f6fbd0c --- /dev/null +++ b/github/github-query-nuget/action.yaml @@ -0,0 +1,56 @@ +name: github-query-nuget +description: "Make a query to the GitHub NuGet api." +inputs: + url: + description: "Url of the GitHub server repository." + required: true + default: ${{ github.server_url }} + organization: + description: "Organization to search." + required: true + default: ${{ github.repository_owner }} + apiToken: + description: "Api Token to for GitHub." + required: true + default: ${{ github.token }} + prerelease: + description: "Show prerelease packages. Values: true, false." + required: false + default: "false" + name: + description: "Name of a specific package." + required: false + default: "" + additionalArgs: + description: "Additional arguments to pass into curl." + required: false +outputs: + query: + description: "The query result." + value: ${{ steps.query.outputs.query }} +runs: + using: "composite" + steps: + - name: "Build route." + id: route + run: | + ROUTE="/_registry/nuget/${{ inputs.organization }}/query?" + NAME="${{ inputs.name }}" + PRERELEASE="${{ inputs.prerelease }}" + if [[ "$PRERELEASE" == "true" ]]; then + ROUTE="${ROUTE}prerelease=true&" + fi + if [[ -n "$NAME" ]]; then + ROUTE="${ROUTE}q=$NAME" + fi + + echo "route=$ROUTE" >> "$GITHUB_OUTPUT" + shell: bash + - name: "Build and run query." + id: query + uses: act/common/github/github-query@master + with: + url: ${{ inputs.url }} + route: ${{ steps.route.outputs.route }} + apiToken: ${{ inputs.apiToken }} + additionalArgs: ${{ inputs.additionalArgs }} diff --git a/github/github-query/action.yaml b/github/github-query/action.yaml new file mode 100644 index 0000000..fa7222e --- /dev/null +++ b/github/github-query/action.yaml @@ -0,0 +1,54 @@ +name: github-query +description: "Make a query to GitHub." +inputs: + url: + description: "Url of the GitHub server repository." + required: true + default: ${{ github.server_url }} + route: + description: "Route of the api to call." + required: false + default: "" + apiToken: + description: "Api Token to for GitHub." + required: false + default: ${{ github.token }} + additionalArgs: + description: "Additional arguments to pass into curl." + required: false +outputs: + query: + description: "The query result." + value: ${{ steps.query.outputs.console }} +runs: + using: "composite" + steps: + - name: "Build and run query." + id: query + run: | + URL_ROOT="${{ inputs.url }}" + # Remove any trailing slash from the url root + URL_ROOT=${URL_ROOT%/} + # Remove any leading slash from the route + ROUTE="${{ inputs.route }}" + ROUTE=${ROUTE#/} + + FULL_URL="$URL_ROOT/$ROUTE" + + QUERY="curl -sL \"$FULL_URL\" ${{ inputs.additionalArgs }}" + + TOKEN="${{ inputs.apiToken }}" + if [[ -n "$TOKEN" ]]; then + QUERY="$QUERY -H \"Authorization: token $TOKEN\"" + fi + + OUTPUT=$(eval "$QUERY") + RESULT=$? + + if [[ -n "$OUTPUT" ]]; then + echo "console<> "$GITHUB_OUTPUT" + echo "$OUTPUT" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + fi + exit $RESULT + shell: bash \ No newline at end of file diff --git a/minio/mc-find-tags/action.yaml b/minio/mc-find-tags/action.yaml new file mode 100644 index 0000000..ac36bb3 --- /dev/null +++ b/minio/mc-find-tags/action.yaml @@ -0,0 +1,84 @@ +name: mc-find-tags +description: "Find files in s3." +inputs: + accessKey: + description: "S3 access key." + required: true + secretKey: + description: "S3 secret key." + required: true + alias: + description: "S3 alias." + required: true + url: + description: "S3 url." + required: true + default: https://s3-us-gov-west-1.amazonaws.com + path: + description: "The path to search for." + required: true + name: + description: "The name pattern to search for." + required: true + default: "" + tags: + description: "The tags/version to search for." + required: true + default: "" + additionalArgs: + description: "Additional arguments." + required: false +outputs: + files: + description: "The path of the found file." + value: ${{ steps.output.outputs.files }} + console: + description: "The console output of the command." + value: ${{ steps.output.outputs.console }} + success: + description: "Whether files were found." + value: ${{ steps.output.outputs.success }} +runs: + using: "composite" + steps: + - name: "Build command." + id: command + run: | + COMMAND="find \"${{ inputs.path }}\" ${{ inputs.additionalArgs }}" + echo "command=$COMMAND" >> "$GITHUB_OUTPUT" + + if [[ -n "${{ inputs.name }}" ]]; then + COMMAND="$COMMAND --name \"${{ inputs.name }}\"" + fi + + if [[ -n "${{ inputs.tags }}" ]]; then + COMMAND="$COMMAND --exec \"mc tag list {}\"" + fi + + shell: bash + - name: "Find file in S3." + id: find + uses: act/common/minio/mc@master + with: + alias: ${{ inputs.alias }} + command: ${{ steps.command.outputs.command }} + accessKey: ${{ inputs.accessKey }} + secretKey: ${{ inputs.secretKey }} + url: ${{ inputs.url }} + catchErrors: true + - name: "Set output." + id: output + run: | + RESULT="${{ steps.find.outputs.exitCode }}" + + if [[ "$RESULT" != "0" ]]; then + SUCCESS="false" + else + echo "console<> "$GITHUB_OUTPUT" + echo "${{ steps.find.outputs.console }}" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + SUCCESS="true" + fi + + echo "success=$SUCCESS" >> "$GITHUB_OUTPUT" + shell: bash diff --git a/minio/mc-find-tags/parse_output.sh b/minio/mc-find-tags/parse_output.sh new file mode 100644 index 0000000..dafadac --- /dev/null +++ b/minio/mc-find-tags/parse_output.sh @@ -0,0 +1,37 @@ +MINIO_URL="$1" +MINIO_ALIAS="$2" + +OUTPUT=$(cat <> "$GITHUB_OUTPUT" +echo "urls=$URLS" >> "$GITHUB_OUTPUT" +echo "aliasedUrls=$ALIASED_URLS" >> "$GITHUB_OUTPUT" \ No newline at end of file diff --git a/mono/ikdasm-files/action.yaml b/mono/ikdasm-files/action.yaml new file mode 100644 index 0000000..f29f09a --- /dev/null +++ b/mono/ikdasm-files/action.yaml @@ -0,0 +1,49 @@ +name: ikdasm-files +description: "Run ikdasm to disassemble .NET assemblies in a folder." +inputs: + directory: + description: "Directory to search." + required: true + default: '.' + pattern: + description: "Pattern of files to search for." + required: true + default: '*.dll' + extension: + description: "Extension of the disassembly files. Default: .dasm" + required: true + default: '.dasm' + deleteAssemblies: + description: "Whether or not the assemblies should be deleted afterwards." + required: false + default: "false" + removeComments: + description: "Whether or not the lines starting with // should be removed from the disassembled files." + required: false + default: "false" + catchErrors: + description: "Whether or not errors should be handled." + required: false +outputs: + console: + description: "The console output of the command." + value: ${{ steps.ikdasm.outputs.console }} +runs: + using: 'composite' + steps: + - name: "Make temporary file of script." + id: script + uses: act/common/utils/mktemp@master + with: + input: ${{ github.action_path }}/disassemble_files.sh + tmpDir: . + - name: "Run ikdasm script." + id: ikdasm + uses: act/common/mono/mono@master + env: + DASM_EXTENSION: ${{ inputs.extension }} + with: + program: bash + command: ${{ steps.script.outputs.tmp }} "${{ inputs.directory }}" "${{ inputs.pattern }}" ${{ inputs.deleteAssemblies }} ${{ inputs.removeComments }} + catchErrors: ${{ inputs.catchErrors }} + \ No newline at end of file diff --git a/mono/ikdasm-files/disassemble_files.sh b/mono/ikdasm-files/disassemble_files.sh new file mode 100644 index 0000000..cb1fd22 --- /dev/null +++ b/mono/ikdasm-files/disassemble_files.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# Get the directory and pattern as arguments +DIR=$1 +PATTERN=$2 +REMOVE_ORIGINAL=$3 +REMOVE_COMMENTS=$4 + +DASM_EXTENSION=${DASM_EXTENSION:-".dasm"} + +find "$DIR" -type f -name "$PATTERN" -print0 | while IFS= read -r -d '' file; do + # Disassemble the file and save it to a temporary file. + OUTFILE="${file}${DASM_EXTENSION}" + TMP=$(mktemp) + ikdasm "$file" > "$TMP" + if [[ "$REMOVE_COMMENTS" == "true" ]]; then + # Remove lines starting with // + sed -i '/^\/\//d' "$TMP" + fi + # Move the temporary file to the output file. + mv "$TMP" "$OUTFILE" + echo $(basename "$OUTFILE") + + if [[ "$REMOVE_ORIGINAL" == "true" ]]; then + rm "$file" + fi +done diff --git a/mono/mono/Dockerfile b/mono/mono/Dockerfile new file mode 100644 index 0000000..d03cd4f --- /dev/null +++ b/mono/mono/Dockerfile @@ -0,0 +1,20 @@ +FROM debian:stable-slim + +ENV NUGET_VERSION=v6.5.0 + +RUN apt-get update +RUN apt-get install -y --no-install-recommends \ + bash \ + wget \ + mono-complete \ + tzdata + +RUN apt-get clean +RUN rm -rf /var/lib/apt/lists/* + +RUN wget https://dist.nuget.org/win-x86-commandline/$NUGET_VERSION/nuget.exe -O /usr/bin/nuget.exe +RUN chmod +x /usr/bin/nuget.exe + +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/mono/mono/action.yaml b/mono/mono/action.yaml new file mode 100644 index 0000000..03c3c3f --- /dev/null +++ b/mono/mono/action.yaml @@ -0,0 +1,24 @@ +name: mono +description: "Run mono commands." +inputs: + command: + description: "Shell arguments to pass into mono." + required: true + program: + description: "Program to run instead of mono. Default: mono" + required: false + default: "mono" + catchErrors: + description: "Whether or not errors should be handled." + required: false +outputs: + console: + description: "The console output of the command." +runs: + env: + PROGRAM: ${{ inputs.program }} + CATCH_ERRORS: ${{ inputs.catchErrors }} + using: docker + image: Dockerfile + args: + - ${{ inputs.command }} \ No newline at end of file diff --git a/mono/mono/entrypoint.sh b/mono/mono/entrypoint.sh new file mode 100644 index 0000000..5b1892b --- /dev/null +++ b/mono/mono/entrypoint.sh @@ -0,0 +1,20 @@ +#!/bin/bash +COMMAND="$@" + +PROGRAM=${PROGRAM:-"mono"} +OUTPUT=$(bash -c "$PROGRAM $COMMAND") +RESULT=$? + +#Output multiline strings. +#https://trstringer.com/github-actions-multiline-strings/ +if [[ -n "$OUTPUT" ]]; then + echo "console<> "$GITHUB_OUTPUT" + echo "$OUTPUT" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" +fi + +echo "exitCode=$RESULT" >> "$GITHUB_OUTPUT" + +if [[ "$CATCH_ERRORS" != "true" ]]; then + exit $RESULT +fi diff --git a/nuget/nuget-build-and-compare/action.yaml b/nuget/nuget-build-and-compare/action.yaml new file mode 100644 index 0000000..0f1daf8 --- /dev/null +++ b/nuget/nuget-build-and-compare/action.yaml @@ -0,0 +1,79 @@ +name: nuget-build-and-compare +description: "Pack a .nuspec file into a .nupkg." +inputs: + name: + description: "The name of the package." + required: true + input: + description: "The json input which will be converted into yaml." + required: true + defaultVersion: + description: "Version of the .nupkg file." + required: true + default: 1.0.0 + outputDirectory: + description: "Directory for the output .nupkg." + required: true + url: + description: "Url of the GitHub server instance." + required: true + default: ${{ github.server_url }} + organization: + description: "Organization to search." + required: true + default: ${{ github.repository_owner }} + username: + description: "Username for the nuget repository to search." + required: true + default: ${{ github.actor }} + password: + description: "Password or ApiKey of the nuget repository to search." + required: true + default: ${{ github.token }} +outputs: + nupkg: + description: "The generated output .nupkg file." + value: ${{ steps.package.outputs.nupkg }} + nupkgName: + description: "The generated output .nupkg file's name." + value: ${{ steps.package.outputs.nupkgName }} + hasChanged: + description: "Whether or not the .nupkg files match." + value: ${{ steps.compare.outputs.success != 'true' }} +runs: + using: "composite" + steps: + - name: "Get the next version of the package." + uses: act/common/nuget/nuget-get-next-branched-version@master + id: nuget + with: + name: ${{ inputs.name }} + defaultVersion: ${{ inputs.defaultVersion }} + url: ${{ inputs.url }} + organization: ${{ inputs.organization }} + apiToken: ${{ inputs.password }} + - name: "Get yaml from json." + id: convert + uses: act/common/yq/yq-convert@master + with: + from: json + to: yaml + input: ${{ inputs.input }} + - name: "Build .nupkg." + id: package + uses: act/common/tpl/tpl-to-nupkg@master + with: + input: ${{ steps.convert.outputs.result }} + version: ${{ steps.nuget.outputs.nextVersion }} + outputDirectory: ${{ inputs.outputDirectory }} + - name: "Compare .nupkg to remote .nupkg." + if: ${{ steps.nuget.outputs.latestVersion }} + id: compare + uses: act/common/nuget/nuget-compare-version@master + with: + lhs: ${{ steps.package.outputs.nupkg }} + version: ${{ steps.nuget.outputs.latestVersion }} + name: ${{ inputs.name }} + username: ${{ inputs.username }} + password: ${{ inputs.password }} + url: ${{ inputs.url }}/_registry/nuget/${{ inputs.organization }}/index.json diff --git a/nuget/nuget-compare-version/action.yaml b/nuget/nuget-compare-version/action.yaml new file mode 100644 index 0000000..5642f3b --- /dev/null +++ b/nuget/nuget-compare-version/action.yaml @@ -0,0 +1,69 @@ +name: nuget-compare-version +description: "Download the desired .nupkg file and compare it to an existing .nupkg file." +inputs: + lhs: + description: "Path to the existing .nupkg file." + required: true + name: + description: "Name of the .nupkg file." + required: true + version: + description: "Version of the .nupkg file." + required: false + default: "" + prerelease: + description: "Install prerelease packages. Values: true, false." + required: false + default: "${{ github.event_name == 'pull_request' }}" + url: + description: "Url of the NuGet repository." + required: true + default: ${{ github.server_url }}/_registry/nuget/${{ github.repository_owner }}/index.json + username: + description: "Username for the nuget repository to search." + required: true + default: ${{ github.actor }} + password: + description: "Password or ApiKey of the nuget repository to search." + required: true + default: ${{ github.token }} + tmpDir: + description: "Temporary directory. Default: _tmp" + required: true + default: _tmp +outputs: + success: + description: "Whether or not the .nupkg files match." + value: ${{ steps.compare.outputs.success }} +runs: + using: "composite" + steps: + - name: "Make temporary folder if we are using .nupkg only." + id: mktmp + uses: act/common/utils/mktemp@master + with: + tmpDir: ${{ inputs.tmpDir }} + outputType: dir + - name: "Get the desired version of the package." + id: install + uses: act/common/nuget/nuget-install@master + with: + name: ${{ inputs.name }} + version: ${{ inputs.version }} + prerelease: ${{ inputs.prerelease }} + url: ${{ inputs.url }} + username: ${{ inputs.username }} + password: ${{ inputs.password }} + outputDirectory: ${{ steps.mktmp.outputs.tmp }} + nupkgOnly: true + directDownload: true + cleanTmp: false + - name: "Compare the two .nupkg files." + id: compare + uses: act/common/utils/compare-nupkg@master + with: + lhs: ${{ inputs.lhs }} + rhs: ${{ steps.install.outputs.nupkg }} + - name: "Remove temporary files." + run: rm -rf "${{ inputs.tmpDir }}" + shell: bash diff --git a/nuget/nuget-get-next-branched-version/action.yaml b/nuget/nuget-get-next-branched-version/action.yaml new file mode 100644 index 0000000..c02b847 --- /dev/null +++ b/nuget/nuget-get-next-branched-version/action.yaml @@ -0,0 +1,66 @@ +name: nuget-get-next-branched-version +description: "Get the next version of a NuGet package based on the current branch status." +inputs: + name: + description: "The name of the package." + required: true + defaultVersion: + description: "Default version to use." + required: true + default: 1.0.0 + url: + description: "Url of the GitHub server instance." + required: true + default: ${{ github.server_url }} + organization: + description: "Organization to search." + required: true + default: ${{ github.repository_owner }} + apiToken: + description: "Api Token for GitHub." + required: true + default: ${{ github.token }} + prerelease: + description: "Query prerelease packages. Values: true, false." + required: false + default: "${{ github.event_name == 'pull_request' }}" +outputs: + latestVersion: + description: "The current latest version for the .nupkg." + value: ${{ steps.nuget.outputs.version || steps.nugetFallback.outputs.version }} + nextVersion: + description: "The next version for the .nupkg file." + value: ${{ steps.version.outputs.nextVersion }} +runs: + using: "composite" + steps: + - name: "Get the base version for the package." + uses: act/common/utils/version-increment-branch@master + id: base + with: + version: ${{ inputs.defaultVersion }} + - uses: act/common/github/github-query-nuget-versions-latest@master + id: nuget + with: + name: ${{ inputs.name }} + url: ${{ inputs.url }} + organization: ${{ inputs.organization }} + apiToken: ${{ inputs.apiToken }} + filter: ^${{ steps.base.outputs.baseVersion }} + prerelease: ${{ inputs.prerelease }} + - name: "If no version is found, get the latest version for the package if we didn't already look for it." + uses: act/common/github/github-query-nuget-versions-latest@master + id: nugetFallback + if: ${{ steps.nuget.outputs.version == '' && inputs.prerelease != 'false' }} + with: + name: ${{ inputs.name }} + url: ${{ inputs.url }} + organization: ${{ inputs.organization }} + apiToken: ${{ inputs.apiToken }} + filter: ^${{ steps.base.outputs.majorMinorPatchVersion }} + prerelease: false + - name: "Get the next version for the package." + uses: act/common/utils/version-increment-branch@master + id: version + with: + version: ${{ steps.nuget.outputs.version || steps.nugetFallback.outputs.version || inputs.defaultVersion }} diff --git a/nuget/nuget-install/action.yaml b/nuget/nuget-install/action.yaml new file mode 100644 index 0000000..ad05b80 --- /dev/null +++ b/nuget/nuget-install/action.yaml @@ -0,0 +1,135 @@ +name: nuget-install +description: "Download the desired .nupkg file." +inputs: + name: + description: "Name of the .nupkg file." + required: true + version: + description: "Version of the .nupkg file." + required: false + default: "" + prerelease: + description: "Install prerelease packages. Values: true, false." + required: false + default: "false" + outputDirectory: + description: "Directory for the output file." + required: true + default: "." + directDownload: + description: "Download the .nupkg file directly from the source." + required: true + default: "true" + excludeVersion: + description: "Exclude the version when downloading the .nuget package." + required: true + default: "false" + nupkgOnly: + description: "Only output the .nupkg file directly to the output directory." + required: true + default: "false" + additionalArgs: + description: "Additional arguments to use when dowloading the .nupkg file." + required: false + source: + description: "Name of the source to use." + required: true + default: lewdorg + url: + description: "Url of the NuGet repository." + required: true + default: ${{ github.server_url }}/_registry/nuget/${{ github.repository_owner }}/index.json + username: + description: "Username for the nuget repository to search." + required: true + default: ${{ github.actor }} + password: + description: "Password or ApiKey of the nuget repository to search." + required: true + default: ${{ github.token }} + tmpDir: + description: "Temporary directory. Default: _tmp" + required: true + default: _tmp + cleanTmp: + description: "Remove the temporary directory after use. Default: true" + required: true + default: "true" +outputs: + nupkg: + description: "The path to the .nupkg file." + value: ${{ steps.move.outputs.nupkg }} +runs: + using: "composite" + steps: + - name: "Make temporary folder if we are using .nupkg only." + id: mktmp + uses: act/common/utils/mktemp@master + with: + tmpDir: ${{ inputs.tmpDir }} + outputType: dir + - name: "Create Output Directory" + run: | + OUTPUT_DIR="${{ inputs.outputDirectory }}" + mkdir "$OUTPUT_DIR" -p + shell: bash + - name: "Build nuget command." + id: command + run: | + COMMAND="install ${{ inputs.name }} -OutputDirectory \"${{ steps.mktmp.outputs.tmp }}\" ${{ inputs.additionalArgs }}" + VERSION="${{ inputs.version }}" + PRERELEASE="${{ inputs.prerelease }}" + DIRECT="${{ inputs.directDownload }}" + + if [ "$DIRECT" == "true" ]; then + COMMAND="$COMMAND -DirectDownload" + fi + if [ -n "$VERSION" ]; then + COMMAND="$COMMAND -Version $VERSION" + fi + if [ "$PRERELEASE" == "true" ]; then + COMMAND="$COMMAND -Prerelease" + fi + echo "command=$COMMAND" >> "$GITHUB_OUTPUT" + shell: bash + - name: "Download the .nupkg file." + uses: act/common/nuget/nuget@master + with: + command: ${{ steps.command.outputs.command }} + username: ${{ inputs.username }} + password: ${{ inputs.password }} + source: ${{ inputs.source }} + url: ${{ inputs.url }} + - name: "Take ownership of the artifacts." + uses: act/common/utils/chown@master + with: + file: ${{ steps.mktmp.outputs.tmp }} + - name: "Copy contents to output folder." + id: move + run: | + OUTPUT_DIR="${{ inputs.outputDirectory }}" + TMP_DIR="${{ steps.mktmp.outputs.tmp }}" + EXCLUDE_VERSION="${{ inputs.excludeVersion }}" + NUPKG_ONLY="${{ inputs.nupkgOnly }}" + + if [ "$EXCLUDE_VERSION" == "true" ]; then + NUPKG_NAME="${{ inputs.name }}.nupkg" + else + # Get the subdirectory name + OUTDIR=($TMP_DIR/*) + BASE_NAME=$(basename "$OUTDIR") + NUPKG_NAME="${BASE_NAME}.nupkg" + fi + + if [ "$NUPKG_ONLY" == "true" ]; then + mv "$OUTDIR/$NUPKG_NAME" "$OUTPUT_DIR" + echo "nupkg=$OUTPUT_DIR/$NUPKG_NAME" >> "$GITHUB_OUTPUT" + else + mv "$TMP_DIR"/* "$OUTPUT_DIR" + echo "nupkg=$OUTPUT_DIR/$OUTDIR/$NUPKG_NAME" >> "$GITHUB_OUTPUT" + fi + shell: bash + - name: "Remove temporary files." + if: ${{ inputs.cleanTmp == 'true' }} + run: rm -rf "${{ inputs.tmpDir }}" + shell: bash \ No newline at end of file diff --git a/nuget/nuget-pack/action.yaml b/nuget/nuget-pack/action.yaml new file mode 100644 index 0000000..3b026d0 --- /dev/null +++ b/nuget/nuget-pack/action.yaml @@ -0,0 +1,37 @@ +name: nuget-pack +description: "Pack a .nuspec file into a .nupkg." +inputs: + nuspec: + description: "The .nuspec file or configuration to pack." + required: true + version: + description: "Version of the .nupkg file." + required: true + outputDirectory: + description: "Directory for the output file." + required: true + additionalArgs: + description: "Additional arguments to use when packing the .nuspec file." + required: false +runs: + using: "composite" + steps: + - name: "Make temporary file of nuspec." + id: tmp + uses: act/common/utils/mktemp@master + with: + input: ${{ inputs.nuspec }} + tmpDir: . + additionalArgs: --suffix=.nuspec + - name: "Create Output Directory" + run: | + OUTPUT_DIR="${{ inputs.outputDirectory }}" + mkdir "$OUTPUT_DIR" -p + shell: bash + - name: "Build the .nupkg file." + uses: act/common/nuget/nuget@master + with: + command: pack "${{ steps.tmp.outputs.tmp }}" -OutputDirectory "${{ inputs.outputDirectory }}" -Version "${{ inputs.version }}" ${{ inputs.additionalArgs }} + - name: "Remove temporary files." + run: rm -rf "${{ steps.tmp.outputs.tmp }}" + shell: bash \ No newline at end of file diff --git a/nuget/nuget-upload-nupkg/action.yaml b/nuget/nuget-upload-nupkg/action.yaml new file mode 100644 index 0000000..1264e3e --- /dev/null +++ b/nuget/nuget-upload-nupkg/action.yaml @@ -0,0 +1,37 @@ +name: nuget-upload-nupkg +description: "Upload a nupkg to a NuGet repository." +inputs: + package: + description: "Name of the package to search for." + required: true + source: + description: "Name of the source to use." + required: true + default: lewdorg + url: + description: "Url of the NuGet repository." + required: true + default: ${{ github.server_url }}/_registry/nuget/${{ github.repository_owner }}/index.json + username: + description: "Username for the nuget repository to search." + required: true + default: ${{ github.actor }} + password: + description: "Password or ApiKey of the nuget repository to search." + required: true + default: ${{ github.token }} + options: + description: "Additional options when uploading." + required: false +runs: + using: "composite" + steps: + - name: "Run nuget push." + id: nuget + uses: act/common/nuget/nuget@master + with: + command: push ${{ inputs.package }} -Source ${{ inputs.source }} ${{ inputs.options }} + username: ${{ inputs.username }} + password: ${{ inputs.password }} + source: ${{ inputs.source }} + url: ${{ inputs.url }} diff --git a/nuget/nuget/Dockerfile b/nuget/nuget/Dockerfile new file mode 100644 index 0000000..05a2dc6 --- /dev/null +++ b/nuget/nuget/Dockerfile @@ -0,0 +1,20 @@ +FROM debian:stable-slim + +ENV VERSION=v6.5.0 + +RUN apt-get update +RUN apt-get install -y --no-install-recommends \ + bash \ + wget \ + mono-complete \ + tzdata + +RUN apt-get clean +RUN rm -rf /var/lib/apt/lists/* + +RUN wget https://dist.nuget.org/win-x86-commandline/$VERSION/nuget.exe -O /usr/bin/nuget.exe +RUN chmod +x /usr/bin/nuget.exe + +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/nuget/nuget/action.yaml b/nuget/nuget/action.yaml new file mode 100644 index 0000000..3001900 --- /dev/null +++ b/nuget/nuget/action.yaml @@ -0,0 +1,39 @@ +name: nuget +description: "Run a nuget command." +inputs: + command: + description: "Nuget command to run." + required: false + catchErrors: + description: "Whether or not errors should be handled." + required: false + source: + description: "Name of the source to use." + required: false + default: origin + url: + description: "Url of the NuGet repository." + required: false + default: ${{ github.server_url }}/_registry/nuget/${{ github.repository_owner }}/index.json + username: + description: "Username for the nuget repository to search." + required: false + default: ${{ github.actor }} + password: + description: "Password or ApiKey of the nuget repository to search." + required: false + default: ${{ github.token }} +outputs: + console: + description: "The console output of the command." +runs: + using: 'docker' + image: 'Dockerfile' + env: + NUGET_SOURCE_NAME: ${{ inputs.source }} + NUGET_SOURCE_URL: ${{ inputs.url }} + NUGET_SOURCE_USERNAME: ${{ inputs.username }} + NUGET_SOURCE_PASSWORD: ${{ inputs.password }} + CATCH_ERRORS: ${{ inputs.catchErrors }} + args: + - ${{ inputs.command }} \ No newline at end of file diff --git a/nuget/nuget/entrypoint.sh b/nuget/nuget/entrypoint.sh new file mode 100644 index 0000000..96610a2 --- /dev/null +++ b/nuget/nuget/entrypoint.sh @@ -0,0 +1,32 @@ +#!/bin/bash +#TODO: Reweite this action to make use of act/common/mono/mono +function nuget +{ + mono /usr/bin/nuget.exe $@ +} + +if [[ -n "$NUGET_SOURCE_NAME" && -n "$NUGET_SOURCE_URL" && -n "$NUGET_SOURCE_USERNAME" && -n "$NUGET_SOURCE_PASSWORD" ]]; then + nuget source remove -Name "$NUGET_SOURCE_NAME" + nuget source add -Name "$NUGET_SOURCE_NAME" -Source "$NUGET_SOURCE_URL" -Username "$NUGET_SOURCE_USERNAME" -Password "$NUGET_SOURCE_PASSWORD" + SET_SOURCE=true +fi + +OUTPUT=$(bash -c "mono /usr/bin/nuget.exe $@") +RESULT=$? +echo "$OUTPUT" + +#Output multiline strings. +#https://trstringer.com/github-actions-multiline-strings/ +if [[ -n "$OUTPUT" ]]; then + echo "console<> "$GITHUB_OUTPUT" + echo "$OUTPUT" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" +fi + +if [[ -n "$SET_SOURCE" ]]; then + nuget source remove -Name "$NUGET_SOURCE_NAME" +fi + +if [[ "$CATCH_ERRORS" != "true" ]]; then + exit $RESULT +fi diff --git a/renpy/renpy-distribute/action.yaml b/renpy/renpy-distribute/action.yaml new file mode 100644 index 0000000..c1063f9 --- /dev/null +++ b/renpy/renpy-distribute/action.yaml @@ -0,0 +1,73 @@ +name: renpy-distribute +description: "Build a RenPy project for various platforms." +inputs: + project: + description: "Path to the RenPy project." + required: true + package: + description: "The specific package to build. Values: win, mac, linux, android, pc, market" #TODO: android + required: true + dest: + description: "Destination folder for the builds." + required: false + packageDest: + description: "Destination folder for the indivdual package." + required: false + archive: + description: "Whether or not to compress the build into a zip file." + required: true + default: "true" + format: + description: "The archive format to use. Values: zip, tar.bz2 Default: zip" + required: true + default: "zip" + additionalArgs: + description: "Additional arguments to pass into RenPy." + required: false +outputs: + package: + description: "The path to the package or packages." + value: ${{ steps.command.outputs.output }} +runs: + using: "composite" + steps: + - name: "Build command." + id: command + run: | + # Replace each space with a backslash and a space + PROJECT="${{ inputs.project }}" + PROJECT="${PROJECT// /\\ }" + COMMAND="distribute $PROJECT --package ${{ inputs.package }} ${{ inputs.additionalArgs }}" + + ARCHIVE="${{ inputs.archive }}" + if [[ "$ARCHIVE" == "false" ]]; then + COMMAND="$COMMAND --no-archive" + EXT="" + else + EXT=".${{ inputs.format }}" + fi + + DEST="${{ inputs.dest }}" + if [[ -n "$DEST" ]]; then + OUTPUT="$DEST" + mkdir -p "$DEST" + COMMAND="$COMMAND --destination $DEST" + fi + FORMAT="${{ inputs.format }}" + if [[ -n "$FORMAT" ]]; then + COMMAND="$COMMAND --format $FORMAT" + fi + PACKAGE_DEST="${{ inputs.packageDest }}" + if [[ -n "$PACKAGE_DEST" ]]; then + OUTPUT="${PACKAGE_DEST}${EXT}" + mkdir -p "$PACKAGE_DEST" + COMMAND="$COMMAND --packagedest $PACKAGE_DEST" + fi + echo "command=$COMMAND" >> "$GITHUB_OUTPUT" + echo "output=$OUTPUT" >> "$GITHUB_OUTPUT" + shell: bash + - name: "Run RenPy distribute command." + uses: act/common/renpy/renpy@master + with: + command: ${{ steps.command.outputs.command }} + catchErrors: true diff --git a/renpy/renpy/Dockerfile b/renpy/renpy/Dockerfile new file mode 100644 index 0000000..41386a2 --- /dev/null +++ b/renpy/renpy/Dockerfile @@ -0,0 +1,8 @@ +# Container image that runs your code +FROM maienm/renpy:8.1.0 +ENV RENPY_HOME="/opt/renpy/" + +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/renpy/renpy/action.yaml b/renpy/renpy/action.yaml new file mode 100644 index 0000000..ce8d215 --- /dev/null +++ b/renpy/renpy/action.yaml @@ -0,0 +1,21 @@ +name: renpy +description: "Run RenPy commands." +inputs: + command: + description: "Arguments to pass into RenPy." + required: true + catchErrors: + description: "Whether or not errors should be handled." + required: false +outputs: + console: + description: "The console output of the RenPy command." + exitCode: + description: "How the program exited." +runs: + using: docker + image: Dockerfile + env: + CATCH_ERRORS: ${{ inputs.catchErrors }} + args: + - ${{ inputs.command }} diff --git a/renpy/renpy/entrypoint.sh b/renpy/renpy/entrypoint.sh new file mode 100644 index 0000000..ed5ce51 --- /dev/null +++ b/renpy/renpy/entrypoint.sh @@ -0,0 +1,27 @@ +#!/bin/bash +ARGS="$@" + +set -o pipefail +exec 5>&1 +OUTPUT=$(bash -c "$RENPY_HOME/renpy.sh $RENPY_HOME/launcher $ARGS" | tee /dev/fd/5) +RESULT=$? + +#Output multiline strings. +#https://trstringer.com/github-actions-multiline-strings/ +# if [[ -n "$OUTPUT" ]]; then +# echo "console<> "$GITHUB_OUTPUT" +# echo "$OUTPUT" >> "$GITHUB_OUTPUT" +# echo "EOF" >> "$GITHUB_OUTPUT" +# fi +if [[ -n "$OUTPUT" ]]; then + OUTPUT="${OUTPUT//'%'/'%25'}" + OUTPUT="${OUTPUT//$'\n'/'%0A'}" + OUTPUT="${OUTPUT//$'\r'/'%0D'}" + echo "::set-output name=console::$OUTPUT" +fi + +echo "exitCode=$RESULT" >> "$GITHUB_OUTPUT" + +if [[ "$CATCH_ERRORS" != "true" ]]; then + exit $RESULT +fi diff --git a/rpm/rpm-verifysign/action.yaml b/rpm/rpm-verifysign/action.yaml new file mode 100644 index 0000000..6795ea8 --- /dev/null +++ b/rpm/rpm-verifysign/action.yaml @@ -0,0 +1,20 @@ +name: rpm-verifysign +description: "Verify the signature a given .rpm file with a given .gpg key." +inputs: + file: + description: "File to verify." + required: true + gpgKey: + description: "GPG public key to check with. Can be a file or raw key." + required: true +runs: + using: "composite" + steps: + - run: cp -f ${{ github.action_path }}/verify_file.sh _verify_file.sh + shell: bash + - name: "Verify file." + uses: act/common/distros/rockylinux@master + with: + args: bash "_verify_file.sh" "${{ inputs.file }}" "${{ inputs.gpgKey }}" + - run: rm _verify_file.sh + shell: bash diff --git a/rpm/rpm-verifysign/verify_file.sh b/rpm/rpm-verifysign/verify_file.sh new file mode 100644 index 0000000..2d106d4 --- /dev/null +++ b/rpm/rpm-verifysign/verify_file.sh @@ -0,0 +1,22 @@ +#!/bin/bash +#Importing gpg key via cli +#https://d.sb/2016/11/gpg-inappropriate-ioctl-for-device-errors +FILE="$1" +GPG_KEY="$2" +TMP_KEY_PATH="/tmp_key.gpg" + +if [[ ! -f "$GPG_KEY" ]]; then + cat < "$TMP_KEY_PATH" +$GPG_KEY +EOF + GPG_KEY="$TMP_KEY_PATH" +fi + +#Only seems to import files, not STDIN. +#gpg --import does not work with 'rpm -K' +rpm --import "$GPG_KEY" +rm -f "$TMP_KEY_PATH" + +rpm -K $FILE + +exit $? \ No newline at end of file diff --git a/rpm/rpmsign-file/action.yaml b/rpm/rpmsign-file/action.yaml new file mode 100644 index 0000000..1d45291 --- /dev/null +++ b/rpm/rpmsign-file/action.yaml @@ -0,0 +1,34 @@ +name: rpmsign-file +description: "Sign a given .rpm file with a given .gpg key." +inputs: + file: + description: "File to sign." + required: true + gpgKey: + description: "GPG key to sign with." + required: true + gpgPass: + description: "Password to the GPG key." + required: true +outputs: + publicKey: + description: "Public GPG key of the signed file." + value: ${{ steps.sign.outputs.publicKey }} +runs: + using: "composite" + steps: + - run: cp -f ${{ github.action_path }}/sign_file.sh _sign_file.sh + shell: bash + - name: "Sign file." + id: sign + uses: act/common/distros/rockylinux@master + with: + #Having single quotes around "${{ inputs.gpgKey }}" makes it work in act. + args: bash "_sign_file.sh" "${{ inputs.file }}" "${{ inputs.gpgKey }}" "${{ inputs.gpgPass }}" + - run: rm _sign_file.sh + shell: bash + - name: "Own artifacts." + uses: act/common/utils/chown@master + with: + file: ${{ inputs.file }} + \ No newline at end of file diff --git a/rpm/rpmsign-file/sign_file.sh b/rpm/rpmsign-file/sign_file.sh new file mode 100644 index 0000000..e06950a --- /dev/null +++ b/rpm/rpmsign-file/sign_file.sh @@ -0,0 +1,41 @@ +#!/bin/bash +#Importing gpg key via cli +#https://d.sb/2016/11/gpg-inappropriate-ioctl-for-device-errors +FILE="$1" +GPG_KEY="$2" +GPG_PASS="$3" + +GPG_DIR="/root/.gnupg" +mkdir -p "$GPG_DIR" + +if [[ -f "$GPG_KEY" ]]; then + GPG_KEY=$(cat "$GPG_KEY") +fi + +#Trim single quotes if it has any. (Single quotes are needed for ACT) +GPG_KEY=$(echo "$GPG_KEY" | tr -d \') + +gpg --homedir "$GPG_DIR" --allow-secret-key-import --import --batch --passphrase "$GPG_PASS" <> "$GITHUB_OUTPUT" + +exit $RESULT diff --git a/tpl/tpl-env/action.yaml b/tpl/tpl-env/action.yaml new file mode 100644 index 0000000..8ddf766 --- /dev/null +++ b/tpl/tpl-env/action.yaml @@ -0,0 +1,32 @@ +name: tpl-env +description: "Format a Go template file given yaml input. The input has yaml file environment variables replaced first." +inputs: + template: + description: "Template or local path of the template file." + required: true + decoder: + description: "Decoder format. Supported values: json, yaml, toml" + required: true + default: yaml + input: + description: "Input or local path of the input data file." + required: true +outputs: + result: + description: "Local path of the output file." + value: ${{ steps.template.outputs.result }} +runs: + using: "composite" + steps: + - name: "Substitute Environment Variables" + id: envsubst + uses: act/common/utils/envsubst@master + with: + input: ${{ inputs.input }} + - name: "Build Template" + id: template + uses: act/common/tpl/tpl-file@master + with: + template: ${{ inputs.template }} + decoder: ${{ inputs.decoder }} + input: ${{ steps.envsubst.outputs.result }} diff --git a/tpl/tpl-file/action.yaml b/tpl/tpl-file/action.yaml new file mode 100644 index 0000000..cdf7f00 --- /dev/null +++ b/tpl/tpl-file/action.yaml @@ -0,0 +1,45 @@ +name: tpl-file +description: "Format a Go template file given a yaml input file." +inputs: + template: + description: "Template or local path of the template file." + required: true + decoder: + description: "Decoder format. Supported values: json, yaml, toml" + required: true + default: yaml + input: + description: "Input or local path of the input data file." + required: true + tmpDir: + description: "Temporary directory. Default: _tmp" + required: true + default: _tmp +outputs: + result: + description: "Local path of the output file." + value: ${{ steps.template.outputs.console }} +runs: + using: "composite" + steps: + - name: "Make temporary file of template." + id: mktmp-template + uses: act/common/utils/mktemp@master + with: + input: ${{ inputs.template }} + tmpDir: ${{ inputs.tmpDir }} + - name: "Make temporary file of input." + id: mktmp-input + uses: act/common/utils/mktemp@master + with: + input: ${{ inputs.input }} + tmpDir: ${{ inputs.tmpDir }} + - name: "Generate template." + id: template + uses: act/common/tpl/tpl@master + with: + command: --file "${{ steps.mktmp-template.outputs.tmp }}" --decoder ${{ inputs.decoder }} < "${{ steps.mktmp-input.outputs.tmp }}" + - name: "Remove temporary files." + run: rm -rf "${{ inputs.tmpDir }}" + shell: bash + \ No newline at end of file diff --git a/tpl/tpl-to-dir/action.yaml b/tpl/tpl-to-dir/action.yaml new file mode 100644 index 0000000..8d68936 --- /dev/null +++ b/tpl/tpl-to-dir/action.yaml @@ -0,0 +1,38 @@ +name: tpl-to-dir +description: "Format a Go template file given a yaml input file to a file of the same name in the specified output directory. The input yaml file environment variables replaced first." +inputs: + templateFile: + description: "Local path to the template file." + required: true + inputFilename: + description: "Name of the input file without directories or extensions." + required: true + inputExtension: + description: "Extension for the input file." + required: false + default: .yaml + outputExtension: + description: "Extension for the output file." + required: false + inputDirectory: + description: "Directory for the input files." + required: false + outputDirectory: + description: "Directory for the output files." + required: false +outputs: + outputFile: + description: "The generated output file." + value: ${{ inputs.outputDirectory }}/${{ inputs.inputFilename }}${{ inputs.outputExtension }} +runs: + using: "composite" + steps: + - name: "Create Output Directory" + run: mkdir ${{ inputs.outputDirectory }} -p + shell: bash + - name: "Generate Template" + uses: act/common/tpl/tpl-env@master + with: + templateFile: ${{ inputs.inputDirectory }}/${{ inputs.templateFile }} + inputFile: ${{ inputs.inputDirectory }}/${{ inputs.inputFilename }}${{ inputs.inputExtension }} + outputFile: ${{ inputs.outputDirectory }}/${{ inputs.inputFilename }}${{ inputs.outputExtension }} \ No newline at end of file diff --git a/tpl/tpl-to-nupkg/action.yaml b/tpl/tpl-to-nupkg/action.yaml new file mode 100644 index 0000000..097ee82 --- /dev/null +++ b/tpl/tpl-to-nupkg/action.yaml @@ -0,0 +1,50 @@ +name: tpl-to-nupkg +description: "Pack a .nupkg given a .nuspec Go template file and a yaml input file. The input yaml file environment variables replaced first." +inputs: + template: + description: "Template or local path of the template file to use. Defaults to the template file in the action's directory." + required: false + input: + description: "Input or local path of the yaml input data file." + required: true + version: + description: "Version of the .nupkg file." + required: true + outputDirectory: + description: "Directory for the output file." + required: true + default: '.' + nuspecExtension: + description: "Extension for the output file." + required: false + default: .nuspec + tmpDir: + description: "Temporary directory. Default: _tmp" + required: true + default: _tmp +outputs: + nuspec: + description: "The generated output .nuspec file." + value: ${{ steps.template.outputs.result }} + nupkg: + description: "The generated output .nupkg file." + value: ${{ inputs.outputDirectory }}/${{ steps.nuspec.outputs.packageName }}.${{ inputs.version }}.nupkg + nupkgName: + description: "The generated output .nupkg file's name." + value: ${{ steps.nuspec.outputs.packageName }}.${{ inputs.version }}.nupkg +runs: + using: "composite" + steps: + - name: "Generate Nuspec From Template" + id: nuspec + uses: act/common/tpl/tpl-to-nuspec@master + with: + template: ${{ inputs.template }} + input: ${{ inputs.input }} + - name: "Build the .nupkg file." + uses: act/common/nuget/nuget-pack@master + with: + nuspec: ${{ steps.nuspec.outputs.nuspec }} + version: ${{ inputs.version }} + outputDirectory: ${{ inputs.outputDirectory }} + \ No newline at end of file diff --git a/tpl/tpl-to-nuspec/action.yaml b/tpl/tpl-to-nuspec/action.yaml new file mode 100644 index 0000000..4dc9f5d --- /dev/null +++ b/tpl/tpl-to-nuspec/action.yaml @@ -0,0 +1,67 @@ +name: tpl-to-nuspec +description: "Pack a .nupkg given a .nuspec Go template file and a yaml input file. The input yaml file environment variables replaced first." +inputs: + template: + description: "Template or local path of the template file to use. Defaults to the template file in the action's directory." + required: false + input: + description: "Input or local path of the yaml input data file." + required: true +outputs: + nuspec: + description: "The generated output .nuspec file." + value: ${{ steps.xml.outputs.result }} + packageName: + description: "The 'name' property of the generated .nuspec file." + value: ${{ steps.name.outputs.result }} +runs: + using: "composite" + steps: + - name: "Set template variable." + id: get-template + run: | + TEMPLATE=$(cat << EOF + ${{ inputs.template }} + EOF + ) + if [[ -z "$TEMPLATE" ]]; then + TEMPLATE="${{ github.action_path }}/nuspec.yaml.tpl" + fi + + echo "template<> "$GITHUB_OUTPUT" + echo "$TEMPLATE" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + shell: bash + - name: "Merge Input" + id: merge + uses: act/common/yq/yq-merge@master + with: + lhs: ${{ github.action_path }}/defaults.yaml + rhs: ${{ inputs.input }} + - name: "Generate Nuspec Yaml from Template" + id: template + uses: act/common/tpl/tpl-env@master + with: + template: ${{ steps.get-template.outputs.template }} + decoder: yaml + input: ${{ steps.merge.outputs.result }} + - name: "Convert the Nuspec Yaml to XML" + id: trim + uses: act/common/yq/yq-trim@master + with: + input: ${{ steps.template.outputs.result }} + recursive: true + - name: "Convert the Nuspec Yaml to XML" + id: xml + uses: act/common/yq/yq-convert@master + with: + input: ${{ steps.trim.outputs.result }} + from: yaml + to: xml + - name: "Get id from input." + id: name + uses: act/common/yq/yq-expression@master + with: + input: ${{ steps.merge.outputs.result }} + expression: .id + \ No newline at end of file diff --git a/tpl/tpl-to-nuspec/defaults.yaml b/tpl/tpl-to-nuspec/defaults.yaml new file mode 100644 index 0000000..fb5f2dd --- /dev/null +++ b/tpl/tpl-to-nuspec/defaults.yaml @@ -0,0 +1,16 @@ +authors: +- lewdorg Inc +name: ${GITHUB_REPOSITORY} +version: 0.0.0-dev +projectUrl: https://lewdorg.com +iconUrl: https://lewdorg.com/wp-content/uploads/2022/03/cropped-lewdorg-Profile-Circle-Light-1-1-270x270.png +copyright: '© Copyright {{ now | date "2006" }} lewdorg Inc, Patents Issued.' +repository: + type: git + url: git@github.lewdorg.com:${GITHUB_REPOSITORY}.git + branch: ${GITHUB_REF_NAME} + commit: ${GITHUB_SHA} +tags: +- lewdorg +requireLicenseAcceptance: false +language: en-US \ No newline at end of file diff --git a/tpl/tpl-to-nuspec/example.yaml b/tpl/tpl-to-nuspec/example.yaml new file mode 100644 index 0000000..c9324f5 --- /dev/null +++ b/tpl/tpl-to-nuspec/example.yaml @@ -0,0 +1,67 @@ +# This file provides an example for the desired Yaml format for a .nuspec file. +# Required Metadata +id: Example.Package +version: 1.0.0 +description: This is an example package. +authors: +- John Doe + +# Optional Metadata +title: Example Package +license: + content: MIT + type: expression +projectUrl: https://example.com +iconUrl: icon.png +icon: + src: icon.png + target: icon.png +requireLicenseAcceptance: false +developmentDependency: true +summary: This is a summary of the example package. +releaseNotes: This is the first release of the example package. +language: en-US +tags: +- example +- tag1 +- tag2 +repository: + type: git + url: https://github.com/example/example.package + branch: master + commit: 0a1b2c3d + +path: /root +# Content +content: + path: /content + files: + - include: any/any/config.json + buildAction: Content + copyToOutput: "true" + flatten: "true" + +# Source Files +source: + path: /source + groups: + - framework: .NETStandard2.0 + references: + - name: System.Data + dependencies: + - id: Example.Dependency + version: 1.0.0 + exclude: + - Build + - Analyzers + files: + - name: Example.Package.dll + - name: Example.Package.pdb + dlls: + - name: Unity.Package + - files: + - name: icon.png + target: content + - framework: net40 + assemblies: + - name: System.IO \ No newline at end of file diff --git a/tpl/tpl-to-nuspec/nuspec.yaml.tpl b/tpl/tpl-to-nuspec/nuspec.yaml.tpl new file mode 100644 index 0000000..47da12b --- /dev/null +++ b/tpl/tpl-to-nuspec/nuspec.yaml.tpl @@ -0,0 +1,133 @@ ++p_xml: version="1.0" encoding="utf-8" +package: + +@xmlns: http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd + metadata: + id: {{ .id | default "" }} + version: {{ .version | default "" }} + description: {{ .description | default "" }} + authors: "{{ join ", " .authors | default "" }}" + + title: {{ .title | default "" }} + projectUrl: {{ .projectUrl | default "" }} + licenseUrl: {{ .licenseUrl | default "" }} + {{- with .license }} + license: + {{- if .content }} + +content: {{ .content }} + {{- end }} + {{- if .type }} + +@type: {{ .type }} + {{- end }} + {{- end }} + icon: {{ .icon | default "" }} + iconUrl: {{ .iconUrl | default "" }} + requireLicenseAcceptance: {{ .requireLicenseAcceptance | default "" }} + developmentDependency: {{ .developmentDependency | default "" }} + {{- if .copyright }} + copyright: {{ tpl (toYaml .copyright) $ }} + {{- end }} + summary: {{ .summary | default "" }} + releaseNotes: {{ .releaseNotes | default "" }} + language: {{ .language | default "" }} + tags: "{{ join ", " .tags | default "" }}" + {{- with .repository }} + repository: + {{- if .type }} + +@type: {{ .type }} + {{- end }} + {{- if .url }} + +@url: {{ .url }} + {{- end }} + {{- if .branch }} + +@branch: {{ .branch }} + {{- end }} + {{- if .commit }} + +@commit: {{ .commit }} + {{- end }} + {{- end }} + + {{- with $.source }} + {{- $path := print (default "." $.path) "/" (default "." .path) | clean }} + dependencies: + group: + {{- range $item := .groups }} + {{- if and $item.framework }} + - +@targetFramework: {{ $item.framework }} + dependency: + {{- range $dep := $item.dependencies }} + - +@id: {{ $dep.id }} + +@version: {{ $dep.version }} + +@exclude: "{{ join ", " $dep.exclude }}" + {{- end }} + {{- end }} + {{- end }} + references: + group: + {{- range $item := .groups }} + {{- if and $item.framework $item.references }} + - +@targetFramework: {{ $item.framework }} + {{- range $ref := $item.references }} + - reference: + +@file: {{ print $path "/" $ref.name | clean }} + {{- end }} + {{- end }} + {{- end }} + frameworkAssemblies: + frameworkAssembly: + {{- range $item := .groups }} + {{- range $ref := $item.assemblies }} + - +@assemblyName: {{ $ref.name }} + {{- if $item.framework }} + +@targetFramework: {{ $item.framework }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- with $.content }} + {{- $path := print (default "." $.path) "/" (default "." .path) | clean }} + contentFiles: + files: + {{- range $file := .files }} + - +@include: {{ print $path "/" $file.include | clean }} + {{- if $file.exclude }} + +@exclude: {{ print $path "/" $file.exclude | clean }} + {{- end }} + {{- if $file.buildAction }} + +@buildAction: {{ $file.buildAction }} + {{- end }} + {{- if $file.copyToOutput }} + +@copyToOutput: {{ $file.copyToOutput }} + {{- end }} + {{- if $file.flatten }} + +@flatten: {{ $file.flatten }} + {{- end }} + {{- end }} + {{- end }} + {{- with $.source }} + {{- $path := print (default "." $.path) "/" (default "." .path) | clean }} + files: + file: + {{- range $item := .groups }} + {{- range $file := $item.files }} + - +@src: {{ print $path "/" $file.name | clean }} + {{- if $item.framework }} + +@target: {{ print "lib/" $item.framework "/" (default $file.target ".") | clean }} + {{- else if $file.target }} + +@target: {{ $file.target }} + {{- end }} + {{- if $file.exclude }} + +@exclude: {{ print $path "/" $file.exclude | clean }} + {{- end }} + {{- end }} + {{- if $item.framework }} + {{- range $dll := $item.dlls }} + - +@src: {{ print $path "/" $dll.name ".dll" | clean }} + +@target: {{ print "lib/" $item.framework "/" (default $item.target ".") | clean }} + {{- if ($dll.hasPdb | default true) }} + - +@src: {{ print $path "/" $dll.name ".pdb" | clean }} + +@target: {{ print "lib/" $item.framework "/" (default $item.target ".") | clean }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} diff --git a/tpl/tpl/Dockerfile b/tpl/tpl/Dockerfile new file mode 100644 index 0000000..6e3bfe9 --- /dev/null +++ b/tpl/tpl/Dockerfile @@ -0,0 +1,12 @@ +FROM debian:stable-slim + +ENV VERSION=v0.2.0 + +RUN apt-get update +RUN apt-get install wget -y +RUN wget https://github.com/bluebrown/go-template-cli/releases/download/$VERSION/tpl-linux-amd64 -O /usr/bin/tpl +RUN chmod +x /usr/bin/tpl + +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] diff --git a/tpl/tpl/action.yaml b/tpl/tpl/action.yaml new file mode 100644 index 0000000..574ff2b --- /dev/null +++ b/tpl/tpl/action.yaml @@ -0,0 +1,21 @@ +name: tpl +description: "Format a Go template file given yaml file." +inputs: + command: + description: "Arguments to pass into tpl." + required: false + catchErrors: + description: "Whether or not errors should be handled." + required: false +outputs: + console: + description: "The console output of the tpl command." + exitCode: + description: "How the program exited." +runs: + using: 'docker' + image: 'Dockerfile' + env: + CATCH_ERRORS: ${{ inputs.catchErrors }} + args: + - ${{ inputs.command }} \ No newline at end of file diff --git a/tpl/tpl/entrypoint.sh b/tpl/tpl/entrypoint.sh new file mode 100644 index 0000000..24963c4 --- /dev/null +++ b/tpl/tpl/entrypoint.sh @@ -0,0 +1,20 @@ +#!/bin/bash +#See https://github.com/bluebrown/go-template-cli +ARGS="$@" + +OUTPUT=$(sh -c "tpl $ARGS") +RESULT=$? + +#Output multiline strings. +#https://trstringer.com/github-actions-multiline-strings/ +if [[ -n "$OUTPUT" ]]; then + echo "console<> "$GITHUB_OUTPUT" + echo "$OUTPUT" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" +fi + +echo "exitCode=$RESULT" >> "$GITHUB_OUTPUT" + +if [[ "$CATCH_ERRORS" != "true" ]]; then + exit $RESULT +fi diff --git a/unity/unity-command/Dockerfile b/unity/unity-command/Dockerfile new file mode 100644 index 0000000..147fe16 --- /dev/null +++ b/unity/unity-command/Dockerfile @@ -0,0 +1,22 @@ +#Arg is replaced with the desired Unity container. +ARG IMAGE=unityci/base:latest +FROM ${IMAGE} + +RUN apt update +RUN apt install -y wget chromium-browser + +#ADD https://minio.studiowhy.net/hackmd/UnityBuilder /usr/local/bin/ +COPY UnityBuilder /usr/local/bin/ +RUN chmod +x /usr/local/bin/UnityBuilder + +COPY entrypoint.sh / +RUN chmod +x /entrypoint.sh + +COPY scripts/. /scripts +# Commented out until better image selection is enabled. +# RUN --mount=type=secret,id=SERIAL \ +# --mount=type=secret,id=USERNAME \ +# --mount=type=secret,id=PASSWORD \ +# bash /scripts/activate_license.sh + +ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/unity/unity-command/UnityBuilder b/unity/unity-command/UnityBuilder new file mode 100644 index 0000000..93a049b Binary files /dev/null and b/unity/unity-command/UnityBuilder differ diff --git a/unity/unity-command/action.yaml b/unity/unity-command/action.yaml new file mode 100644 index 0000000..4bd47b9 --- /dev/null +++ b/unity/unity-command/action.yaml @@ -0,0 +1,84 @@ +name: unity-command +description: "Run a Unity command using a specified version of Unity." +inputs: + platform: + description: "Unity Platform. Options: windows, windows32bit, mac, linux, android" + required: true + version: + description: "Unity Version." + required: true + imageTag: + description: "Tag to use for the temporary version of Unity. Must refer to an existing public Docker image. Must be the same is in the Dockerfile of the called action." + required: true + default: unityci/base:latest + serial: + description: "Unity license serial number. Or 'public' for a public license." + required: true + default: public + email: + description: "Unity email." + required: true + password: + description: "Unity password." + required: true + command: + description: "Unity command to run." + required: false + noGraphics: + description: "Whether or not to use the graphics device when running Unity." + required: false + default: "true" + unityBuilder: + description: "Whether or not to use the UnityBuilder instead of a Unity command." + required: false + removeContainer: + description: "Remove the mock container after building." + required: false + default: "true" +runs: + using: "composite" + steps: + - name: "Get Unity container name." + id: getContainer + uses: act/unity/unity-get-container@master + with: + version: ${{ inputs.version }} + platform: ${{ inputs.platform }} + - name: "Pull Unity container." + run: | + CONTAINER="${{ steps.getContainer.outputs.container }}" + + CACHED_CONTAINER="$CONTAINER-activated" + # Activate the license on build. + # DOCKER_BUILDKIT=1 \ + # SERIAL="${{ inputs.serial }}" USERNAME="${{ inputs.email }}" PASSWORD="${{ inputs.password }}" \ + # docker build --secret id=SERIAL,env=SERIAL --secret id=USERNAME,env=USERNAME --secret id=PASSWORD,env=PASSWORD \ + # -t $CACHED_CONTAINER --build-arg IMAGE=$CONTAINER ${{ github.action_path }} + docker build -t $CACHED_CONTAINER --build-arg IMAGE=$CONTAINER ${{ github.action_path }} + + docker tag $CACHED_CONTAINER ${{ inputs.imageTag }} + shell: bash + - name: "Get Unity Command." + id: command + run: | + COMMAND="${{ inputs.command }}" + NO_GRAPHICS="${{ inputs.noGraphics }}" + + if [[ "$NO_GRAPHICS" == "true" ]]; then + COMMAND="-nographics $COMMAND" + fi + echo "command=$COMMAND" >> "$GITHUB_OUTPUT" + - name: "Run Unity command." + uses: act/unity/unity@master + with: + serial: ${{ inputs.serial }} + # serial: "activated" + email: ${{ inputs.email }} + password: ${{ inputs.password }} + command: ${{ steps.command.outputs.command }} + unityBuilder: ${{ inputs.unityBuilder }} + - name: "Remove temporary image." + if: ${{ inputs.removeContainer == 'true' }} + run: | + docker image rm ${{ inputs.imageTag }} + shell: bash diff --git a/unity/unity-command/entrypoint.sh b/unity/unity-command/entrypoint.sh new file mode 100644 index 0000000..f44a250 --- /dev/null +++ b/unity/unity-command/entrypoint.sh @@ -0,0 +1,24 @@ +#!/bin/bash +SERIAL=$1; EMAIL=$2; PASSWORD=$3; COMMAND=$4; UNITY_BUILDER=$5 +DEFAULT_ARGS="-quit -logFile -" + +rm -rf $HOME/.config/unity3d +rm -rf /home/unity/.config/unity3d + +#Add ssh key information for resolving packages. +bash /scripts/add_ssh_keys.sh + +if [[ "$SERIAL" != "activated" ]]; then + echo "::group::Activating Unity License" + bash /scripts/activate_license.sh "$SERIAL" "$EMAIL" "$PASSWORD" + echo "::endgroup::" +fi + +echo "::group::Running Unity Command" +#Run the command. +if [[ -n "$UNITY_BUILDER" ]]; then + UnityBuilder $COMMAND +else + unity-editor $DEFAULT_ARGS $COMMAND +fi +echo "::endgroup::" \ No newline at end of file diff --git a/unity/unity-command/scripts/activate_license.sh b/unity/unity-command/scripts/activate_license.sh new file mode 100644 index 0000000..81100fe --- /dev/null +++ b/unity/unity-command/scripts/activate_license.sh @@ -0,0 +1,29 @@ +#!/bin/bash +SERIAL=$1; USERNAME=$2; PASSWORD=$3; + +function check_path +{ + local SECRET_PATH="/run/secrets" + local ENV_NAME="$1" + local ENV_VALUE="${!ENV_NAME}" + + local FILE_PATH="$SECRET_PATH/$ENV_NAME" + if [[ -z "$ENV_VALUE" && -f "$FILE_PATH" ]]; then + export $ENV_NAME=$(cat "$FILE_PATH") + fi +} + +check_path SERIAL +check_path USERNAME +check_path PASSWORD + +if [[ -z "$SERIAL" || -z "$USERNAME" || -z "$PASSWORD" ]]; then + exit 0 +fi + +#Activate Unity +if [[ "$SERIAL" == "personal" ]]; then + UnityBuilder activate -i /usr/bin/unity-editor -u $USERNAME -p $PASSWORD +else + unity-editor $DEFAULT_ARGS -serial $SERIAL -username $USERNAME -password $PASSWORD +fi \ No newline at end of file diff --git a/unity/unity-command/scripts/add_ssh_keys.sh b/unity/unity-command/scripts/add_ssh_keys.sh new file mode 100644 index 0000000..25da0fa --- /dev/null +++ b/unity/unity-command/scripts/add_ssh_keys.sh @@ -0,0 +1,17 @@ +#!/bin/bash +if [[ -n "$SSH_PUBLIC_KEY" && -n "$SSH_PRIVATE_KEY" ]]; then + echo "ADDING SSH KEYS!" + SSH_DIR="/home/$(whoami)/.ssh" + mkdir -p $SSH_DIR + + echo "$SSH_PUBLIC_KEY" > $SSH_DIR/id_rsa.pub + echo "$SSH_PRIVATE_KEY" > $SSH_DIR/id_rsa +cat << EOF > $SSH_DIR/config +Host * + StrictHostKeyChecking no +EOF + + chmod 600 $SSH_DIR/id_rsa + chmod 644 $SSH_DIR/id_rsa.pub + cat $SSH_DIR/config +fi \ No newline at end of file diff --git a/unity/unity-composite/action.yaml b/unity/unity-composite/action.yaml new file mode 100644 index 0000000..dc74fd3 --- /dev/null +++ b/unity/unity-composite/action.yaml @@ -0,0 +1,77 @@ +name: unity-composite +description: "Run a Unity command using a project's version and a build target. Then compress the result to a zip file." +inputs: + platform: + description: "Unity Platform. Options: windows, windows32bit, mac, linux, android" + required: true + email: + description: "Unity email." + required: true + password: + description: "Unity password." + required: true + command: + description: "Unity command to run." + required: false + unityBuilder: + description: "Whether or not to use the UnityBuilder instead of a Unity command." + required: false + buildDir: + description: "Where the built application ends up." + required: false + default: build + cacheVolume: + description: "Name of the volume to cache the Library folder to." + required: false + artifactsVolume: + description: "Name of the volume to copy the artifacts to." + required: true + artifactsDir: + description: "Name of the directory to copy the artifacts from." + required: true + default: artifacts + noGraphics: + description: "Whether or not to use the graphics device when running Unity." + required: false + default: "true" + zipName: + description: "Name of the resulting zip file." + required: false + artifactMode: + description: "The mode with which to publish artifacts. Options: copy, own, or null Default: copy" + required: false + default: "" +runs: + using: "composite" + steps: + - name: "Checkout" + uses: actions/checkout@v2 + - uses: act/unity/unity-project@master + with: + platform: ${{ inputs.platform }} + email: ${{ inputs.email }} + password: ${{ inputs.password }} + command: ${{ inputs.command }} + unityBuilder: ${{ inputs.unityBuilder }} + cacheVolume: ${{ inputs.cacheVolume }} + noGraphics: ${{ inputs.noGraphics }} + - name: "Compress build" + if: ${{ inputs.zipName }} + env: + WORKDIR: ${{ inputs.buildDir }} + uses: act/common/utils/compress@master + with: + name: ../${{ inputs.artifactsDir }}/${{ inputs.zipName }} + files: . + - name: "Own artifacts" + if: inputs.artifactMode == 'own' + uses: act/common/utils/chown@master + with: + file: ${{ inputs.artifactsDir }} + - name: "Copy artifacts" + if: inputs.artifactMode == 'copy' + uses: act/common/docker/docker-cp@master + with: + recreateVolume: true + volume: ${{inputs.artifactsVolume }} + fromPath: ${{ inputs.artifactsDir }}/. diff --git a/unity/unity-default/action.yaml b/unity/unity-default/action.yaml new file mode 100644 index 0000000..b55242c --- /dev/null +++ b/unity/unity-default/action.yaml @@ -0,0 +1,58 @@ +name: unity-default +description: "Run a Unity command using defaults loaded from environment variables." +inputs: + platform: + description: "Unity Platform. Options: windows, windows32bit, mac, linux, android" + required: true + default: ${{ env.UNITY_PLATFORM }} + email: + description: "Unity email." + required: true + default: ${{ env.UNITY_USERNAME }} + password: + description: "Unity password." + required: true + default: ${{ env.UNITY_PASSWORD }} + command: + description: "Unity command to run." + required: false + unityBuilder: + description: "Whether or not to use the UnityBuilder instead of a Unity command." + required: false + buildDir: + description: "Where the built application ends up." + required: false + default: ${{ env.BUILD_DIR || 'build' }} + cacheVolume: + description: "Name of the volume to cache the Library folder to." + required: false + artifactsVolume: + description: "Name of the volume to copy the artifacts to." + required: true + default: ${{ env.ARTIFACTS_VOLUME }} + noGraphics: + description: "Whether or not to use the graphics device when running Unity." + required: false + default: ${{ env.NO_GRAPHICS || 'true' }} + artifactsDir: + description: "Name of the directory to copy the artifacts from." + required: true + default: artifacts + zipName: + description: "Name of the resulting zip file." + required: false +runs: + using: "composite" + steps: + - uses: act/unity/unity-composite@master + with: + platform: ${{ inputs.platform }} + email: ${{ inputs.email }} + password: ${{ inputs.password }} + command: ${{ inputs.command }} + unityBuilder: ${{ inputs.unityBuilder }} + buildDir: ${{ inputs.buildDir }} + artifactsDir: ${{ inputs.artifactsDir }} + cacheVolume: ${{ inputs.cacheVolume }} + zipName: ${{ inputs.zipName }} + noGraphics: ${{ inputs.noGraphics }} diff --git a/unity/unity-get-buildtarget/action.yaml b/unity/unity-get-buildtarget/action.yaml new file mode 100644 index 0000000..26590da --- /dev/null +++ b/unity/unity-get-buildtarget/action.yaml @@ -0,0 +1,23 @@ +name: unity-get-buildtarget +description: "Get the correct Unity build target from a provided platform." +inputs: + platform: + description: "Unity Platform. Options: windows, windows32bit, mac, linux, android" + required: true +outputs: + buildTarget: + description: "Unity Build Target." + value: ${{ steps.getTarget.outputs.buildTarget }} + buildArg: + description: "Unity Build Argument." + value: ${{ steps.getTarget.outputs.buildArg }} +runs: + using: "composite" + steps: + - name: "Get Unity Build Target." + id: getTarget + run: | + #Choose the correct buildTarget: https://docs.unity3d.com/Manual/EditorCommandLineArguments.html + + bash ${{ github.action_path }}/get_target.sh "${{ inputs.platform }}" + shell: bash \ No newline at end of file diff --git a/unity/unity-get-buildtarget/get_target.sh b/unity/unity-get-buildtarget/get_target.sh new file mode 100644 index 0000000..1c75955 --- /dev/null +++ b/unity/unity-get-buildtarget/get_target.sh @@ -0,0 +1,38 @@ +#!/bin/bash +UNITY_TARGET="$1" + +TARGET=$(echo "$UNITY_TARGET" | awk '{print tolower($0)}') +BUILD_ARG="" +case $TARGET in + "windows") + UNITY_TARGET=Win64 + BUILD_ARG=-buildWindows64Player + ;; + "windows32bit") + UNITY_TARGET=Win + BUILD_ARG=-buildWindowsPlayer + ;; + "mac") + UNITY_TARGET=OSXUniversal + BUILD_ARG=-buildOSXUniversalPlayer + ;; + "ios") + UNITY_TARGET=iOS + ;; + "linux") + UNITY_TARGET=Linux64 + BUILD_ARG=-buildLinux64Player + ;; + "android") + UNITY_TARGET=Android + ;; + "webgl") + UNITY_TARGET=WebGL + ;; + *) + echo "Invalid target. Valid options are: Windows, Windows32bit, Mac, iOS, Linux, Android, WebGL" + ;; +esac + +echo "buildTarget=$UNITY_TARGET" >> "$GITHUB_OUTPUT" +echo "buildArg=$BUILD_ARG" >> "$GITHUB_OUTPUT" diff --git a/unity/unity-get-container/action.yaml b/unity/unity-get-container/action.yaml new file mode 100644 index 0000000..ee1e5a6 --- /dev/null +++ b/unity/unity-get-container/action.yaml @@ -0,0 +1,23 @@ +name: unity-get-container +description: "Get the correct Unity docker container from a provided platform." +inputs: + version: + description: "Unity Version." + required: true + platform: + description: "Unity Platform. Options: windows, windows32bit, mac, linux, android" + required: true +outputs: + container: + description: "Unity Docker Container" + value: ${{ steps.getContainer.outputs.container }} +runs: + using: "composite" + steps: + - name: "Get Unity Docker Container." + id: getContainer + run: | + #Choose the appropriate container from: https://hub.docker.com/r/unityci/editor + + bash ${{ github.action_path }}/get_container.sh "${{ inputs.platform }}" "${{ inputs.version }}" + shell: bash \ No newline at end of file diff --git a/unity/unity-get-container/get_container.sh b/unity/unity-get-container/get_container.sh new file mode 100644 index 0000000..23d7126 --- /dev/null +++ b/unity/unity-get-container/get_container.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# Choose the appropriate container from: https://hub.docker.com/r/unityci/editor +UNITY_TARGET="$1" +UNITY_VERSION="$2" + +TARGET=$(echo "$UNITY_TARGET" | awk '{print tolower($0)}') +BUILD_ARG="" +case $TARGET in + "windows" | "windows32bit") + UNITY_TARGET=windows-mono-1 + ;; + "mac" | "osx") + UNITY_TARGET=mac-mono-1 + ;; + "ios") + UNITY_TARGET=ios-1 + UNITY_VERSION=ubuntu-$UNITY_VERSION + ;; + "linux") + UNITY_TARGET=base-1 + UNITY_VERSION=ubuntu-$UNITY_VERSION + ;; + "android") + UNITY_TARGET=android-1 + UNITY_VERSION=ubuntu-$UNITY_VERSION + ;; + "webgl") + UNITY_TARGET=webgl-1 + UNITY_VERSION=ubuntu-$UNITY_VERSION + ;; + *) + echo "Invalid target. Valid options are: Windows, Windows32bit, Mac, iOS, Linux, Android, WebGL" + ;; +esac + +CONTAINER=unityci/editor:$UNITY_VERSION-$UNITY_TARGET +echo "container=$CONTAINER" >> "$GITHUB_OUTPUT" \ No newline at end of file diff --git a/unity/unity-get-version/action.yaml b/unity/unity-get-version/action.yaml new file mode 100644 index 0000000..fc0a675 --- /dev/null +++ b/unity/unity-get-version/action.yaml @@ -0,0 +1,25 @@ +name: unity-get-version +description: "Get the correct Unity version from a provided project." +inputs: + projectPath: + description: "Path to the Unity project." + required: true + default: "." +outputs: + projectVersion: + description: "Unity project version." + value: ${{ steps.getVersion.outputs.projectVersion }} +runs: + using: "composite" + steps: + - name: "Get Unity project version." + id: getVersion + run: | + VERSION_KEY="m_EditorVersion" + VERSION_FILE="ProjectSettings/ProjectVersion.txt" + VERSION_FILE_PATH="${{ inputs.projectPath }}/$VERSION_FILE" + + VERSION=$(grep -w $VERSION_KEY $VERSION_FILE_PATH | cut -d ':' -f2 | xargs) + + echo "projectVersion=$VERSION" >> "$GITHUB_OUTPUT" + shell: bash diff --git a/unity/unity-project-cached/action.yaml b/unity/unity-project-cached/action.yaml new file mode 100644 index 0000000..3ad6f15 --- /dev/null +++ b/unity/unity-project-cached/action.yaml @@ -0,0 +1,105 @@ +name: unity-project-cached +description: "Run a Unity command using a project's version and a build target. Cache the library folder." +inputs: + projectPath: + description: "Path to the Unity project." + required: true + default: "." + platform: + description: "Unity Platform. Options: windows, windows32bit, mac, linux, android" + required: true + serial: + description: "Unity license serial number." + required: true + email: + description: "Unity email." + required: true + password: + description: "Unity password." + required: true + executeMethod: + description: "Unity method to call." + required: false + command: + description: "Additional unity commands." + required: false + buildOnCacheHit: + description: "Whether or not to build if a cache was found. Default: true" + required: false + default: "true" + sshPublicKey: + description: "Public SSH key to use for git package restoration." + required: false + sshPrivateKey: + description: "Private SSH key to use for git package restoration." + required: false + cacheSuffix: + description: "Suffix or hash to use for the cache key." + required: false + default: ${{ github.sha }} + cachePrefix: + description: "Prefix to use for the cache key." + required: false + default: unity-library + releaseBranch: + description: "Release name to use for the middle of the cache key if an exact release match was not found." + required: false + default: release + cachePath: + description: "Cache path. Default: Library" + required: false + default: Library +outputs: + cacheChanged: + description: "Whether or not the cache was changed." + value: ${{ steps.check-cache.outputs.cache-hit != 'true' }} +runs: + using: "composite" + steps: + - name: "Get full cache key and build command." + id: command + run: | + # Get the full cache id. + echo "key=${{ inputs.cachePrefix }}-${{ github.ref_name }}-${{ inputs.cacheSuffix }}" >> "$GITHUB_OUTPUT" + # Get the build command. + COMMAND="${{ inputs.command }}" + if [[ -n "${{ inputs.executeMethod }}" ]]; then + COMMAND="$COMMAND -executeMethod ${{ inputs.executeMethod }}" + fi + echo "command=$COMMAND" >> "$GITHUB_OUTPUT" + shell: bash + - name: "Check if cache exists." + if: ${{ !env.ACT }} + id: check-cache + uses: actions/cache/restore@v3 + with: + path: ${{ inputs.cachePath }} + key: ${{ steps.command.outputs.key }} + lookup-only: true + - name: "Restore Library from Cache." + if: ${{ !env.ACT && ( inputs.buildOnCacheHit == 'true' || steps.check-cache.outputs.cache-hit != 'true' ) }} + uses: actions/cache/restore@v3 + with: + path: ${{ inputs.cachePath }} + key: ${{ steps.command.outputs.key }} + restore-keys: | + ${{ inputs.cachePrefix }}-${{ github.ref_name }} + ${{ inputs.cachePrefix }}-${{ inputs.releaseBranch }} + ${{ inputs.cachePrefix }} + - name: "Build project." + if: ${{ inputs.buildOnCacheHit == 'true' || steps.check-cache.outputs.cache-hit != 'true' }} + uses: act/common/unity/unity-project@master + with: + platform: ${{ inputs.platform }} + serial: ${{ inputs.serial }} + email: ${{ inputs.email }} + password: ${{ inputs.password }} + sshPublicKey: ${{ inputs.sshPublicKey }} + sshPrivateKey: ${{ inputs.sshPrivateKey }} + command: ${{ steps.command.outputs.command }} + - name: "Upload Library to Cache." + if: ${{ !env.ACT && steps.check-cache.outputs.cache-hit != 'true' }} + uses: actions/cache/save@v3 + with: + path: ${{ inputs.cachePath }} + key: ${{ steps.command.outputs.key }} diff --git a/unity/unity-project/action.yaml b/unity/unity-project/action.yaml new file mode 100644 index 0000000..04d68ee --- /dev/null +++ b/unity/unity-project/action.yaml @@ -0,0 +1,74 @@ +name: unity-project +description: "Run a Unity command using a project's version and a build target." +inputs: + projectPath: + description: "Path to the Unity project." + required: true + default: "." + platform: + description: "Unity Platform. Options: windows, windows32bit, mac, linux, android" + required: true + serial: + description: "Unity license serial number. Or 'personal' for a personal license." + required: true + default: personal + email: + description: "Unity email." + required: true + password: + description: "Unity password." + required: true + command: + description: "Unity command to run." + required: false + unityBuilder: + description: "Whether or not to use the UnityBuilder instead of a Unity command." + required: false + noGraphics: + description: "Whether or not to use the graphics device when running Unity." + required: false + default: "true" + cacheVolume: + description: "Name of the volume to cache the Library folder to." + required: false + removeContainer: + description: "Remove the mock container after building." + required: false + default: "false" +runs: + using: "composite" + steps: + - name: "Get Unity Version." + id: getVersion + uses: act/unity/unity-get-version@master + with: + projectPath: ${{ inputs.projectPath }} + - name: "Get Unity buildTarget." + id: getTarget + uses: act/unity/unity-get-buildtarget@master + with: + platform: ${{ inputs.platform }} + - name: "Restore the cached Library folder." + if: inputs.cacheVolume != null + uses: act/common/docker/docker-cp@master + with: + volume: ${{ inputs.cacheVolume }} + toPath: . + - name: "Run Unity command." + uses: act/unity/unity-command@master + with: + platform: ${{ inputs.platform }} + version: ${{ steps.getVersion.outputs.projectVersion }} + serial: ${{ inputs.serial }} + email: ${{ inputs.email }} + password: ${{ inputs.password }} + command: -projectPath ${{ inputs.projectPath }} -buildTarget ${{ steps.getTarget.outputs.buildTarget }} ${{ inputs.command }} + removeContainer: ${{ inputs.removeContainer }} + noGraphics: ${{ inputs.noGraphics }} + - name: "Cache the Library folder." + if: inputs.cacheVolume != null + uses: act/common/docker/docker-cp@master + with: + recreateVolume: true + volume: ${{ inputs.cacheVolume }} + fromPath: Library diff --git a/unity/unity/action.yaml b/unity/unity/action.yaml new file mode 100644 index 0000000..1819789 --- /dev/null +++ b/unity/unity/action.yaml @@ -0,0 +1,29 @@ +name: unity +description: "Register Unity with the provided license and run a Unity command." +inputs: + serial: + description: "Unity license serial number. Or 'personal' for a personal license. Or 'activated' to skip activation." + required: true + default: personal + email: + description: "Unity email." + required: true + password: + description: "Unity password." + required: true + command: + description: "Unity command to run." + required: false + unityBuilder: + description: "Whether or not to use the UnityBuilder instead of a Unity command." + required: false +runs: + using: docker + #This is a base "mock" image which is replaced by the correct image in the "unity-command" action at runtime. + image: docker://unityci/base:latest + args: + - ${{ inputs.serial }} + - ${{ inputs.email }} + - ${{ inputs.password }} + - ${{ inputs.command }} + - ${{ inputs.unityBuilder }} diff --git a/utils/chown/action.yaml b/utils/chown/action.yaml index 0f3e907..2de4c3a 100644 --- a/utils/chown/action.yaml +++ b/utils/chown/action.yaml @@ -29,8 +29,8 @@ runs: echo $USER_UID:$USER_GID - echo "::set-output name=uid::$USER_UID" - echo "::set-output name=gid::$USER_GID" + echo "uid=$USER_UID" >> "$GITHUB_OUTPUT" + echo "gid=$USER_GID" >> "$GITHUB_OUTPUT" shell: bash - name: "Take ownership of output." uses: act/common/distros/busybox@master diff --git a/utils/compare-files/action.yaml b/utils/compare-files/action.yaml new file mode 100644 index 0000000..e6bafd2 --- /dev/null +++ b/utils/compare-files/action.yaml @@ -0,0 +1,49 @@ +name: compare-files +description: "Compare the output of a command to an expected value." +inputs: + expected: + description: "Expected output file." + required: true + expectedPattern: + description: "Optional pattern to match files in the expected directory." + required: false + actual: + description: "Actual output file." + required: true + actualPattern: + description: "Optional pattern to match files in the actual directory." + required: false + exitOnFail: + description: "Should the program exit on a failure." + required: true + default: "true" +outputs: + success: + description: "The result of the comparison." + value: ${{ steps.compare.outputs.success }} +runs: + using: "composite" + steps: + - name: "Read files." + id: read + run: | + LHS_NUSPEC=$(cat "${{ inputs.expected }}"${{ inputs.expectedPattern }}) + RHS_NUSPEC=$(cat "${{ inputs.actual }}"${{ inputs.actualPattern }}) + + if [[ -n "$LHS_NUSPEC" ]]; then + echo "lhs<> "$GITHUB_OUTPUT" + echo "$LHS_NUSPEC" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + fi + if [[ -n "$RHS_NUSPEC" ]]; then + echo "rhs<> "$GITHUB_OUTPUT" + echo "$RHS_NUSPEC" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + fi + shell: bash + - name: "Build matrix from yaml." + uses: act/common/utils/compare@master + with: + expected: ${{ steps.read.outputs.lhs }} + actual: ${{ steps.read.outputs.rhs }} + exitOnFail: ${{ inputs.exitOnFail }} \ No newline at end of file diff --git a/utils/compare-nupkg/action.yaml b/utils/compare-nupkg/action.yaml new file mode 100644 index 0000000..bd1511e --- /dev/null +++ b/utils/compare-nupkg/action.yaml @@ -0,0 +1,99 @@ +name: compare-nupkg +description: "Compare the contents of a nupkg file to an expected value." +inputs: + lhs: + description: "Left hand side nupkg." + required: true + rhs: + description: "Right hand side nupkg." + required: true + compareNuspec: + description: "Whether or not to compare the .nuspec file when comparing versions." + required: true + default: "false" + exitOnFail: + description: "Should the program exit on a failure." + required: true + default: "false" + tmpDir: + description: "Temporary directory. Default: _tmp" + required: true + default: _tmp +outputs: + success: + description: "The result of the comparison." + value: ${{ steps.compare.outputs.success == 'true' && ( inputs.compareNuspec == 'false' || steps.compare-nuspec.outputs.success == 'true' ) }} +runs: + using: "composite" + steps: + - name: "Make temporary directory for lhs extraction" + id: mktemp-lhs + uses: act/common/utils/mktemp@master + with: + outputType: dir + tmpDir: ${{ inputs.tmpDir }} + - name: "Make temporary directory for rhs extraction" + id: mktemp-rhs + uses: act/common/utils/mktemp@master + with: + outputType: dir + tmpDir: ${{ inputs.tmpDir }} + - name: "Extract lhs." + uses: act/common/utils/extract@master + with: + file: ${{ inputs.lhs }} + outputDir: ${{ steps.mktemp-lhs.outputs.tmp }} + - name: "Extract rhs." + uses: act/common/utils/extract@master + with: + file: ${{ inputs.rhs }} + outputDir: ${{ steps.mktemp-rhs.outputs.tmp }} + - name: "Disassemble lhs dlls." + uses: act/common/mono/ikdasm-files@master + with: + directory: ${{ steps.mktemp-lhs.outputs.tmp }}/lib + deleteAssemblies: true + removeComments: true + - name: "Disassemble rhs dlls." + uses: act/common/mono/ikdasm-files@master + with: + directory: ${{ steps.mktemp-rhs.outputs.tmp }}/lib + deleteAssemblies: true + removeComments: true + - name: "Get shasum for lhs." + id: lhs-shasum + uses: act/common/utils/shasum-files@master + with: + directory: ${{ steps.mktemp-lhs.outputs.tmp }}/lib + pattern: "*" + - name: "Get shasum for rhs." + id: rhs-shasum + uses: act/common/utils/shasum-files@master + with: + directory: ${{ steps.mktemp-rhs.outputs.tmp }}/lib + pattern: "*" + - name: "Compare lhs and rhs." + id: compare + uses: act/common/utils/compare@master + with: + expected: ${{ steps.lhs-shasum.outputs.sums }} + actual: ${{ steps.rhs-shasum.outputs.sums }} + exitOnFail: ${{ inputs.exitOnFail }} + #TODO: Use a yq expression to remove the git sha and version before comparing. + - name: "Compare nuspec files." + id: compare-nuspec + if: ${{ inputs.compareNuspec == 'true' }} + uses: act/common/utils/compare-files@master + with: + expected: ${{ steps.mktemp-lhs.outputs.tmp }} + expectedPattern: /*.nuspec + actual: ${{ steps.mktemp-rhs.outputs.tmp }} + actualPattern: /*.nuspec + exitOnFail: ${{ inputs.exitOnFail }} + - name: "Take ownership of the artifacts." + uses: act/common/utils/chown@master + with: + file: ${{ inputs.tmpDir }} + - name: "Remove temporary files." + run: rm -rf "${{ inputs.tmpDir }}" + shell: bash diff --git a/utils/compare/action.yaml b/utils/compare/action.yaml new file mode 100644 index 0000000..3c413a0 --- /dev/null +++ b/utils/compare/action.yaml @@ -0,0 +1,44 @@ +name: compare +description: "Compare the output of a command to an expected value." +inputs: + expected: + description: "Expected output." + required: false + actual: + description: "Actual output." + required: true + exitOnFail: + description: "Should the program exit on a failure." + required: true + default: "true" +outputs: + success: + description: "The result of the comparison." + value: ${{ steps.compare.outputs.success }} +runs: + using: "composite" + steps: + - name: "Compare input and output" + id: compare + run: | + EXPECTED=$(cat <> "$GITHUB_OUTPUT" + else + echo "success=false" >> "$GITHUB_OUTPUT" + if [[ "${{ inputs.exitOnFail }}" == "true" ]]; then + echo EXPECTED: "$EXPECTED" + echo -------------------------------- + echo ACTUAL: "$ACTUAL" + exit 1 + fi + fi + shell: bash diff --git a/utils/download/download.sh b/utils/download/download.sh index a8faae6..03060e8 100644 --- a/utils/download/download.sh +++ b/utils/download/download.sh @@ -5,4 +5,5 @@ if [[ -z "$OUTPUT_FILE" ]]; then OUTPUT_FILE="$(basename $URL)" fi wget $URL -O "$OUTPUT_FILE" -echo "::set-output name=file::$OUTPUT_FILE" \ No newline at end of file + +echo "file=$OUTPUT_FILE" >> "$GITHUB_OUTPUT" diff --git a/utils/envsubst/.github/workflows/test.yaml b/utils/envsubst/.github/workflows/test.yaml new file mode 100644 index 0000000..ab6602c --- /dev/null +++ b/utils/envsubst/.github/workflows/test.yaml @@ -0,0 +1,25 @@ +#This is an example of a possible way to Unit Test a single action. +name: "Run unit tests." +on: workflow_call +jobs: + run-tests: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v3 + - name: "Run Test" + id: test + uses: ./. + env: + TEST_VAR: Hello, world! + with: + input: | + And I say: + "$TEST_VAR" + - name: "Verify output." + uses: act/common/utils/compare@master + with: + expected: | + And I say: + "Hello, world!" + actual: | + ${{ steps.test.outputs.result }} diff --git a/utils/envsubst/action.yaml b/utils/envsubst/action.yaml new file mode 100644 index 0000000..4f95853 --- /dev/null +++ b/utils/envsubst/action.yaml @@ -0,0 +1,31 @@ +name: envsubst +description: "Substitute environment variables in the given input." +inputs: + input: + description: "Input to substitute." + required: false + tmpDir: + description: "Temporary directory. Default: _tmp" + required: true + default: _tmp +outputs: + result: + description: "The result of the substitution." + value: ${{ steps.envsubst.outputs.console }} +runs: + using: "composite" + steps: + - name: "Make temporary file of input." + id: mktmp + uses: act/common/utils/mktemp@master + with: + input: ${{ inputs.input }} + tmpDir: ${{ inputs.tmpDir }} + - name: "Download file." + id: envsubst + uses: act/common/distros/rockylinux@master + with: + args: envsubst < ${{ steps.mktmp.outputs.tmp }} + - name: "Remove temporary files." + run: rm -rf "${{ inputs.tmpDir }}" + shell: bash \ No newline at end of file diff --git a/utils/extract/action.yaml b/utils/extract/action.yaml index c8ec811..aade8c4 100644 --- a/utils/extract/action.yaml +++ b/utils/extract/action.yaml @@ -27,9 +27,9 @@ runs: COMMAND="unzip ${{ inputs.prefixArgs }} -o ${{ inputs.file }} ${{ inputs.additionalArgs }}" OUTPUT_DIR="${{ inputs.outputDir }}" if [[ -n "$OUTPUT_DIR" ]]; then - COMMAND="$COMMAND" -d "$OUTPUT_DIR" + COMMAND="$COMMAND -d \"$OUTPUT_DIR\"" fi - echo "::set-output name=command::$COMMAND" + echo "command=$COMMAND" >> "$GITHUB_OUTPUT" shell: bash - name: "Convert file." id: convert @@ -39,7 +39,8 @@ runs: - name: "Delete source." run: | if [[ ${{ inputs.deleteSource }} != "true" ]]; then - return + exit 0 fi + rm ${{ inputs.file }} shell: bash \ No newline at end of file diff --git a/utils/get-latest-version/action.yaml b/utils/get-latest-version/action.yaml new file mode 100644 index 0000000..c5b71bb --- /dev/null +++ b/utils/get-latest-version/action.yaml @@ -0,0 +1,44 @@ +name: get-latest-version +description: "Get the latest version of a package." +inputs: + versions: + description: "Newline-seperated list of package versions." + required: true + filter: + description: "String to filter by." + required: false + filterIsExpression: + description: "Is the first filter a Regular Expression? Values: true, false." + required: false + default: "false" + stripPrerelease: + description: "Whether or not to strip prerelease versions. Values: true, false." + required: false + default: "false" +outputs: + version: + description: "The latest version of the specified package." + value: ${{ steps.parse.outputs.version }} +runs: + using: "composite" + steps: + - name: "Get latest package." + id: parse + run: | + VERSIONS="${{ inputs.versions }}" + # Filter versions, sort them, and get the latest one + if [[ "${{ inputs.filterIsExpression }}" == "true" ]]; then + EXPRESSION_FLAG="-E" + fi + if [[ "${{ inputs.stripPrerelease }}" == "true" ]]; then + VERSIONS=$(echo "$VERSIONS" | grep -E "^(v)?[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?$") + fi + RESULT=$(echo "$VERSIONS" | grep $EXPRESSION_FLAG "${{ inputs.filter }}" || echo "error") + + VERSION=$(echo "$RESULT" | sort -rV | head -1) + + if [[ "$RESULT" != "error" ]]; then + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + fi + # No error if no versions found. + shell: bash \ No newline at end of file diff --git a/utils/inputtype/action.yaml b/utils/inputtype/action.yaml new file mode 100644 index 0000000..273327e --- /dev/null +++ b/utils/inputtype/action.yaml @@ -0,0 +1,29 @@ +name: inputtype +description: "Determine whether the input is a file, directory, or raw input." +inputs: + input: + description: "Input contents." + required: true +outputs: + type: + description: "Whether the input is a file, dir (directory), or raw input." + value: ${{ steps.gettype.outputs.type }} +runs: + using: "composite" + steps: + - name: "Make the temporary file." + id: gettype + run: | + #Store in a heredoc to account for quotes. + INPUT=$(cat <> "$GITHUB_OUTPUT" + shell: bash \ No newline at end of file diff --git a/utils/mktemp/action.yaml b/utils/mktemp/action.yaml new file mode 100644 index 0000000..c7d4bdd --- /dev/null +++ b/utils/mktemp/action.yaml @@ -0,0 +1,55 @@ +name: mktemp +description: "Make a temporary file or directory with the specified contents." +inputs: + input: + description: "Contents of the temporary file or directory." + required: false + default: "" + inputType: + description: "How the input should be parsed. Options: raw, file, dir, expression, auto" + required: false + default: auto + outputType: + description: "How the input should be output. Options: file, dir, auto" + required: false + default: auto + transferType: + description: "How the input should be transferred. Options: copy, move" + required: false + default: copy + tmpDir: + description: "Temporary directory. Default: /tmp" + required: true + default: /tmp + additionalArgs: + description: "Additional arguments to pass in." + required: false +outputs: + tmp: + description: "The name of the temporary file or directory." + value: ${{ steps.mktemp.outputs.tmp }} +runs: + using: "composite" + steps: + - name: "Get the proper input type." + if: ${{ inputs.inputType == 'auto' }} + id: getinputtype + uses: act/common/utils/inputtype@master + with: + input: ${{ inputs.input }} + - name: "Make the temporary file." + id: mktemp + run: | + INPUT_TYPE="${{ inputs.inputType }}" + if [[ $INPUT_TYPE == 'auto' ]]; then + INPUT_TYPE="${{ steps.getinputtype.outputs.type }}" + fi + + #Store in a heredoc to account for quotes. + INPUT=$(cat <> "$GITHUB_OUTPUT" + +if [[ -z "$INPUT" ]]; then + exit 0 +fi + +TRANSFER_COMMAND="cp -r" +if [[ $TRANSFER_TYPE == 'move' ]]; then + TRANSFER_COMMAND="mv" +fi + +if [[ $INPUT_TYPE == 'raw' ]]; then + echo "$INPUT" > "$TMP" +elif [[ $OUTPUT_TYPE == 'file' ]]; then + $TRANSFER_COMMAND "$INPUT" "$TMP" +elif [[ $OUTPUT_TYPE == 'dir' ]]; then + if [[ $INPUT_TYPE == "expression" ]]; then + $TRANSFER_COMMAND $INPUT "$TMP" + else + $TRANSFER_COMMAND "$INPUT" "$TMP" + fi + +fi diff --git a/utils/shasum-files/action.yaml b/utils/shasum-files/action.yaml new file mode 100644 index 0000000..047fe17 --- /dev/null +++ b/utils/shasum-files/action.yaml @@ -0,0 +1,28 @@ +name: shasum-files +description: "Output the shasum of files in a directory matching a pattern." +inputs: + directory: + description: "Directory to search." + required: true + default: '.' + pattern: + description: "Pattern of files to search for." + required: true + default: '*' +outputs: + sums: + description: "The sums of the files matching the pattern." + value: ${{ steps.sums.outputs.sums }} +runs: + using: "composite" + steps: + - name: "Get sums of files matching the pattern" + id: sums + run: | + OUTPUT=$(bash ${{ github.action_path }}/get_sums.sh "${{ inputs.directory }}" "${{ inputs.pattern }}") + if [[ -n "$OUTPUT" ]]; then + echo "sums<> "$GITHUB_OUTPUT" + echo "$OUTPUT" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + fi + shell: bash diff --git a/utils/shasum-files/get_sums.sh b/utils/shasum-files/get_sums.sh new file mode 100644 index 0000000..a34eefa --- /dev/null +++ b/utils/shasum-files/get_sums.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# Get the directory and pattern as arguments +DIR=$1 +PATTERN=$2 + +find "$DIR" -type f -name "$PATTERN" -print0 | while IFS= read -r -d '' file; do + # compute the sha256 hash of the file using sha256sum command + HASH=$(sha256sum "$file" | cut -d " " -f1) + NAME=$(basename "$file") + # print the file name and hash to a temporary file + echo "$NAME: $HASH" +done diff --git a/utils/urlencode/action.yaml b/utils/urlencode/action.yaml new file mode 100644 index 0000000..d645809 --- /dev/null +++ b/utils/urlencode/action.yaml @@ -0,0 +1,47 @@ +name: urlencode +description: "Encode or decode the input string as a url." +inputs: + input: + description: "Input to encode/decode." + required: true + mild: + description: "Do a mild conversion." + required: false + default: "false" + decode: + description: "Whether or not to decode instead of encode." + required: true + default: "false" +outputs: + result: + description: "The url-encoded or decoded string." + value: ${{ steps.url.outputs.console }} +runs: + using: "composite" + steps: + - name: "Build the command." + id: command + run: | + COMMAND="urlencode" + + DECODE="${{ inputs.decode }}" + if [[ "$DECODE" == "true" ]]; then + COMMAND="$COMMAND -d" + fi + + MILD="${{ inputs.mild }}" + if [[ "$MILD" == "true" ]]; then + if [[ "$DECODE" == "true" ]]; then + echo "Cannot perform url decoding in mild mode." + exit 1 + fi + COMMAND="$COMMAND -m" + fi + + echo "command=$COMMAND" >> "$GITHUB_OUTPUT" + shell: bash + - name: "Encode/decode the input." + id: url + uses: act/common/distros/debian@master + with: + args: ${{ steps.command.outputs.command }} "${{ inputs.input }}" diff --git a/utils/uuid/action.yaml b/utils/uuid/action.yaml new file mode 100644 index 0000000..756912f --- /dev/null +++ b/utils/uuid/action.yaml @@ -0,0 +1,18 @@ +name: uuid +description: "Download a file from a URL." +inputs: + additionalArgs: + description: "Additional arguments to pass in." + required: false +outputs: + uuid: + description: "The unique identifier output." + value: ${{ steps.uuid.outputs.console }} +runs: + using: "composite" + steps: + - name: "Download file." + id: uuid + uses: act/common/distros/rockylinux@master + with: + args: uuid ${{ inputs.additionalArgs }} \ No newline at end of file diff --git a/utils/version-increment-branch/action.yaml b/utils/version-increment-branch/action.yaml new file mode 100644 index 0000000..ac1f4a4 --- /dev/null +++ b/utils/version-increment-branch/action.yaml @@ -0,0 +1,57 @@ +name: version-increment-branch +description: "Get the latest and next version of a package from a NuGet repository based on the current branch and merge target." +inputs: + version: + description: "The version to increment." + required: false +outputs: + nextVersion: + description: "The next version of the package, based on the current branch and merge target." + value: ${{ steps.increment.outputs.nextVersion }} + baseVersion: + description: "Base of the branch-defined version." + value: ${{ steps.branch.outputs.baseVersion }} + majorMinorPatchVersion: + description: "Major.Minor.Patch of the latest version." + value: ${{ steps.branch.outputs.majorMinorPatchVersion }} +runs: + using: "composite" + steps: + - name: "Get latest non-pre-release NuGet package version." + id: parse + uses: act/common/utils/version-parse@master + with: + version: ${{ inputs.version }} + - name: "Build the next version with the given repository information." + id: branch + run: | + EVENT_NAME="${{ github.event_name }}" + HEAD="${{ github.head_ref || github.ref_name }}" + BASE="${{ github.base_ref || github.ref_name }}" + PR_NUMBER="${{ github.event.number || '-1' }}" + + MAJOR="${{ steps.parse.outputs.major || '0' }}" + MINOR="${{ steps.parse.outputs.minor || '0' }}" + PATCH="${{ steps.parse.outputs.patch || '0' }}" + LAST_MMP_VERSION="$MAJOR.$MINOR.$PATCH" + + REVISION="${{ steps.parse.outputs.revision || '0' }}" + + bash ${{ github.action_path }}/get_next_version.sh "$EVENT_NAME" "$HEAD" "$BASE" "$PR_NUMBER" "$LAST_MMP_VERSION" "$REVISION" + shell: bash + - name: "Parse the version to increment." + id: parseNext + uses: act/common/utils/version-parse@master + with: + version: ${{ steps.branch.outputs.currentVersion }} + - name: "Get next version." + id: increment + uses: act/common/utils/version-increment@master + with: + incrementMode: revision + major: ${{ steps.parseNext.outputs.major }} + minor: ${{ steps.parseNext.outputs.minor }} + patch: ${{ steps.parseNext.outputs.patch }} + revision: ${{ steps.parseNext.outputs.revision }} + suffix: ${{ steps.parseNext.outputs.suffix }} + metadata: ${{ steps.parseNext.outputs.metadata }} diff --git a/utils/version-increment-branch/compare_versions.sh b/utils/version-increment-branch/compare_versions.sh new file mode 100644 index 0000000..c57c6f6 --- /dev/null +++ b/utils/version-increment-branch/compare_versions.sh @@ -0,0 +1,30 @@ +#!/bin/bash +function compare_versions +{ + # Check if two arguments are given + if [ $# -ne 2 ]; then + echo "Please provide two version numbers to compare" + return 1 + fi + + # Assign arguments to local variables + local ver1=$1 + local ver2=$2 + + # Remove dots and pad with zeros + ver1=${ver1//./} + ver2=${ver2//./} + printf -v ver1 "%-4s" "$ver1" + printf -v ver2 "%-4s" "$ver2" + ver1=${ver1// /0} + ver2=${ver2// /0} + + # Compare as integers and return result + if [ $ver1 -lt $ver2 ]; then + return -1 + elif [ $ver1 -gt $ver2 ]; then + return 1 + else + return 0 + fi +} diff --git a/utils/version-increment-branch/get_next_version.sh b/utils/version-increment-branch/get_next_version.sh new file mode 100644 index 0000000..2d6c613 --- /dev/null +++ b/utils/version-increment-branch/get_next_version.sh @@ -0,0 +1,52 @@ +#!/bin/bash +FILE_PATH=$(readlink -f "$BASH_SOURCE") +FILE_DIR=$(dirname "$FILE_PATH") +source "$FILE_DIR/compare_versions.sh" + +EVENT_NAME="$1" +HEAD="$2" +BASE="$3" +PR_NUMBER="$4" +LATEST_MMP_VERSION="$5" # Latest major.minor.patch version. +LATEST_REVISION="${6:-0}" + +if [[ ! -f "$GITHUB_OUTPUT" ]]; then + # Write to stdout if the output file doesn't exist. + GITHUB_OUTPUT="/dev/fd/1" +fi + +BASE_VERSION=$(echo "$BASE" | cut -d '/' -sf 2 | xargs) +# Remove the first v in the version if it has onem as well as invalid characters. +BASE_VERSION="${BASE_VERSION#v}" +# Convert the base to a valid semver version. Anything not alphanumeric or a - or .. +BASE_VERSION="${BASE_VERSION//[^a-z0-9\-\.]/-}" + +if [[ -z "$BASE_VERSION" ]]; then + # Just use the latest version as a base if the release branch has no possible versions. + BASE_VERSION="$LATEST_MMP_VERSION" +fi + +echo "majorMinorPatchVersion=$BASE_VERSION" >> "$GITHUB_OUTPUT" + +# Convert the head to a valid semver patch version. Anything not alphanumeric or a -. +HEAD="${HEAD//[^a-z0-9\-]/-}" + +compare_versions "$BASE_VERSION" "$LATEST_MMP_VERSION" +if [[ $? == 1 ]]; then + # If the base version is greater than the latest version, then set the increment mode to 'patch' + LATEST_REVISION=0 +fi + +if [[ "$EVENT_NAME" == "pull_request" ]]; then + # Use the branch name as a prerelease version and increment the revision. + BASE_VERSION="$BASE_VERSION-$PR_NUMBER.$HEAD" + CURRENT_VERSION="$BASE_VERSION.$LATEST_REVISION" +elif [[ "$EVENT_NAME" != "push" && "$EVENT_NAME" != "workflow_dispatch" ]]; then + echo "Invalid event name to attempt to push a package on: $EVENT_NAME" + exit 1 +fi + +CURRENT_VERSION="$BASE_VERSION.$LATEST_REVISION" + +echo "baseVersion=$BASE_VERSION" >> "$GITHUB_OUTPUT" +echo "currentVersion=$CURRENT_VERSION" >> "$GITHUB_OUTPUT" diff --git a/utils/version-increment/action.yaml b/utils/version-increment/action.yaml new file mode 100644 index 0000000..af16074 --- /dev/null +++ b/utils/version-increment/action.yaml @@ -0,0 +1,59 @@ +name: version-increment +description: "Increment a semantic version 2.0." +inputs: + incrementMode: + description: "The mode to increment by. Options: 'default', 'major', 'minor', 'patch', 'revision'" + required: true + default: default + gitShaMetadata: + description: "Whether or not to update the git sha in the metadata." + required: false + default: "false" + major: + description: "The latest major version of the package." + required: false + minor: + description: "The latest minor version of the package." + required: false + patch: + description: "The latest patch version of the package." + required: false + revision: + description: "The latest patch revision version of the package. The suffix treated as a number seperated by a '.'" + required: false + suffix: + description: "The suffix of the package." + required: false + metadata: + description: "The metadata of the package." + required: false +outputs: + nextVersion: + description: "The next version of the package." + value: ${{ steps.parse.outputs.nextVersion }} + nextMajor: + description: "The next major version of the package." + value: ${{ steps.parse.outputs.nextMajor }} + nextMinor: + description: "The next minor version of the package." + value: ${{ steps.parse.outputs.nextMinor }} + nextPatch: + description: "The next patch version of the package." + value: ${{ steps.parse.outputs.nextPatch }} + nextRevision: + description: "The next patch revision version of the package." + value: ${{ steps.parse.outputs.nextRevision }} + nextSuffix: + description: "The next version of suffix of the package." + value: ${{ steps.parse.outputs.nextSuffix }} + nextMetadata: + description: "The next version of metadata of the package." + value: ${{ steps.parse.outputs.nextMetadata }} +runs: + using: "composite" + steps: + - name: "Get next version." + id: parse + run: | + bash ${{ github.action_path }}/increment_version.sh "${{ inputs.major }}" "${{ inputs.minor }}" "${{ inputs.patch }}" "${{ inputs.revision }}" "${{ inputs.suffix }}" "${{ inputs.metadata }}" "${{ inputs.incrementMode }}" "${{ inputs.gitShaMetadata }}" + shell: bash \ No newline at end of file diff --git a/utils/version-increment/increment_version.sh b/utils/version-increment/increment_version.sh new file mode 100644 index 0000000..cae290e --- /dev/null +++ b/utils/version-increment/increment_version.sh @@ -0,0 +1,67 @@ +#!/bin/bash +MAJOR="$1" +MINOR="$2" +PATCH="$3" +REVISION="$4" +SUFFIX="$5" +METADATA="$6" +INCREMENT_MODE="${7:-default}" +GIT_SHA_METADATA="$8" + +if [[ ! -f "$GITHUB_OUTPUT" ]]; then + # Write to stdout if the output file doesn't exist. + GITHUB_OUTPUT="/dev/fd/1" +fi + +NEXT_MAJOR=$((MAJOR + 1)) +NEXT_MINOR=$((MINOR + 1)) +NEXT_PATCH=$((PATCH + 1)) +NEXT_REVISION=$((REVISION + 1)) +NEXT_SUFFIX="$SUFFIX" +NEXT_METADATA="$METADATA" +if [[ "$GIT_SHA_METADATA" == "true" ]]; then + NEXT_METADATA="$GITHUB_SHA" +fi + +echo "nextMajor=$NEXT_MAJOR" >> "$GITHUB_OUTPUT" +echo "nextMinor=$NEXT_MINOR" >> "$GITHUB_OUTPUT" +echo "nextPatch=$NEXT_PATCH" >> "$GITHUB_OUTPUT" +echo "nextRevision=$NEXT_REVISION" >> "$GITHUB_OUTPUT" +echo "nextSuffix=$NEXT_SUFFIX" >> "$GITHUB_OUTPUT" +echo "nextMetadata=$NEXT_METADATA" >> "$GITHUB_OUTPUT" + + +# This script assumes that thre version numbers is the desired default format. +NEXT_VERSION="${MAJOR:-0}.${MINOR:-0}" +if [[ "$INCREMENT_MODE" == "default" ]]; then + if [[ -n "$REVISION" ]]; then + NEXT_VERSION="$NEXT_VERSION.${PATCH:-0}.$NEXT_REVISION" + elif [[ -n "$PATCH" ]]; then + NEXT_VERSION="$NEXT_VERSION.$NEXT_PATCH" + elif [[ -n "$MINOR" ]]; then + NEXT_VERSION="${MAJOR:-0}.$NEXT_MINOR.0" + else + NEXT_VERSION="$NEXT_MAJOR.0.0" + fi +elif [[ "$INCREMENT_MODE" == "major" ]]; then + NEXT_VERSION="$NEXT_MAJOR.0.0" +elif [[ "$INCREMENT_MODE" == "minor" ]]; then + NEXT_VERSION="${MAJOR:-0}.$NEXT_MINOR.0" +elif [[ "$INCREMENT_MODE" == "patch" ]]; then + NEXT_VERSION="${MAJOR:-0}.${MINOR:-0}.$NEXT_PATCH" +elif [[ "$INCREMENT_MODE" == "revision" ]]; then + NEXT_VERSION="${MAJOR:-0}.${MINOR:-0}.${PATCH:-0}.$NEXT_REVISION" +else + echo "Invalid increment mode: $INCREMENT_MODE" + exit 1 +fi + +if [[ -n "$NEXT_SUFFIX" ]]; then + NEXT_VERSION="$NEXT_VERSION-$NEXT_SUFFIX" +fi + +if [[ -n "$NEXT_METADATA" ]]; then + NEXT_VERSION="$NEXT_VERSION+$NEXT_METADATA" +fi + +echo "nextVersion=$NEXT_VERSION" >> "$GITHUB_OUTPUT" diff --git a/utils/version-parse/action.yaml b/utils/version-parse/action.yaml new file mode 100644 index 0000000..1ce5d44 --- /dev/null +++ b/utils/version-parse/action.yaml @@ -0,0 +1,38 @@ +name: version-parse +description: "Parse a semantic version." +inputs: + version: + description: "The version to parse." + required: true +outputs: + version: + description: "The version of the package." + value: ${{ steps.parse.outputs.version }} + major: + description: "The major version of the package." + value: ${{ steps.parse.outputs.major }} + minor: + description: "The minor version of the package." + value: ${{ steps.parse.outputs.minor }} + patch: + description: "The patch version of the package." + value: ${{ steps.parse.outputs.patch }} + revision: + description: "The patch revision version of the package. The suffix treated as a number seperated by a '.'" + value: ${{ steps.parse.outputs.revision }} + metadata: + description: "The of the package." + value: ${{ steps.parse.outputs.metadata }} + suffix: + description: "The suffix of the package." + value: ${{ steps.parse.outputs.suffix }} + isPrerelease: + description: "Whether or not the package is a prerelease package." + value: ${{ steps.parse.outputs.isPrerelease }} +runs: + using: "composite" + steps: + - name: "Parse version." + id: parse + run: bash ${{ github.action_path }}/parse_version.sh "${{ inputs.version }}" + shell: bash \ No newline at end of file diff --git a/utils/version-parse/parse_version.sh b/utils/version-parse/parse_version.sh new file mode 100644 index 0000000..f140d17 --- /dev/null +++ b/utils/version-parse/parse_version.sh @@ -0,0 +1,30 @@ +#!/bin/bash +VERSION="$1" + +if [[ ! -f "$GITHUB_OUTPUT" ]]; then + # Write to stdout if the output file doesn't exist. + GITHUB_OUTPUT="/dev/fd/1" +fi + +IS_PRERELEASE=$(echo "$VERSION" | grep -c '-') +if [[ "$IS_PRERELEASE" == 0 ]]; then + IS_PRERELEASE=false +else + IS_PRERELEASE=true +fi +echo "isPrerelease=$IS_PRERELEASE" >> "$GITHUB_OUTPUT" + +MAJOR=$(echo "$VERSION" | cut -d '.' -f 1 | cut -d '+' -f 1 | xargs printf %d 2> /dev/null) +MINOR=$(echo "$VERSION" | cut -d '.' -f 2 | cut -d '+' -f 1 | xargs printf %d 2> /dev/null) +PATCH=$(echo "$VERSION" | cut -d '.' -f 3 | cut -d '-' -f 1 | xargs | cut -d '+' -f 1 | xargs printf %d 2> /dev/null) +REVISION=$(echo "$VERSION" | cut -d '.' -f 4 | cut -d '-' -f 1 | cut -d '+' -f 1 | xargs printf %d 2> /dev/null) +SUFFIX=$(echo "$VERSION" | sed "s|^$MAJOR.$MINOR.$PATCH||" | sed "s|^.$REVISION||" | sed "s|^-||" | cut -d '+' -f 1 | xargs) +METADATA=$(echo "$VERSION" | cut -d '+' -sf 2 | xargs) # Empty if no delimeter '+' present. + +echo "version=$VERSION" >> "$GITHUB_OUTPUT" +echo "major=$MAJOR" >> "$GITHUB_OUTPUT" +echo "minor=$MINOR" >> "$GITHUB_OUTPUT" +echo "patch=$PATCH" >> "$GITHUB_OUTPUT" +echo "revision=$REVISION" >> "$GITHUB_OUTPUT" +echo "suffix=$SUFFIX" >> "$GITHUB_OUTPUT" +echo "metadata=$METADATA" >> "$GITHUB_OUTPUT" diff --git a/yq/yq-convert/action.yaml b/yq/yq-convert/action.yaml new file mode 100644 index 0000000..e955917 --- /dev/null +++ b/yq/yq-convert/action.yaml @@ -0,0 +1,44 @@ +name: yq-convert +description: "Change the language format of a file." +inputs: + from: + #yaml, json, xml + description: "Format to convert from..." + required: true + to: + #yaml, json, xml + description: "Format to convert to..." + required: true + input: + #yaml, json, xml + description: "File or data to convert." + required: true + tmpDir: + description: "Temporary directory. Default: _tmp" + required: true + default: _tmp +outputs: + result: + description: "The converted file." + value: ${{ steps.convert.outputs.console }} +runs: + using: "composite" + steps: + - name: "Make temporary file of input." + id: mktmp + uses: act/common/utils/mktemp@master + with: + input: ${{ inputs.input }} + tmpDir: ${{ inputs.tmpDir }} + - name: "Convert file." + id: convert + uses: act/common/yq/yq@master + with: + command: -p ${{ inputs.from }} -o ${{ inputs.to }} "${{ steps.mktmp.outputs.tmp }}" + - name: "Take ownership of the artifacts." + uses: act/common/utils/chown@master + with: + file: ${{ inputs.tmpDir }} + - name: "Remove temporary files." + run: rm -rf "${{ inputs.tmpDir }}" + shell: bash \ No newline at end of file diff --git a/yq/yq-expression/action.yaml b/yq/yq-expression/action.yaml new file mode 100644 index 0000000..6fda428 --- /dev/null +++ b/yq/yq-expression/action.yaml @@ -0,0 +1,35 @@ +name: yq-expression +description: "Change the language format of a file." +inputs: + input: + description: "Yaml to run the expression on." + required: true + expression: + description: "Expression to run." + required: true + default: "." + tmpDir: + description: "Temporary directory. Default: _tmp" + required: true + default: _tmp +outputs: + result: + description: "The converted file." + value: ${{ steps.expression.outputs.console }} +runs: + using: "composite" + steps: + - name: "Make temporary file of input." + id: input + uses: act/common/utils/mktemp@master + with: + input: ${{ inputs.input }} + tmpDir: ${{ inputs.tmpDir }} + - name: "Run expression." + id: expression + uses: act/common/yq/yq@master + with: + command: "'${{ inputs.expression }}' '${{ steps.input.outputs.tmp }}'" + - name: "Remove temporary files." + run: rm -rf "${{ inputs.tmpDir }}" + shell: bash diff --git a/yq/yq-merge/action.yaml b/yq/yq-merge/action.yaml new file mode 100644 index 0000000..564607e --- /dev/null +++ b/yq/yq-merge/action.yaml @@ -0,0 +1,48 @@ +name: yq-merge +description: "Change the language format of a file." +inputs: + lhs: + description: "Left-hand side of merge." + required: true + rhs: + description: "Right-hand side of merge." + required: true + operator: + description: "Merge operator. See: https://mikefarah.gitbook.io/yq/operators/multiply-merge" + required: true + default: "*+" + element: + description: "Element to merge." + required: true + default: "." + tmpDir: + description: "Temporary directory. Default: _tmp" + required: true + default: _tmp +outputs: + result: + description: "The converted file." + value: ${{ steps.merge.outputs.console }} +runs: + using: "composite" + steps: + - name: "Make temporary file of first input." + id: lhs + uses: act/common/utils/mktemp@master + with: + input: ${{ inputs.lhs }} + tmpDir: ${{ inputs.tmpDir }} + - name: "Make temporary file of second input." + id: rhs + uses: act/common/utils/mktemp@master + with: + input: ${{ inputs.rhs }} + tmpDir: ${{ inputs.tmpDir }} + - name: "Merge files." + id: merge + uses: act/common/yq/yq@master + with: + command: "'${{ inputs.element }} ${{ inputs.operator }} load(\"${{ steps.rhs.outputs.tmp }}\")' '${{ steps.lhs.outputs.tmp }}'" + - name: "Remove temporary files." + run: rm -rf "${{ inputs.tmpDir }}" + shell: bash diff --git a/yq/yq-trim/action.yaml b/yq/yq-trim/action.yaml new file mode 100644 index 0000000..dc8e757 --- /dev/null +++ b/yq/yq-trim/action.yaml @@ -0,0 +1,44 @@ +name: yq-trim +description: "Change the language format of a file." +inputs: + input: + description: "Left-hand side of merge." + required: true + recursive: + description: "Recursivevly trim the input. Default: true" + required: true + default: "true" + tmpDir: + description: "Temporary directory. Default: _tmp" + required: true + default: _tmp +outputs: + result: + description: "The converted file." + value: ${{ steps.trim.outputs.console }} +runs: + using: "composite" + steps: + - name: "Make temporary file of input." + id: input + uses: act/common/utils/mktemp@master + with: + input: ${{ inputs.input }} + tmpDir: ${{ inputs.tmpDir }} + - name: "Make temporary file of script." + id: script + uses: act/common/utils/mktemp@master + with: + input: ${{ github.action_path }}/trim.sh + tmpDir: . + - name: "Run script." + id: trim + uses: act/common/yq/yq@master + with: + program: bash + command: ${{ steps.script.outputs.tmp }} ${{ steps.input.outputs.tmp }} ${{ inputs.recursive }} + - name: "Remove temporary files." + run: | + rm "${{ steps.script.outputs.tmp }}" + rm -rf "${{ inputs.tmpDir }}" + shell: bash diff --git a/yq/yq-trim/trim.sh b/yq/yq-trim/trim.sh new file mode 100644 index 0000000..c8a9b41 --- /dev/null +++ b/yq/yq-trim/trim.sh @@ -0,0 +1,16 @@ +#!/bin/bash +INPUT="$1" +RECURSIVE="$2" + +if [[ -f "$INPUT" ]]; then + INPUT=$(cat "$INPUT") +fi + +OUTPUT=$(echo "$INPUT" | yq e 'del(.. | select(length == 0))') +if [[ "$RECURSIVE" == "true" ]]; then + while [ "$(echo "$OUTPUT" | yq e 'map (.. | select (length == 0)) | any')" = "true" ]; do + OUTPUT=$(echo "$OUTPUT" | yq e 'del (.. | select (length == 0))') + done +fi + +echo "$OUTPUT" diff --git a/yq/yq/Dockerfile b/yq/yq/Dockerfile new file mode 100644 index 0000000..2f7a47a --- /dev/null +++ b/yq/yq/Dockerfile @@ -0,0 +1,16 @@ +# Container image that runs your code +FROM debian:stable-slim + +RUN apt update && apt install -y \ + wget + +ARG VERSION=v4.30.6 +ARG BINARY=yq_linux_amd64 + +RUN wget https://github.com/mikefarah/yq/releases/download/${VERSION}/${BINARY} -O /usr/bin/yq && \ + chmod +x /usr/bin/yq + +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/yq/yq/action.yaml b/yq/yq/action.yaml new file mode 100644 index 0000000..09890f7 --- /dev/null +++ b/yq/yq/action.yaml @@ -0,0 +1,24 @@ +name: yq +description: "Run yq commands." +inputs: + command: + description: "Shell arguments to pass into yq." + required: true + program: + description: "Program to run instead of yq. Default: yq" + required: false + default: "yq" + catchErrors: + description: "Whether or not errors should be handled." + required: false +outputs: + console: + description: "The console output of the command." +runs: + env: + PROGRAM: ${{ inputs.program }} + CATCH_ERRORS: ${{ inputs.catchErrors }} + using: docker + image: Dockerfile + args: + - ${{ inputs.command }} \ No newline at end of file diff --git a/yq/yq/entrypoint.sh b/yq/yq/entrypoint.sh new file mode 100644 index 0000000..b370ac1 --- /dev/null +++ b/yq/yq/entrypoint.sh @@ -0,0 +1,27 @@ +#!/bin/bash +COMMAND="$@" + +# yq -p json -o yaml file.json # json -> yaml +# yq -p json -o xml file.json # json -> xml +# yq -p yaml -o json file.yaml # yaml -> json +# yq -p yaml -o xml file.yaml # yaml -> xml +# yq -p xml -o json file.xml # xml -> json +# yq -p xml -o yaml file.xml # xml -> yaml +#https://github.com/mikefarah/yq +PROGRAM=${PROGRAM:-"yq"} +OUTPUT=$(bash -c "$PROGRAM $COMMAND") +RESULT=$? + +#Output multiline strings. +#https://trstringer.com/github-actions-multiline-strings/ +if [[ -n "$OUTPUT" ]]; then + echo "console<> "$GITHUB_OUTPUT" + echo "$OUTPUT" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" +fi + +echo "exitCode=$RESULT" >> "$GITHUB_OUTPUT" + +if [[ "$CATCH_ERRORS" != "true" ]]; then + exit $RESULT +fi