diff --git a/.forgejo/workflows/tag-release.yml b/.forgejo/workflows/tag-release.yml index b1c3e06..0c7be9f 100644 --- a/.forgejo/workflows/tag-release.yml +++ b/.forgejo/workflows/tag-release.yml @@ -18,6 +18,7 @@ on: - aws-configure - cache - checkout + - inject-content - pnpm-build - publish-static-contents - terraform-apply diff --git a/README.md b/README.md index d1a1bf6..4c67c09 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ Shared actions for Forgejo CI/CD pipelines. | [aws-configure](aws-configure) | Authenticate with AWS via OIDC | | [cache](cache) | Cache files between workflow runs | | [checkout](checkout) | Action for checking out a repository | +| [inject-content](inject-content) | Inject content into a file by appending or overwriting | | [pnpm-build](pnpm-build) | Action for building and validating with PNPM | | [publish-static-contents](publish-static-contents) | Syncs frontend assets to S3 and invalidates a CloudFront distribution | | [terraform-apply](terraform-apply) | Apply Terraform configuration files using the official Terraform CLI | diff --git a/inject-content/README.md b/inject-content/README.md new file mode 100644 index 0000000..b44d324 --- /dev/null +++ b/inject-content/README.md @@ -0,0 +1,40 @@ +# inject-content + +Inject content into a file by appending or overwriting. Useful for writing secrets, configuration snippets, or any multi-line content into an existing file at runtime. + +## Inputs + +| Input | Required | Default | Description | +|-------|----------|---------|-------------| +| `content` | Yes | | Content to write into the target file | +| `target-file` | Yes | | Path to the target file | +| `mode` | No | `append` | Write mode: `append` adds to the end of the file; `overwrite` replaces its contents | + +## Usage + +Append secrets to a Java `.properties` file: + +```yaml +- uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/inject-content@inject-content-v1 + with: + content: ${{ secrets.APP_PROPERTIES }} + target-file: src/main/resources/application.properties +``` + +Overwrite a `.env` file: + +```yaml +- uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/inject-content@inject-content-v1 + with: + content: ${{ secrets.DOTENV_CONTENT }} + target-file: .env + mode: overwrite +``` + +## Notes + +- Content is passed via an environment variable to avoid shell injection vulnerabilities. +- In `append` mode a blank line is inserted between existing content and the new content. If the target file is empty or does not exist, no leading blank line is added. +- In `overwrite` mode the file is replaced entirely; if the file does not exist it is created. +- Both modes ensure the written content ends with a trailing newline. +- Parent directories of `target-file` are created automatically if they do not exist. diff --git a/inject-content/action.yml b/inject-content/action.yml new file mode 100644 index 0000000..6ab2ade --- /dev/null +++ b/inject-content/action.yml @@ -0,0 +1,67 @@ +name: inject-content +description: Inject content into a file by appending or overwriting + +inputs: + content: + description: Content to write into the target file + required: true + target-file: + description: Path to the target file + required: true + mode: + description: "Write mode: 'append' adds to the end of the file; 'overwrite' replaces its contents" + required: false + default: append + +outputs: + target-file: + description: Path of the file that was written + value: ${{ steps.inject.outputs.target-file }} + +runs: + using: composite + steps: + - name: Validate target-file input + shell: bash + env: + TARGET_FILE: ${{ inputs.target-file }} + run: | + if [[ -z "$TARGET_FILE" ]]; then + echo "::error::target-file must not be empty" + exit 1 + fi + + - name: Validate mode input + shell: bash + env: + MODE: ${{ inputs.mode }} + run: | + if [[ "$MODE" != "append" && "$MODE" != "overwrite" ]]; then + echo "::error::Invalid mode '$MODE'. Must be 'append' or 'overwrite'." + exit 1 + fi + + - name: Inject content into file + id: inject + shell: bash + env: + CONTENT: ${{ inputs.content }} + TARGET_FILE: ${{ inputs.target-file }} + MODE: ${{ inputs.mode }} + run: | + set -euo pipefail + + mkdir -p "$(dirname "$TARGET_FILE")" + + if [[ "$MODE" == "overwrite" ]]; then + printf '%s\n' "$CONTENT" > "$TARGET_FILE" + else + if [[ -s "$TARGET_FILE" ]]; then + printf '\n%s\n' "$CONTENT" >> "$TARGET_FILE" + else + printf '%s\n' "$CONTENT" >> "$TARGET_FILE" + fi + fi + + echo "Content injected into $TARGET_FILE (mode: $MODE)" + echo "target-file=$TARGET_FILE" >> "$GITHUB_OUTPUT"