From 3c3aa7a8ce825240e0b8c906f62661274eb88ddb Mon Sep 17 00:00:00 2001 From: Michael Seele Date: Mon, 8 Jun 2026 15:06:22 +0000 Subject: [PATCH 01/17] feat: add playwright actions with documentation --- .forgejo/workflows/tag-release.yml | 2 + README.md | 2 + playwright-merge/README.md | 39 +++++++++++ playwright-merge/action.yml | 104 +++++++++++++++++++++++++++++ playwright-run/README.md | 33 +++++++++ playwright-run/action.yml | 87 ++++++++++++++++++++++++ 6 files changed, 267 insertions(+) create mode 100644 playwright-merge/README.md create mode 100644 playwright-merge/action.yml create mode 100644 playwright-run/README.md create mode 100644 playwright-run/action.yml diff --git a/.forgejo/workflows/tag-release.yml b/.forgejo/workflows/tag-release.yml index 21f5c87..3bd09b0 100644 --- a/.forgejo/workflows/tag-release.yml +++ b/.forgejo/workflows/tag-release.yml @@ -24,6 +24,8 @@ on: - inject-content - maven-build - pnpm-build + - playwright-merge + - playwright-run - publish-static-contents - rust-build - terraform-apply diff --git a/README.md b/README.md index bfb6f69..cf223c2 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ Shared actions for Forgejo CI/CD pipelines. | [inject-content](inject-content) | Inject content into a file by appending or overwriting | | [maven-build](maven-build) | Action for building and validating Maven projects | | [pnpm-build](pnpm-build) | Action for building and validating with PNPM | +| [playwright-merge](playwright-merge) | Merge Playwright shard blob reports and publish consolidated reports | +| [playwright-run](playwright-run) | Run Playwright tests for one shard and upload its blob report | | [publish-static-contents](publish-static-contents) | Syncs frontend assets to S3 and invalidates a CloudFront distribution | | [rust-build](rust-build) | Set up Rust toolchain, run checks, and build via the project's build.sh | | [terraform-apply](terraform-apply) | Apply Terraform configuration files using the official Terraform CLI | diff --git a/playwright-merge/README.md b/playwright-merge/README.md new file mode 100644 index 0000000..fdc9845 --- /dev/null +++ b/playwright-merge/README.md @@ -0,0 +1,39 @@ +# playwright-merge + +Download all Playwright blob reports from shard jobs, merge them into a single HTML + JUnit report, and optionally upload the HTML report to S3. + +## Inputs + +| Input | Required | Default | Description | +|-------|----------|---------|-------------| +| `working-directory` | No | `.` | Directory containing `package.json` and `playwright.config.ts` | +| `node-version` | No | `24` | Node.js version | +| `pnpm-version` | No | `10.33` | pnpm version | +| `jfrog-token` | No | `""` | JFrog npm auth token | +| `role-arn` | Yes | — | IAM role ARN for AWS authentication | +| `aws-access-key-id` | Yes | — | AWS access key ID | +| `aws-secret-access-key` | Yes | — | AWS secret access key | +| `project-name` | Yes | — | Project name used as the folder in the report bucket (e.g. `hs-pricelist`) | +| `publish-test-reports` | No | `true` | Whether to upload the report to S3 and print the URL at `https://test-reports.schmalz.com` | + +## Usage + +```yaml +- uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/playwright-merge@playwright-merge-v1 + with: + working-directory: frontend + node-version: 22 + jfrog-token: ${{ secrets.JFROG_TOKEN }} + role-arn: arn:aws:iam::953815822701:role/deployment-role + aws-access-key-id: ${{ secrets.DB_STAGE_DEPLOYMENT_ACCESS_KEY }} + aws-secret-access-key: ${{ secrets.DB_STAGE_DEPLOYMENT_SECRET_ACCESS_KEY }} + project-name: hs-pricelist +``` + +## Notes + +- Intended as a follow-up job after all `playwright-run` shard jobs complete. +- Downloads shard artifacts into `all-blob-reports/` and merges them with `playwright merge-reports`. +- Generates HTML report in `playwright-report/` and JUnit XML in `test-results/junit.xml`. +- Uploads report files to `s3://com.schmalz.db.stage.test-reports/reports///` when `publish-test-reports` is `true`. +- Prints the final report URL on `https://test-reports.schmalz.com`. diff --git a/playwright-merge/action.yml b/playwright-merge/action.yml new file mode 100644 index 0000000..f7ae409 --- /dev/null +++ b/playwright-merge/action.yml @@ -0,0 +1,104 @@ +name: Playwright Merge +description: > + Download all blob reports from shard jobs, merge them into a single HTML + JUnit + report, upload the HTML report to S3, and upload the JUnit report as an artifact. + Call this in a follow-up job after all playwright-run shard jobs complete. + +inputs: + working-directory: + description: Directory containing package.json and playwright.config.ts + required: false + default: "." + node-version: + description: Node.js version + required: false + default: "24" + pnpm-version: + description: pnpm version + required: false + default: "10.33" + jfrog-token: + description: JFrog npm auth token + required: false + default: "" + role-arn: + description: IAM role ARN for AWS authentication + required: true + aws-access-key-id: + description: AWS access key ID + required: true + aws-secret-access-key: + description: AWS secret access key + required: true + project-name: + description: Project name used as the folder in the report bucket (e.g. hs-pricelist) + required: true + publish-test-reports: + description: Whether to upload the report to S3 and print the URL at https://test-reports.schmalz.com. Set to false to skip upload entirely. + required: false + default: "true" + +runs: + using: composite + steps: + - name: Install AWS CLI + shell: bash + run: | + if ! command -v aws &>/dev/null; then + curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o /tmp/awscliv2.zip + unzip -q /tmp/awscliv2.zip -d /tmp + sudo /tmp/aws/install + rm -rf /tmp/awscliv2.zip /tmp/aws + fi + + - name: Configure AWS + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/aws-configure@aws-configure-v1 + with: + role-arn: ${{ inputs.role-arn }} + aws-access-key-id: ${{ inputs.aws-access-key-id }} + aws-secret-access-key: ${{ inputs.aws-secret-access-key }} + + - name: Install dependencies + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/pnpm-build@pnpm-build-v1 + with: + working-directory: ${{ inputs.working-directory }} + node-version: ${{ inputs.node-version }} + pnpm-version: ${{ inputs.pnpm-version }} + jfrog-token: ${{ inputs.jfrog-token }} + run-scripts: "" + frozen-lockfile: "true" + check-dedupe: "false" + + - name: Download blob reports + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/download-artifact@download-artifact-v1 + with: + path: ${{ inputs.working-directory }}/all-blob-reports/ + merge-multiple: "true" + + - name: Merge blob reports + shell: bash + env: + CI: "true" + WORKING_DIR: ${{ inputs.working-directory }} + PLAYWRIGHT_JUNIT_OUTPUT_NAME: test-results/junit.xml + run: | + cd "${WORKING_DIR}" + pnpm exec playwright merge-reports \ + --reporter=html,junit \ + all-blob-reports/ + + - name: Upload report to S3 + if: ${{ inputs.publish-test-reports == 'true' }} + shell: bash + env: + WORKING_DIR: ${{ inputs.working-directory }} + PROJECT_NAME: ${{ inputs.project-name }} + run: | + TIMESTAMP=$(date +%s) + S3_BUCKET=com.schmalz.db.stage.test-reports + S3_PATH="s3://${S3_BUCKET}/reports/${PROJECT_NAME}/${TIMESTAMP}" + aws s3 sync "${WORKING_DIR}/playwright-report/" "${S3_PATH}/" + if [ -f "${WORKING_DIR}/test-results/junit.xml" ]; then + aws s3 cp "${WORKING_DIR}/test-results/junit.xml" "${S3_PATH}/junit.xml" + fi + echo "Report URL: https://test-reports.schmalz.com/reports/${PROJECT_NAME}/${TIMESTAMP}/index.html" diff --git a/playwright-run/README.md b/playwright-run/README.md new file mode 100644 index 0000000..825b354 --- /dev/null +++ b/playwright-run/README.md @@ -0,0 +1,33 @@ +# playwright-run + +Run Playwright E2E tests for one shard and upload the blob report as an artifact. + +## Inputs + +| Input | Required | Default | Description | +|-------|----------|---------|-------------| +| `working-directory` | No | `.` | Directory containing `package.json` and `playwright.config.ts` | +| `node-version` | No | `24` | Node.js version | +| `pnpm-version` | No | `10.33` | pnpm version | +| `jfrog-token` | No | `""` | JFrog npm auth token | +| `shard-index` | No | `1` | Current shard index (1-based). Set to `1` when not sharding. | +| `shard-total` | No | `1` | Total number of shards. Set to `1` to disable sharding. | +| `artifact-retention-days` | No | `3` | Number of days to retain the blob report artifact | + +## Usage + +```yaml +- uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/playwright-run@playwright-run-v1 + with: + working-directory: frontend + node-version: 22 + jfrog-token: ${{ secrets.JFROG_TOKEN }} + shard-index: ${{ matrix.shard-index }} + shard-total: 5 +``` + +## Notes + +- Intended for matrix shard jobs. +- Uploads one artifact per shard named `blob-report-`. +- Use `playwright-merge` in a follow-up job to merge shard reports. diff --git a/playwright-run/action.yml b/playwright-run/action.yml new file mode 100644 index 0000000..b07b29b --- /dev/null +++ b/playwright-run/action.yml @@ -0,0 +1,87 @@ +name: Playwright Run +description: > + Run Playwright E2E tests for one shard and upload the blob report as an artifact. + Call this from a matrix job. Use the playwright-merge action in a follow-up job + to produce the final HTML + JUnit report. + +inputs: + working-directory: + description: Directory containing package.json and playwright.config.ts + required: false + default: "." + node-version: + description: Node.js version + required: false + default: "24" + pnpm-version: + description: pnpm version + required: false + default: "10.33" + jfrog-token: + description: JFrog npm auth token + required: false + default: "" + shard-index: + description: Current shard index (1-based). Set to 1 when not sharding. + required: false + default: "1" + shard-total: + description: Total number of shards. Set to 1 to disable sharding. + required: false + default: "1" + artifact-retention-days: + description: Number of days to retain the blob report artifact + required: false + default: "3" + +runs: + using: composite + steps: + - name: Install dependencies + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/pnpm-build@pnpm-build-v1 + with: + working-directory: ${{ inputs.working-directory }} + node-version: ${{ inputs.node-version }} + pnpm-version: ${{ inputs.pnpm-version }} + jfrog-token: ${{ inputs.jfrog-token }} + run-scripts: "" + frozen-lockfile: "true" + check-dedupe: "false" + + - name: Cache Playwright browsers + id: playwright-cache + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/cache@cache-v1 + with: + path: ~/.cache/ms-playwright + key: ${{ runner.os }}-playwright-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: ${{ runner.os }}-playwright- + + - name: Install Playwright browsers + if: ${{ steps.playwright-cache.outputs.cache-hit != 'true' }} + shell: bash + env: + WORKING_DIR: ${{ inputs.working-directory }} + run: pnpm --prefix="${WORKING_DIR}" exec playwright install --with-deps + + - name: Run Playwright tests + shell: bash + env: + CI: "true" + WORKING_DIR: ${{ inputs.working-directory }} + SHARD_INDEX: ${{ inputs.shard-index }} + SHARD_TOTAL: ${{ inputs.shard-total }} + run: | + SHARD_ARG="" + if [ "${SHARD_TOTAL}" != "1" ]; then + SHARD_ARG="--shard=${SHARD_INDEX}/${SHARD_TOTAL}" + fi + pnpm --prefix="${WORKING_DIR}" exec playwright test ${SHARD_ARG} --reporter=blob,dot + + - name: Upload blob report + if: ${{ !cancelled() }} + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/upload-artifact@upload-artifact-v1 + with: + name: blob-report-${{ inputs.shard-index }} + path: ${{ inputs.working-directory }}/blob-report/ + retention-days: ${{ inputs.artifact-retention-days }} + if-no-files-found: ignore From b0f915be4c538e3ae71e40215ca403326bef53b0 Mon Sep 17 00:00:00 2001 From: Ruben Date: Tue, 9 Jun 2026 07:08:14 +0200 Subject: [PATCH 02/17] feat: add release note and webhook actions --- generate-release-notes/README.md | 39 +++++++++ generate-release-notes/action.yml | 92 ++++++++++++++++++++ publish-release-notes-via-webhook/README.md | 44 ++++++++++ publish-release-notes-via-webhook/action.yml | 41 +++++++++ 4 files changed, 216 insertions(+) create mode 100644 generate-release-notes/README.md create mode 100644 generate-release-notes/action.yml create mode 100644 publish-release-notes-via-webhook/README.md create mode 100644 publish-release-notes-via-webhook/action.yml diff --git a/generate-release-notes/README.md b/generate-release-notes/README.md new file mode 100644 index 0000000..37b5c3e --- /dev/null +++ b/generate-release-notes/README.md @@ -0,0 +1,39 @@ +# generate-release-notes + +Collects the git commit log between two refs and generates human-readable release notes using [Opencode](https://opencode.ai) with AWS Bedrock. + +## Inputs + +| Input | Required | Default | Description | +|-------|----------|---------|-------------| +| `bedrock-bearer-token` | Yes | — | AWS Bedrock bearer token for Opencode | +| `base-ref` | Yes | — | Base branch for git log comparison (e.g. `main` or `dev`) | +| `head-ref` | Yes | — | Head branch for git log comparison (e.g. `HEAD` or `dev`) | +| `section-title` | Yes | — | Title for the commits section in the generated markdown | +| `empty-message` | Yes | — | Message to include when no commits are found | +| `include-diff-stat` | No | `true` | Include a "Changed files" section with `git diff --stat` output | + +## Outputs + +| Output | Description | +|--------|-------------| +| `release-note` | The generated release notes as a markdown string | + +## Usage + +```yaml +- id: notes + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/generate-release-notes@generate-release-notes-v1 + with: + bedrock-bearer-token: ${{ secrets.BEDROCK_BEARER_TOKEN }} + base-ref: main + head-ref: HEAD + section-title: My Service + empty-message: No changes since last release. +``` + +## Notes + +- Requires the repository to be checked out with enough history for the comparison (use `fetch-depth: 0` in the `checkout` action). +- Release notes are generated in German and categorised into 💡 Features, 🪲 Bugfixes, and 🧹 Wartung based on conventional commit prefixes. +- The output can be passed directly to the `publish-release-notes-via-webhook` action via `${{ steps.notes.outputs.release-note }}`. diff --git a/generate-release-notes/action.yml b/generate-release-notes/action.yml new file mode 100644 index 0000000..3790f30 --- /dev/null +++ b/generate-release-notes/action.yml @@ -0,0 +1,92 @@ +name: Generate Release Notes +description: Collects git diff and generates release notes using GitHub Copilot CLI + +inputs: + bedrock-bearer-token: + description: AWS Bedrock Bearer token for Opencode + required: true + base-ref: + description: Base branch name for git log comparison (e.g. "dev" or "main") + required: true + head-ref: + description: Head branch name for git log comparison (e.g. "HEAD" or "dev") + required: true + section-title: + description: Title for the commits section in the generated markdown + required: true + empty-message: + description: Message to include when no commits are found + required: true + include-diff-stat: + description: Include a "Changed files" section with git diff --stat output + default: 'true' + +outputs: + release-note: + description: The generated release notes as a markdown string + value: ${{ steps.generate.outputs.release-note }} + +runs: + using: composite + steps: + - name: Collect diff + shell: bash + run: | + git fetch origin ${{ inputs.base-ref }} ${{ inputs.head-ref }} + + BASE_REF="origin/${{ inputs.base-ref }}" + HEAD_REF="${{ inputs.head-ref }}" + [[ "$HEAD_REF" != "HEAD" ]] && HEAD_REF="origin/$HEAD_REF" + + BRANCH_COMMITS=$(git log $BASE_REF..$HEAD_REF \ + --pretty=format:"- %h %s (%an, %ad)" \ + --date=short) + + { + echo "## ${{ inputs.section-title }}" + echo "" + echo "### Commits" + echo "" + if [ -z "$BRANCH_COMMITS" ]; then + echo "${{ inputs.empty-message }}" + else + echo "$BRANCH_COMMITS" + fi + } > commits.md + + if [ "${{ inputs.include-diff-stat }}" = "true" ]; then + DIFF_STAT=$(git diff --stat $BASE_REF...$HEAD_REF) + { + echo "" + echo "### Changed files" + echo "" + if [ -z "$DIFF_STAT" ]; then + echo "No file changes found." + else + echo "$DIFF_STAT" + fi + } >> commits.md + fi + + echo "--- commits.md ---" + cat commits.md + + - name: Write Copilot output to Markdown + id: generate + shell: bash + env: + AWS_BEARER_TOKEN_BEDROCK: ${{ inputs.bedrock-bearer-token }} + PROMPT: "Erstelle Release Notes auf Basis der folgenden Commit-Liste. Release Notes bestehen aus einer Aufzählung mit jeweils einem Aufzählungspunkt pro Änderung. Die Aufzählung wird eingeleitet mit \"Folgende Änderungen wurden in Betrieb genommen:\". Die Änderungen sind nach Art der Änderung sortiert. Es gibt 3 Kategorien: \"💡 Features\", \"🪲 Bugfixes\" und \"🧹 Wartung\". Zu welcher Kategorie eine Änderung gehört, hängt vom Präfix der zugehörigen Commitnachricht ab. Wenn es zu einer Kategorie keine Änderungen gibt, wird sie weggelassen. Am Anfang jedes Punkts steht eine kurze, fettgedruckte Zusammenfassung der Änderung. Danach steht eine sachliche Beschreibung der Änderung in ganzen Sätzen. Sie richtet sich an ein nicht technisches Publikum, das aber mit der Materie vertraut ist (Product Owner, UX Designer, Team Lead). Beschränke dich daher aufs Wesentliche und verschweige technische Einzelheiten. Vermeide Abkürzungen, wenn du deren Bedeutung kennst. Bevorzuge aber die englischen Fachbegriffe. Am Ende jeder Änderung erwähne in Klammern den Autor sowie die referenzierten Ticketnummern, sofern vorhanden. Jira Tickets sollen mit Link eingefügt werden: https://jira.schmalz.com/browse/" + run: | + curl -fsSL https://opencode.ai/install | bash + COMMITS=$(cat commits.md) + AWS_BEARER_TOKEN_BEDROCK=$AWS_BEARER_TOKEN_BEDROCK opencode run "$PROMPT $COMMITS" > release-notes.md + + echo "--- release-notes.md ---" + cat release-notes.md + + { + echo "release-note<> "$GITHUB_OUTPUT" diff --git a/publish-release-notes-via-webhook/README.md b/publish-release-notes-via-webhook/README.md new file mode 100644 index 0000000..59d40a4 --- /dev/null +++ b/publish-release-notes-via-webhook/README.md @@ -0,0 +1,44 @@ +# publish-release-notes-via-webhook + +Sends release notes to a Microsoft Teams channel via a Power Automate webhook. + +## Inputs + +| Input | Required | Default | Description | +|-------|----------|---------|-------------| +| `service-name` | Yes | — | Name of the service included in the webhook payload | +| `release-note` | Yes | — | Release notes markdown content to publish | +| `request-url` | Yes | — | Power Automate webhook URL | + +## Usage + +```yaml +- uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/publish-release-notes-via-webhook@publish-release-notes-via-webhook-v1 + with: + service-name: my-service + release-note: ${{ steps.notes.outputs.release-note }} + request-url: ${{ secrets.TEAMS_WEBHOOK_URL }} +``` + +## Webhook Payload + +The action sends a `POST` request with the following JSON body: + +```json +{ + "servicename": "my-service", + "releasenote": "Folgende Änderungen wurden in Betrieb genommen:\n..." +} +``` + +| Field | Type | Description | +|-------|------|-------------| +| `servicename` | string | Value of the `service-name` input | +| `releasenote` | string | Value of the `release-note` input (markdown) | + +The Power Automate flow must accept a `POST` request with `Content-Type: application/json` and handle both fields. + +## Notes + +- Designed to be used together with the `generate-release-notes` action, which exposes the `release-note` output. +- The webhook URL should be stored as a secret and never hardcoded in the workflow. diff --git a/publish-release-notes-via-webhook/action.yml b/publish-release-notes-via-webhook/action.yml new file mode 100644 index 0000000..830a770 --- /dev/null +++ b/publish-release-notes-via-webhook/action.yml @@ -0,0 +1,41 @@ +name: Publish Release Notes with Webhook +description: Sends generated release notes to a Teams webhook via Power Automate + +inputs: + service-name: + description: Name of the service for the webhook payload + required: true + release-note: + description: The release notes markdown content to publish + required: true + request-url: + description: Power Automate webhook URL + required: true + +runs: + using: composite + steps: + - name: Trigger Teams Webhook with release notes + shell: bash + env: + SERVICE_NAME: ${{ inputs.service-name }} + RELEASE_NOTE: ${{ inputs.release-note }} + REQUEST_URL: ${{ inputs.request-url }} + run: | + RELEASE_NOTE_CONTENT="$RELEASE_NOTE" + + WEBHOOK_PAYLOAD=$(jq -n \ + --arg servicename "$SERVICE_NAME" \ + --arg releasenote "$RELEASE_NOTE_CONTENT" \ + '{ + "servicename": ($servicename), + "releasenote": ($releasenote) + }') + + WEBHOOK_RESPONSE=$(curl -s -w "\n__HTTP_STATUS__:%{http_code}" -X POST \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + "$REQUEST_URL" \ + -d "$WEBHOOK_PAYLOAD") + + echo "Webhook response: $WEBHOOK_RESPONSE" From 801c7e224931fc193043927f3d0b60629f8f3ac5 Mon Sep 17 00:00:00 2001 From: Michael Seele Date: Thu, 11 Jun 2026 07:34:01 +0000 Subject: [PATCH 03/17] feat: add publish actions with documentation --- .forgejo/workflows/tag-release.yml | 2 + README.md | 2 + publish-npm-package/README.md | 28 +++++++++++++ publish-npm-package/action.yml | 64 ++++++++++++++++++++++++++++++ publish-rust-crate/README.md | 29 ++++++++++++++ publish-rust-crate/action.yml | 64 ++++++++++++++++++++++++++++++ 6 files changed, 189 insertions(+) create mode 100644 publish-npm-package/README.md create mode 100644 publish-npm-package/action.yml create mode 100644 publish-rust-crate/README.md create mode 100644 publish-rust-crate/action.yml diff --git a/.forgejo/workflows/tag-release.yml b/.forgejo/workflows/tag-release.yml index 3bd09b0..79c61b0 100644 --- a/.forgejo/workflows/tag-release.yml +++ b/.forgejo/workflows/tag-release.yml @@ -26,6 +26,8 @@ on: - pnpm-build - playwright-merge - playwright-run + - publish-npm-package + - publish-rust-crate - publish-static-contents - rust-build - terraform-apply diff --git a/README.md b/README.md index cf223c2..66f3ecf 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ Shared actions for Forgejo CI/CD pipelines. | [pnpm-build](pnpm-build) | Action for building and validating with PNPM | | [playwright-merge](playwright-merge) | Merge Playwright shard blob reports and publish consolidated reports | | [playwright-run](playwright-run) | Run Playwright tests for one shard and upload its blob report | +| [publish-npm-package](publish-npm-package) | Publish a PNPM package to JFrog Artifactory | +| [publish-rust-crate](publish-rust-crate) | Publish a Rust crate to JFrog Artifactory | | [publish-static-contents](publish-static-contents) | Syncs frontend assets to S3 and invalidates a CloudFront distribution | | [rust-build](rust-build) | Set up Rust toolchain, run checks, and build via the project's build.sh | | [terraform-apply](terraform-apply) | Apply Terraform configuration files using the official Terraform CLI | diff --git a/publish-npm-package/README.md b/publish-npm-package/README.md new file mode 100644 index 0000000..7411507 --- /dev/null +++ b/publish-npm-package/README.md @@ -0,0 +1,28 @@ +# publish-npm-package + +Publish a PNPM package to JFrog Artifactory. + +## Inputs + +| Input | Required | Default | Description | +|-------|----------|---------|-------------| +| `working-directory` | No | `.` | Directory containing `package.json` | +| `node-version` | No | `24` | Node.js version | +| `pnpm-version` | No | `10.33` | pnpm version | +| `jfrog-token` | Yes | — | JFrog npm auth token | +| `registry-url` | No | `https://schmalz.jfrog.io/artifactory/api/npm/default-npm/` | npm registry URL | + +## Usage + +```yaml +- uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/publish-npm-package@publish-npm-package-v1 + with: + working-directory: . + jfrog-token: ${{ secrets.JFROG_TOKEN }} +``` + +## Notes + +- Publishes with `pnpm publish`. +- Configures the registry auth token from `registry-url` and `jfrog-token`. +- Third-party actions used internally are pinned to exact commit SHAs to prevent supply chain attacks. diff --git a/publish-npm-package/action.yml b/publish-npm-package/action.yml new file mode 100644 index 0000000..69b8fa3 --- /dev/null +++ b/publish-npm-package/action.yml @@ -0,0 +1,64 @@ +name: publish-npm-package +description: Publish a PNPM package to JFrog Artifactory. + +inputs: + working-directory: + description: Directory containing package.json + required: false + default: "." + node-version: + description: Node.js version + required: false + default: "24" + pnpm-version: + description: pnpm version + required: false + default: "10.33" + jfrog-token: + description: JFrog npm auth token + required: true + registry-url: + description: npm registry URL + required: false + default: "https://schmalz.jfrog.io/artifactory/api/npm/default-npm/" + +runs: + using: composite + steps: + # Pinned to commit SHA instead of a tag to prevent supply chain attacks. + # actions/setup-node v4.4.0 — https://code.forgejo.org/actions/setup-node/commits/tag/v4.4.0 + - name: Setup Node + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 + with: + node-version: ${{ inputs.node-version }} + + # Pinned to commit SHA instead of a tag to prevent supply chain attacks. + # pnpm/action-setup v4.3.0 — https://code.forgejo.org/pnpm/action-setup/commits/tag/v4.3.0 + - name: Install pnpm + uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 + env: + # pnpm/action-setup bootstraps itself via npm before pnpm is available, + # so it must reach the public npm registry. + NPM_CONFIG_REGISTRY: https://registry.npmjs.org + with: + version: ${{ inputs.pnpm-version }} + + - name: Configure JFrog registry authentication + shell: bash + env: + JFROG_TOKEN: ${{ inputs.jfrog-token }} + REGISTRY_URL: ${{ inputs.registry-url }} + run: | + set -euo pipefail + + pnpm set registry "${REGISTRY_URL}" + + AUTHORITY="${REGISTRY_URL#https://}" + AUTHORITY="${AUTHORITY#http://}" + AUTHORITY="${AUTHORITY%/}" + pnpm set "//${AUTHORITY}/:_authToken" "${JFROG_TOKEN}" + + - name: Publish + shell: bash + working-directory: ${{ inputs.working-directory }} + run: pnpm publish diff --git a/publish-rust-crate/README.md b/publish-rust-crate/README.md new file mode 100644 index 0000000..69a44c2 --- /dev/null +++ b/publish-rust-crate/README.md @@ -0,0 +1,29 @@ +# publish-rust-crate + +Publish a Rust crate to JFrog Artifactory. + +## Inputs + +| Input | Required | Default | Description | +|-------|----------|---------|-------------| +| `working-directory` | No | `.` | Directory containing `Cargo.toml` | +| `rust-version` | No | `1.95.0` | Rust toolchain version | +| `jfrog-token` | Yes | — | JFrog token for the Artifactory Cargo registry | +| `registry-name` | No | `artifactory` | Cargo registry name | +| `registry-index` | No | `sparse+https://schmalz.jfrog.io/artifactory/api/cargo/schmalz-cargo-local/index/` | Cargo registry index URL | + +## Usage + +```yaml +- uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/publish-rust-crate@publish-rust-crate-v1 + with: + working-directory: . + jfrog-token: ${{ secrets.JFROG_TOKEN }} +``` + +## Notes + +- Configures Cargo registry settings in `${CARGO_HOME}/config.toml` and `${CARGO_HOME}/credentials.toml`. +- Falls back to `$HOME/.cargo` when `CARGO_HOME` is not set. +- Publishes with `cargo publish --registry `. +- Third-party actions used internally are pinned to exact commit SHAs to prevent supply chain attacks. diff --git a/publish-rust-crate/action.yml b/publish-rust-crate/action.yml new file mode 100644 index 0000000..11b26b3 --- /dev/null +++ b/publish-rust-crate/action.yml @@ -0,0 +1,64 @@ +name: publish-rust-crate +description: Publish a Rust crate to JFrog Artifactory. + +inputs: + working-directory: + description: Directory containing Cargo.toml + required: false + default: "." + rust-version: + description: Rust toolchain version + required: false + default: "1.95.0" + jfrog-token: + description: JFrog token for the Artifactory Cargo registry + required: true + registry-name: + description: Cargo registry name + required: false + default: artifactory + registry-index: + description: Cargo registry index URL + required: false + default: "sparse+https://schmalz.jfrog.io/artifactory/api/cargo/schmalz-cargo-local/index/" + +runs: + using: composite + steps: + # Pinned to commit SHA instead of a tag to prevent supply chain attacks. + # dtolnay/rust-toolchain v1 (2026-03-27) — https://github.com/dtolnay/rust-toolchain/commit/3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9 + - name: Setup Rust toolchain + uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9 + with: + toolchain: ${{ inputs.rust-version }} + + - name: Configure Cargo registry (JFrog Artifactory) + shell: bash + env: + JFROG_TOKEN: ${{ inputs.jfrog-token }} + REGISTRY_NAME: ${{ inputs.registry-name }} + REGISTRY_INDEX: ${{ inputs.registry-index }} + run: | + set -euo pipefail + + CARGO_HOME_DIR="${CARGO_HOME:-$HOME/.cargo}" + mkdir -p "${CARGO_HOME_DIR}" + + cat >> "${CARGO_HOME_DIR}/config.toml" <> "${CARGO_HOME_DIR}/credentials.toml" < Date: Mon, 15 Jun 2026 12:09:09 +0530 Subject: [PATCH 04/17] fix: create terraform workspaces automatically in shared actions --- terraform-apply/action.yml | 2 +- terraform-validate/action.yml | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/terraform-apply/action.yml b/terraform-apply/action.yml index 3776737..8d76de9 100644 --- a/terraform-apply/action.yml +++ b/terraform-apply/action.yml @@ -61,7 +61,7 @@ runs: TF_DIR: ${{ inputs.terraform-dir }} TF_WORKSPACE_NAME: ${{ inputs.workspace }} run: | - terraform -chdir="$TF_DIR" workspace select "$TF_WORKSPACE_NAME" + terraform -chdir="$TF_DIR" workspace select -or-create "$TF_WORKSPACE_NAME" - name: Terraform Apply shell: bash diff --git a/terraform-validate/action.yml b/terraform-validate/action.yml index 0fcde1f..b4389db 100644 --- a/terraform-validate/action.yml +++ b/terraform-validate/action.yml @@ -69,6 +69,15 @@ runs: TF_TOKEN_schmalz_jfrog_io: ${{ inputs.jfrog-token }} run: terraform -chdir=${{ env.TF_DIR }} init -backend=false -no-color + - name: Terraform Select Workspace + if: ${{ inputs.workspace != '' }} + shell: bash + env: + TF_DIR: ${{ inputs.terraform-dir }} + TF_WORKSPACE_NAME: ${{ inputs.workspace }} + run: | + terraform -chdir="$TF_DIR" workspace select -or-create "$TF_WORKSPACE_NAME" + - name: Terraform Format Check shell: bash env: From 36343e0a7903bc0ff96496c870bde5adb33b8bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6hringer?= Date: Mon, 15 Jun 2026 09:28:00 +0200 Subject: [PATCH 05/17] fix: revert workspace selection as validate does not initialize backend --- terraform-validate/action.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/terraform-validate/action.yml b/terraform-validate/action.yml index b4389db..0fcde1f 100644 --- a/terraform-validate/action.yml +++ b/terraform-validate/action.yml @@ -69,15 +69,6 @@ runs: TF_TOKEN_schmalz_jfrog_io: ${{ inputs.jfrog-token }} run: terraform -chdir=${{ env.TF_DIR }} init -backend=false -no-color - - name: Terraform Select Workspace - if: ${{ inputs.workspace != '' }} - shell: bash - env: - TF_DIR: ${{ inputs.terraform-dir }} - TF_WORKSPACE_NAME: ${{ inputs.workspace }} - run: | - terraform -chdir="$TF_DIR" workspace select -or-create "$TF_WORKSPACE_NAME" - - name: Terraform Format Check shell: bash env: From 5b6f2cfd289b2345339b91f05e827630791e6533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6hringer?= Date: Tue, 16 Jun 2026 13:33:16 +0200 Subject: [PATCH 06/17] feat: create deploy-esb action --- .forgejo/workflows/tag-release.yml | 1 + esb-deploy/README.md | 30 +++++++++++++++ esb-deploy/action.yml | 60 ++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 esb-deploy/README.md create mode 100644 esb-deploy/action.yml diff --git a/.forgejo/workflows/tag-release.yml b/.forgejo/workflows/tag-release.yml index 79c61b0..f17834c 100644 --- a/.forgejo/workflows/tag-release.yml +++ b/.forgejo/workflows/tag-release.yml @@ -18,6 +18,7 @@ on: - aws-configure - cache - checkout + - deploy-esb - download-artifact - helm-deploy - i18n-sync diff --git a/esb-deploy/README.md b/esb-deploy/README.md new file mode 100644 index 0000000..1b761ac --- /dev/null +++ b/esb-deploy/README.md @@ -0,0 +1,30 @@ +# esb-deploy + +Deploy a service to an ESB docker host. + +## Inputs + +| Input | Required | Default | Description | +|-------|----------|---------|-------------| +| `docker-host` | Yes | - | esbdb3.schmalzgroup.net, esbdb4.schmalzgroup.net, esbdb2-stage.schmalzgroup.net| +| `java-version` | Yes | 25 | Same as default of the maven-build action | +| `maven-profile` | No | `test` | Maven profile to activate during deploy | +| `maven-settings` | **Yes** | — | Secret containing the `settings.xml` content used for repository authentication | +| `service-name` | Yes | — | Name of the service to deploy | + +## Usage + +```yaml +- uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/esb-deploy@esb-deploy-v1 + with: + service-name: my-service + docker-host: esbdocker2-stage.schmalzgroup.net + java-version: 8 + maven-profile: test + maven-settings: ${{ secrets.MAVEN_SETTINGS }} +``` + +## Notes + +- The compose files are extracted from variables. They can be provided on the organization or repository level. +- The action uses the maven-build action to build the service. The pom.xml has to be in the root directory diff --git a/esb-deploy/action.yml b/esb-deploy/action.yml new file mode 100644 index 0000000..96a6593 --- /dev/null +++ b/esb-deploy/action.yml @@ -0,0 +1,60 @@ +name: Deploy ESB +description: Deploy a service to an ESB docker host. + +inputs: + docker-host: + description: Docker host to deploy to + required: true + maven-profile: + required: false + default: 'test' + description: 'Maven profile to use for the build' + maven-settings: + description: Secret containing the settings.xml content used for repository authentication + required: true + java-version: + description: Java version to use for the build + required: true + service: + description: Name of the service to deploy + required: false + default: 'true' + +runs: + using: composite + steps: + - name: Create compose files + shell: bash + env: + BASE_COMPOSE: ${{ vars.DOCKER_COMPOSE }} + SU_COMPOSE: ${{ vars.DOCKER_COMPOSE_SU }} + run: | + printf '%s\n' "$BASE_COMPOSE" > compose.yml + printf '%s\n' "$SU_COMPOSE" > compose-su.yml + + - uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/maven-build@maven-build-v1 + with: + phase: verify + maven-settings: ${{ inputs.maven-settings }} + verify-goals: clean package + java-version: ${{ inputs.java-version }} + + - name: Compose stage + if: ${{ inputs.stage == 'true' }} + shell: bash + env: + SERVICE: ${{ inputs.service }} + run: | + echo "Deploying $SERVICE to stage environment" + export DOCKER_HOST="tcp://${{ inputs.docker-host }}:2375" + docker compose -f compose.yml -f compose-su.yml up -d --build --no-deps "$SERVICE" + + - name: Compose prod + if: ${{ inputs.stage != 'true' }} + shell: bash + env: + SERVICE: ${{ inputs.service }} + run: | + echo "Deploying $SERVICE to production environment" + export DOCKER_HOST="tcp://${{ inputs.docker-host }}:2375" + docker compose -f compose.yml up -d --build --no-deps "$SERVICE" From 4e15383d233328604bbd4c37d9dc737d9784e165 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6hringer?= Date: Tue, 16 Jun 2026 16:25:43 +0200 Subject: [PATCH 07/17] fix: use correct name in tag-release workflow --- .forgejo/workflows/tag-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/tag-release.yml b/.forgejo/workflows/tag-release.yml index f17834c..428ec72 100644 --- a/.forgejo/workflows/tag-release.yml +++ b/.forgejo/workflows/tag-release.yml @@ -18,8 +18,8 @@ on: - aws-configure - cache - checkout - - deploy-esb - download-artifact + - esb-deploy - helm-deploy - i18n-sync - inject-content From 115300a7e1614eaee4fc5d40ac7baf6e151ce73b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6hringer?= Date: Tue, 16 Jun 2026 16:32:34 +0200 Subject: [PATCH 08/17] fix: readme mentioned wrong parameters --- esb-deploy/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esb-deploy/README.md b/esb-deploy/README.md index 1b761ac..51eae81 100644 --- a/esb-deploy/README.md +++ b/esb-deploy/README.md @@ -10,14 +10,14 @@ Deploy a service to an ESB docker host. | `java-version` | Yes | 25 | Same as default of the maven-build action | | `maven-profile` | No | `test` | Maven profile to activate during deploy | | `maven-settings` | **Yes** | — | Secret containing the `settings.xml` content used for repository authentication | -| `service-name` | Yes | — | Name of the service to deploy | +| `service` | Yes | — | Name of the service to deploy | ## Usage ```yaml - uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/esb-deploy@esb-deploy-v1 with: - service-name: my-service + service: my-service docker-host: esbdocker2-stage.schmalzgroup.net java-version: 8 maven-profile: test From 0134da8ac7cab452a944bfd3abe25487739952cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6hringer?= Date: Wed, 17 Jun 2026 07:42:35 +0200 Subject: [PATCH 09/17] fix: propagate maven profile in esb-deploy action --- esb-deploy/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/esb-deploy/action.yml b/esb-deploy/action.yml index 96a6593..c8fd97f 100644 --- a/esb-deploy/action.yml +++ b/esb-deploy/action.yml @@ -38,6 +38,7 @@ runs: maven-settings: ${{ inputs.maven-settings }} verify-goals: clean package java-version: ${{ inputs.java-version }} + maven-profile: ${{ inputs.maven-profile}} - name: Compose stage if: ${{ inputs.stage == 'true' }} From 91494155758370e2731738b33ed27543e9113989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6hringer?= Date: Wed, 17 Jun 2026 08:01:38 +0200 Subject: [PATCH 10/17] fix: action did not provide stage toggle --- esb-deploy/README.md | 2 ++ esb-deploy/action.yml | 3 +++ 2 files changed, 5 insertions(+) diff --git a/esb-deploy/README.md b/esb-deploy/README.md index 51eae81..ae02466 100644 --- a/esb-deploy/README.md +++ b/esb-deploy/README.md @@ -11,6 +11,7 @@ Deploy a service to an ESB docker host. | `maven-profile` | No | `test` | Maven profile to activate during deploy | | `maven-settings` | **Yes** | — | Secret containing the `settings.xml` content used for repository authentication | | `service` | Yes | — | Name of the service to deploy | +| `stage` | No | true | If true this is a stage deployment | ## Usage @@ -22,6 +23,7 @@ Deploy a service to an ESB docker host. java-version: 8 maven-profile: test maven-settings: ${{ secrets.MAVEN_SETTINGS }} + stage: true ``` ## Notes diff --git a/esb-deploy/action.yml b/esb-deploy/action.yml index c8fd97f..584274e 100644 --- a/esb-deploy/action.yml +++ b/esb-deploy/action.yml @@ -17,6 +17,9 @@ inputs: required: true service: description: Name of the service to deploy + required: true + stage: + description: Whether to deploy to stage environment (true) or production environment (false) required: false default: 'true' From a49611f28806801b87e0d31dd13ab949b5fae7d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6hringer?= Date: Wed, 17 Jun 2026 08:52:37 +0200 Subject: [PATCH 11/17] fix: maven action did not set profile in verify mode --- maven-build/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/maven-build/action.yml b/maven-build/action.yml index 961bc28..1c9b161 100644 --- a/maven-build/action.yml +++ b/maven-build/action.yml @@ -97,6 +97,7 @@ runs: run: | mvn --batch-mode $VERIFY_GOALS \ -s /tmp/maven-settings.xml \ + -P "$MAVEN_PROFILE" \ $EXTRA_ARGS - name: Deploy From 9783972537edc63ff438168f5c4348148512b4b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6hringer?= Date: Wed, 17 Jun 2026 09:41:57 +0200 Subject: [PATCH 12/17] fix: actually provide maven profile --- maven-build/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/maven-build/action.yml b/maven-build/action.yml index 1c9b161..6b16ded 100644 --- a/maven-build/action.yml +++ b/maven-build/action.yml @@ -94,6 +94,7 @@ runs: env: VERIFY_GOALS: ${{ inputs.verify-goals }} EXTRA_ARGS: ${{ inputs.extra-args }} + MAVEN_PROFILE: ${{ inputs.maven-profile }} run: | mvn --batch-mode $VERIFY_GOALS \ -s /tmp/maven-settings.xml \ From 298cf5c375786e42944ac90487b6160402ce6771 Mon Sep 17 00:00:00 2001 From: DMI Date: Wed, 24 Jun 2026 10:01:11 +0000 Subject: [PATCH 13/17] feat: add `no-deps` and `projects` inputs to `playwright-run` action and adjust readme to include a basic and a sharded example --- playwright-run/README.md | 35 ++++++++++++++++++++++++++++++++--- playwright-run/action.yml | 23 ++++++++++++++++++++++- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/playwright-run/README.md b/playwright-run/README.md index 825b354..570a9ac 100644 --- a/playwright-run/README.md +++ b/playwright-run/README.md @@ -12,18 +12,47 @@ Run Playwright E2E tests for one shard and upload the blob report as an artifact | `jfrog-token` | No | `""` | JFrog npm auth token | | `shard-index` | No | `1` | Current shard index (1-based). Set to `1` when not sharding. | | `shard-total` | No | `1` | Total number of shards. Set to `1` to disable sharding. | +| `no-deps` | No | `false` | Skip dependencies between Playwright projects (e.g. setup/teardown). Passes `--no-deps` to Playwright. | +| `projects` | No | `""` | Comma-separated list of Playwright projects to run (e.g. `chromium,firefox,Mobile Chrome`). Leave empty to use the Playwright default. | | `artifact-retention-days` | No | `3` | Number of days to retain the blob report artifact | ## Usage +### Basic + ```yaml - uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/playwright-run@playwright-run-v1 with: - working-directory: frontend + working-directory: e2e node-version: 22 jfrog-token: ${{ secrets.JFROG_TOKEN }} - shard-index: ${{ matrix.shard-index }} - shard-total: 5 +``` + +### Sharded + +```yaml +jobs: + test: + name: "Test Shard ${{ matrix.shard-index }}/${{ matrix.total }}" + # Define the matrix strategy on the parent job: + strategy: + fail-fast: false + matrix: + total: [5] # The same for all instances + shard-index: [1, 2, 3, 4, 5] + steps: + # ...other steps like checkout repo etc. + - name: Run tests + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/playwright-run@playwright-run-v1 + with: + working-directory: frontend + node-version: 22 + jfrog-token: ${{ secrets.JFROG_TOKEN }} + # Matrix data is passed here: + shard-index: ${{ matrix.shard-index }} + shard-total: ${{ matrix.total }} + no-deps: "true" + projects: "chromium,firefox,webkit,Mobile Chrome,Mobile Safari" ``` ## Notes diff --git a/playwright-run/action.yml b/playwright-run/action.yml index b07b29b..f521fdd 100644 --- a/playwright-run/action.yml +++ b/playwright-run/action.yml @@ -29,6 +29,14 @@ inputs: description: Total number of shards. Set to 1 to disable sharding. required: false default: "1" + no-deps: + description: Whether to ignore dependencies between Playwright projects (e.g. setup, teardown) + required: false + default: false + projects: + description: Comma-separated list of Playwright projects to include, leave empty to use the Playwright default + required: false + default: "" artifact-retention-days: description: Number of days to retain the blob report artifact required: false @@ -70,12 +78,25 @@ runs: WORKING_DIR: ${{ inputs.working-directory }} SHARD_INDEX: ${{ inputs.shard-index }} SHARD_TOTAL: ${{ inputs.shard-total }} + NO_DEPS: ${{ inputs.no-deps }} + PROJECTS: ${{ inputs.projects }} run: | SHARD_ARG="" if [ "${SHARD_TOTAL}" != "1" ]; then SHARD_ARG="--shard=${SHARD_INDEX}/${SHARD_TOTAL}" fi - pnpm --prefix="${WORKING_DIR}" exec playwright test ${SHARD_ARG} --reporter=blob,dot + NO_DEPS_ARG="" + if [ "${NO_DEPS}" == "true" ]; then + NO_DEPS_ARG="--no-deps" + fi + PROJECTS_ARG=() + if [ -n "${PROJECTS}" ]; then + IFS=',' read -ra PROJECT_LIST <<< "${PROJECTS}" + for project in "${PROJECT_LIST[@]}"; do + PROJECTS_ARG+=("--project=${project}") + done + fi + pnpm --prefix="${WORKING_DIR}" exec playwright test ${SHARD_ARG} ${NO_DEPS_ARG} "${PROJECTS_ARG[@]}" --reporter=blob,dot - name: Upload blob report if: ${{ !cancelled() }} From 0ac9047080231277dc35fbc0447c3720975a46e8 Mon Sep 17 00:00:00 2001 From: OmkarSingad Date: Wed, 24 Jun 2026 09:36:41 +0000 Subject: [PATCH 14/17] feat: add terraform-plan action --- .forgejo/workflows/tag-release.yml | 1 + README.md | 1 + terraform-plan/README.md | 47 +++++++++++++++++ terraform-plan/action.yml | 82 ++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 terraform-plan/README.md create mode 100644 terraform-plan/action.yml diff --git a/.forgejo/workflows/tag-release.yml b/.forgejo/workflows/tag-release.yml index 428ec72..3ed1f31 100644 --- a/.forgejo/workflows/tag-release.yml +++ b/.forgejo/workflows/tag-release.yml @@ -32,6 +32,7 @@ on: - publish-static-contents - rust-build - terraform-apply + - terraform-plan - terraform-validate - upload-artifact - vacuum-lint diff --git a/README.md b/README.md index 66f3ecf..63d8d37 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ Shared actions for Forgejo CI/CD pipelines. | [terraform-validate](terraform-validate) | Validate Terraform configuration files using the official Terraform CLI | | [upload-artifact](upload-artifact) | Upload files as a Forgejo Actions artifact | | [vacuum-lint](vacuum-lint) | Validate and lint OpenAPI specifications using Vacuum | +| [terraform-plan](terraform-plan) | Preview Terraform infrastructure changes (create, update, delete, replace) without applying them | ## Security diff --git a/terraform-plan/README.md b/terraform-plan/README.md new file mode 100644 index 0000000..5b48915 --- /dev/null +++ b/terraform-plan/README.md @@ -0,0 +1,47 @@ +# terraform-plan + +Plan Terraform configuration files using the official Terraform CLI. + +## Inputs + +| Input | Required | Default | Description | +|-------|----------|---------|-------------| +| `terraform-dir` | No | `terraform` | Directory containing `.tf` files | +| `terraform-version` | No | `~1.15` | Terraform version to use | +| `var-file` | No | `""` | Path to `.tfvars` file, relative to `terraform-dir` | +| `workspace` | No | `""` | Terraform workspace to select | +| `jfrog-token` | No | `""` | JFrog Artifactory token for the Terraform provider registry (`TF_TOKEN_schmalz_jfrog_io`) | + +## Outputs + +No outputs are exported. + +Terraform `plan` only previews changes and does not produce finalized output values in state. + +## Usage + +```yaml +- uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/terraform-plan@terraform-plan-v1 + id: tf-plan + with: + workspace: stage + var-file: stage.tfvars + jfrog-token: ${{ secrets.JFROG_TOKEN }} +`` + + +## Notes + +- Runs `terraform init`, selects the workspace according to PR, and executes `terraform plan`. +- Does **not** apply any changes — it only previews what Terraform would do. +- Helps identify infrastructure changes before execution, such as: + - Resources that will be created + - Resources that will be updated + - Resources that will be *deleted* + - Resources that will be replaced +- Useful for reviewing changes in environments. +- Helps detect unexpected changes caused by provider version updates, module updates, variable changes, or Terraform configuration changes. +- Improves deployment safety by showing the impact of changes before `terraform apply`. +- Sets `TF_TOKEN_schmalz_jfrog_io` on both `init` and `plan` steps if `jfrog-token` is provided. +- If `var-file` is provided, it is passed as `-var-file` to the plan command. +- Commonly used in CI for pre-apply visibility, especially in pull requests or staging validation workflows. \ No newline at end of file diff --git a/terraform-plan/action.yml b/terraform-plan/action.yml new file mode 100644 index 0000000..dda70f9 --- /dev/null +++ b/terraform-plan/action.yml @@ -0,0 +1,82 @@ +name: Terraform Plan +description: > + Init and plan Terraform configuration files using the official Terraform CLI. + +inputs: + terraform-dir: + description: Directory containing .tf files + required: false + default: terraform + terraform-version: + description: Terraform version to use + required: false + default: "~1.15" + var-file: + description: Path to .tfvars file, relative to terraform-dir + required: false + default: "" + workspace: + description: Terraform workspace to use + required: false + default: "" + jfrog-token: + description: JFrog Artifactory token used for Terraform provider registry (sets TF_TOKEN_schmalz_jfrog_io) + required: false + default: "" + +runs: + using: composite + steps: + # Pinned to commit SHA instead of a tag to prevent supply chain attacks. + # hashicorp/setup-terraform v4.0.0 — https://github.com/hashicorp/setup-terraform/commits/v4.0.0/ + - name: Setup Terraform + uses: hashicorp/setup-terraform@5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 + with: + terraform_version: ${{ inputs.terraform-version }} + + # Plugin cache setup + - name: Set Terraform plugin cache directory + shell: bash + run: | + mkdir -p ~/.terraform.d/plugin-cache + echo "TF_PLUGIN_CACHE_DIR=$HOME/.terraform.d/plugin-cache" >> "$GITHUB_ENV" + + # Cache providers + - name: Cache Terraform providers + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/cache@cache-v1 + with: + path: ~/.terraform.d/plugin-cache + key: ${{ runner.os }}-terraform-providers-${{ inputs.terraform-version }}-${{ hashFiles(format('{0}/.terraform.lock.hcl', inputs.terraform-dir)) }} + restore-keys: ${{ runner.os }}-terraform-providers-${{ inputs.terraform-version }}- + + # Init (backend enabled) + - name: Terraform Init + shell: bash + env: + TF_TOKEN_schmalz_jfrog_io: ${{ inputs.jfrog-token }} + TF_DIR: ${{ inputs.terraform-dir }} + run: terraform -chdir="$TF_DIR" init -no-color + + # Workspace selection + - name: Terraform Select Workspace + if: ${{ inputs.workspace != '' }} + shell: bash + env: + TF_DIR: ${{ inputs.terraform-dir }} + TF_WORKSPACE_NAME: ${{ inputs.workspace }} + run: | + terraform -chdir="$TF_DIR" workspace select -or-create "$TF_WORKSPACE_NAME" + + # Plan step + - name: Terraform Plan + shell: bash + env: + TF_TOKEN_schmalz_jfrog_io: ${{ inputs.jfrog-token }} + TF_DIR: ${{ inputs.terraform-dir }} + VAR_FILE: ${{ inputs.var-file }} + run: | + ARGS="-no-color" + if [ -n "$VAR_FILE" ]; then + ARGS="$ARGS -var-file=$VAR_FILE" + fi + terraform -chdir="$TF_DIR" plan $ARGS From 4d9b2459a4d22349342ee385096ea2a9d780472b Mon Sep 17 00:00:00 2001 From: Marcel Frey Date: Thu, 25 Jun 2026 10:40:28 +0000 Subject: [PATCH 15/17] feat: add `aws-lambda-alias-update` and `aws-lambda-wait-for-provisioned-concurrency` actions --- README.md | 6 +- aws-lambda-alias-update/README.md | 84 ++++++++++++++++++ aws-lambda-alias-update/action.yml | 49 +++++++++++ .../README.md | 86 +++++++++++++++++++ .../action.yml | 64 ++++++++++++++ 5 files changed, 287 insertions(+), 2 deletions(-) create mode 100644 aws-lambda-alias-update/README.md create mode 100644 aws-lambda-alias-update/action.yml create mode 100644 aws-lambda-wait-for-provisioned-concurrency/README.md create mode 100644 aws-lambda-wait-for-provisioned-concurrency/action.yml diff --git a/README.md b/README.md index 63d8d37..755d459 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ Shared actions for Forgejo CI/CD pipelines. | [aikido-full-scan](aikido-full-scan) | Aikido full scan | | [aikido-pr-scan](aikido-pr-scan) | Aikido PR scan | | [aws-configure](aws-configure) | Authenticate with AWS via OIDC | +| [aws-lambda-alias-update](aws-lambda-alias-update) | Update Aliases of Lambda Functions to a new Version | +| [aws-lambda-wait-for-provisioned-concurrency](aws-lambda-wait-for-provisioned-concurrency) | Wait until the Provisioned Concurrency is Ready for Lambda Functions | | [cache](cache) | Cache files between workflow runs | | [checkout](checkout) | Action for checking out a repository | | [download-artifact](download-artifact) | Download Forgejo Actions artifacts by name or pattern | @@ -16,18 +18,18 @@ Shared actions for Forgejo CI/CD pipelines. | [i18n-sync](i18n-sync) | Fetch translations from i18n.schmalz.com and open a pull request | | [inject-content](inject-content) | Inject content into a file by appending or overwriting | | [maven-build](maven-build) | Action for building and validating Maven projects | -| [pnpm-build](pnpm-build) | Action for building and validating with PNPM | | [playwright-merge](playwright-merge) | Merge Playwright shard blob reports and publish consolidated reports | | [playwright-run](playwright-run) | Run Playwright tests for one shard and upload its blob report | +| [pnpm-build](pnpm-build) | Action for building and validating with PNPM | | [publish-npm-package](publish-npm-package) | Publish a PNPM package to JFrog Artifactory | | [publish-rust-crate](publish-rust-crate) | Publish a Rust crate to JFrog Artifactory | | [publish-static-contents](publish-static-contents) | Syncs frontend assets to S3 and invalidates a CloudFront distribution | | [rust-build](rust-build) | Set up Rust toolchain, run checks, and build via the project's build.sh | | [terraform-apply](terraform-apply) | Apply Terraform configuration files using the official Terraform CLI | +| [terraform-plan](terraform-plan) | Preview Terraform infrastructure changes (create, update, delete, replace) without applying them | | [terraform-validate](terraform-validate) | Validate Terraform configuration files using the official Terraform CLI | | [upload-artifact](upload-artifact) | Upload files as a Forgejo Actions artifact | | [vacuum-lint](vacuum-lint) | Validate and lint OpenAPI specifications using Vacuum | -| [terraform-plan](terraform-plan) | Preview Terraform infrastructure changes (create, update, delete, replace) without applying them | ## Security diff --git a/aws-lambda-alias-update/README.md b/aws-lambda-alias-update/README.md new file mode 100644 index 0000000..26d2647 --- /dev/null +++ b/aws-lambda-alias-update/README.md @@ -0,0 +1,84 @@ +# aws-lambda-alias-update + +Composite action that updates Lambda function aliases from a Terraform output. Iterates over the `lambda_alias_updates` Terraform output and calls `aws lambda update-alias` for each entry. + +**Example `lambda-alias-updates` input:** + +```json +[ + "{\"alias_name\": \"live\", \"function_name\": \"my-get-product\", \"version\": \"42\"}", + "{\"alias_name\": \"live\", \"function_name\": \"my-get-category\", \"version\": \"7\"}" +] +``` + +## Inputs + +| Input | Required | Default | Description | +|-------|----------|---------|-------------| +| `lambda-alias-updates` | Yes | — | JSON array of Lambda alias update objects (Terraform output: `lambda_alias_updates`). Each element is a JSON-encoded string with `alias_name`, `function_name`, and `version`. | + +## Usage + +```yaml +- name: Update Lambda Aliases + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/aws-lambda-alias-update@aws-lambda-alias-update-v1 + with: + lambda-alias-updates: ${{ steps.tf-apply.outputs.lambda_alias_updates }} +``` + +## Terraform Setup + +- Add the following content to the project +- Add all Lambda Modules to the `provisioned_lambda_modules` list for which the Function Alias and/or Provisioned Concurrency should be updated + +**`output.tf`** +```tf +locals { + // List of Lambda Modules that have provisioned concurrency configured. + // Required to update the aliases of these functions after deployment. + provisioned_lambda_modules = [ + module.lambda_get_category, + module.lambda_product_get_full_slug, + module.lambda_get_product, + ] +} + +// Output which allows Updates of Lambda Alias and Provisioned Concurrency +output "lambda_alias_updates" { + value = concat([for module in local.provisioned_lambda_modules : "{\"alias_name\": \"${module.lambda_alias_name}\", \"function_name\": \"${module.lambda_name}\", \"version\": \"${module.lambda_version}\" }"]) +} + +``` + +## Example Usage with other Shared Actions + +```yml +jobs: + deploy-stage: + name: Build and Deploy to Stage + runs-on: stackit-ubuntu-22 + steps: + - name: Apply Terraform + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/terraform-apply@terraform-apply-v1 + id: tf-apply + with: + terraform-version: 1.14.9 + workspace: stage + var-file: stage.tfvars + jfrog-token: ${{ secrets.JFROG_TOKEN }} + + - name: Update Lambda Aliases + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/aws-lambda-alias-update@aws-lambda-alias-update-v1 + with: + lambda-alias-updates: ${{ steps.tf-apply.outputs.lambda_alias_updates }} + + - name: Wait for Lambda Provisioned Concurrency + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/aws-lambda-wait-for-provisioned-concurrency@aws-lambda-wait-for-provisioned-concurrency-v1 + with: + lambda-alias-updates: ${{ steps.tf-apply.outputs.lambda_alias_updates }} +``` + +## Notes + +- Expects the `lambda-alias-updates` input to be the raw `lambda_alias_updates` output from the `terraform-apply` action. +- Requires AWS credentials to be configured in the job before this step runs. diff --git a/aws-lambda-alias-update/action.yml b/aws-lambda-alias-update/action.yml new file mode 100644 index 0000000..42f632f --- /dev/null +++ b/aws-lambda-alias-update/action.yml @@ -0,0 +1,49 @@ +name: "AWS Lambda - Update Alias" +description: > + Updates Lambda function aliases from a Terraform output. + Iterates over the lambda_alias_updates Terraform output and calls + aws lambda update-alias for each entry. + +inputs: + lambda-alias-updates: + description: > + JSON array of Lambda alias update objects (Terraform output: lambda_alias_updates). + Each element is a JSON-encoded string with alias_name, function_name, and version. + required: true + +runs: + using: "composite" + steps: + - name: Install AWS CLI + shell: bash + run: | + if ! command -v aws &> /dev/null; then + curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o /tmp/awscliv2.zip + unzip -q /tmp/awscliv2.zip -d /tmp + sudo /tmp/aws/install + rm -rf /tmp/awscliv2.zip /tmp/aws + fi + + - name: Install jq if missing + shell: bash + run: | + set -euo pipefail + command -v jq >/dev/null 2>&1 || sudo apt-get install -y --no-install-recommends jq + + - name: Update Lambda Aliases + shell: bash + env: + LAMBDA_ALIAS_UPDATES: ${{ inputs.lambda-alias-updates }} + run: | + echo "$LAMBDA_ALIAS_UPDATES" | jq -c '.[] | fromjson' | while IFS= read -r entry; do + alias_name=$(echo "$entry" | jq -r '.alias_name') + function_name=$(echo "$entry" | jq -r '.function_name') + version=$(echo "$entry" | jq -r '.version') + echo "Updating alias '$alias_name' for '$function_name' to version '$version'" + aws lambda update-alias \ + --no-cli-pager \ + --name "$alias_name" \ + --function-name "$function_name" \ + --function-version "$version" + echo "Updated alias '$alias_name' for '$function_name' to version '$version'" + done diff --git a/aws-lambda-wait-for-provisioned-concurrency/README.md b/aws-lambda-wait-for-provisioned-concurrency/README.md new file mode 100644 index 0000000..2efbbc3 --- /dev/null +++ b/aws-lambda-wait-for-provisioned-concurrency/README.md @@ -0,0 +1,86 @@ +# aws-lambda-wait-for-provisioned-concurrency + +Composite action that waits for provisioned concurrency to reach `READY` status for all Lambda functions listed in the Terraform `lambda_alias_updates` output. Iterates over the `lambda_alias_updates` Terraform output and polls `aws lambda get-provisioned-concurrency-config` for each entry until the status is `READY` or `FAILED`. + +**Example `lambda-alias-updates` input:** + +```json +[ + "{\"alias_name\": \"live\", \"function_name\": \"my-get-product\", \"version\": \"42\"}", + "{\"alias_name\": \"live\", \"function_name\": \"my-get-category\", \"version\": \"7\"}" +] +``` + +## Inputs + +| Input | Required | Default | Description | +|-------|----------|---------|-------------| +| `lambda-alias-updates` | Yes | — | JSON array of Lambda alias update objects (Terraform output: `lambda_alias_updates`). Each element is a JSON-encoded string with `alias_name`, `function_name`, and `version`. | + +## Usage + +```yaml +- name: Wait for Lambda Provisioned Concurrency + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/aws-lambda-wait-for-provisioned-concurrency@aws-lambda-wait-for-provisioned-concurrency-v1 + with: + lambda-alias-updates: ${{ steps.tf-apply.outputs.lambda_alias_updates }} +``` + +## Terraform Setup + +- Add the following content to the project +- Add all Lambda Modules to the `provisioned_lambda_modules` list for which the Function Alias and/or Provisioned Concurrency should be updated + +**`output.tf`** +```tf +locals { + // List of Lambda Modules that have provisioned concurrency configured. + // Required to update the aliases of these functions after deployment. + provisioned_lambda_modules = [ + module.lambda_get_category, + module.lambda_product_get_full_slug, + module.lambda_get_product, + ] +} + +// Output which allows Updates of Lambda Alias and Provisioned Concurrency +output "lambda_alias_updates" { + value = concat([for module in local.provisioned_lambda_modules : "{\"alias_name\": \"${module.lambda_alias_name}\", \"function_name\": \"${module.lambda_name}\", \"version\": \"${module.lambda_version}\" }"]) +} + +``` + +## Example Usage with other Shared Actions + +```yml +jobs: + deploy-stage: + name: Build and Deploy to Stage + runs-on: stackit-ubuntu-22 + steps: + - name: Apply Terraform + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/terraform-apply@terraform-apply-v1 + id: tf-apply + with: + terraform-version: 1.14.9 + workspace: stage + var-file: stage.tfvars + jfrog-token: ${{ secrets.JFROG_TOKEN }} + + - name: Update Lambda Aliases + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/aws-lambda-alias-update@aws-lambda-alias-update-v1 + with: + lambda-alias-updates: ${{ steps.tf-apply.outputs.lambda_alias_updates }} + + - name: Wait for Lambda Provisioned Concurrency + uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/aws-lambda-wait-for-provisioned-concurrency@aws-lambda-wait-for-provisioned-concurrency-v1 + with: + lambda-alias-updates: ${{ steps.tf-apply.outputs.lambda_alias_updates }} +``` + +## Notes + +- Expects the `lambda-alias-updates` input to be the raw `lambda_alias_updates` output from the `terraform-apply` action. +- Functions without provisioned concurrency configured are skipped automatically. +- If provisioned concurrency reaches `FAILED` status, the action logs a warning and continues without failing the workflow. +- Requires AWS credentials to be configured in the job before this step runs. diff --git a/aws-lambda-wait-for-provisioned-concurrency/action.yml b/aws-lambda-wait-for-provisioned-concurrency/action.yml new file mode 100644 index 0000000..690e6c3 --- /dev/null +++ b/aws-lambda-wait-for-provisioned-concurrency/action.yml @@ -0,0 +1,64 @@ +name: "AWS Lambda - Wait for Provisioned Concurrency" +description: > + Waits for provisioned concurrency to reach READY status for all Lambda + functions listed in the Terraform lambda_alias_updates output. + +inputs: + lambda-alias-updates: + description: > + JSON array of Lambda alias update objects (Terraform output: lambda_alias_updates). + Each element is a JSON-encoded string with alias_name, function_name, and version. + required: true + +runs: + using: "composite" + steps: + - name: Install AWS CLI + shell: bash + run: | + if ! command -v aws &> /dev/null; then + curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o /tmp/awscliv2.zip + unzip -q /tmp/awscliv2.zip -d /tmp + sudo /tmp/aws/install + rm -rf /tmp/awscliv2.zip /tmp/aws + fi + + - name: Install jq if missing + shell: bash + run: | + set -euo pipefail + command -v jq >/dev/null 2>&1 || sudo apt-get install -y --no-install-recommends jq + + - name: Wait for Lambda Provisioned Concurrency + shell: bash + env: + LAMBDA_ALIAS_UPDATES: ${{ inputs.lambda-alias-updates }} + run: | + echo "$LAMBDA_ALIAS_UPDATES" | jq -c '.[] | fromjson' | while IFS= read -r entry; do + function_name=$(echo "$entry" | jq -r '.function_name') + alias_name=$(echo "$entry" | jq -r '.alias_name') + if aws lambda get-provisioned-concurrency-config \ + --no-cli-pager \ + --function-name "$function_name" \ + --qualifier "$alias_name" >/dev/null 2>&1; then + echo "Provisioned concurrency found, waiting for READY status... ($function_name:$alias_name)" + while true; do + STATUS=$(aws lambda get-provisioned-concurrency-config \ + --no-cli-pager \ + --function-name "$function_name" \ + --qualifier "$alias_name" \ + --query 'Status' \ + --output text 2>/dev/null || echo "FAILED") + echo "Current status: $STATUS ($function_name:$alias_name)" + if [[ "$STATUS" == "READY" ]]; then + echo "Provisioned Concurrency - Ready ($function_name:$alias_name)" + break + elif [[ "$STATUS" == "FAILED" ]]; then + echo "Provisioned concurrency failed, continuing anyway ($function_name:$alias_name)" + break + fi + done + else + echo "No provisioned concurrency configured, skipping wait ($function_name:$alias_name)" + fi + done From a4cdd003e742cc3336cc2b388cee981a59f5da18 Mon Sep 17 00:00:00 2001 From: Marcel Frey Date: Thu, 25 Jun 2026 12:46:40 +0000 Subject: [PATCH 16/17] chore(rust-build): clippy no longer fails on warnings The `-- -D warnings` option caused clippy to fail on warnings. --- rust-build/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-build/action.yml b/rust-build/action.yml index d12b6cb..a36a845 100644 --- a/rust-build/action.yml +++ b/rust-build/action.yml @@ -92,7 +92,7 @@ runs: for check in "${CHECKS[@]}"; do case "${check}" in fmt) cargo fmt --manifest-path="${WORKING_DIR}/Cargo.toml" --check ;; - clippy) cargo clippy --manifest-path="${WORKING_DIR}/Cargo.toml" --target="${CROSS_TARGET}" -- -D warnings ;; + clippy) cargo clippy --manifest-path="${WORKING_DIR}/Cargo.toml" --target="${CROSS_TARGET}" ;; test) cargo test --manifest-path="${WORKING_DIR}/Cargo.toml" ;; *) echo "Unknown check: ${check}"; exit 1 ;; esac From 5f6e75b79d5be18d7a9e850086c52438d16a8420 Mon Sep 17 00:00:00 2001 From: Marcel Frey Date: Thu, 25 Jun 2026 12:36:19 +0000 Subject: [PATCH 17/17] docs: document how to add a new action ... and update the `tag-release` workflow with the AWS Lambda actions --- .forgejo/workflows/tag-release.yml | 4 +++- README.md | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.forgejo/workflows/tag-release.yml b/.forgejo/workflows/tag-release.yml index 3ed1f31..14a2b68 100644 --- a/.forgejo/workflows/tag-release.yml +++ b/.forgejo/workflows/tag-release.yml @@ -16,6 +16,8 @@ on: - aikido-full-scan - aikido-pr-scan - aws-configure + - aws-lambda-alias-update + - aws-lambda-wait-for-provisioned-concurrency - cache - checkout - download-artifact @@ -24,9 +26,9 @@ on: - i18n-sync - inject-content - maven-build - - pnpm-build - playwright-merge - playwright-run + - pnpm-build - publish-npm-package - publish-rust-crate - publish-static-contents diff --git a/README.md b/README.md index 755d459..e7acbbf 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,26 @@ Shared actions for Forgejo CI/CD pipelines. Where third-party Forgejo/GitHub Actions are used internally, they are pinned to exact commit hashes rather than mutable tags to prevent supply chain attacks. +## Adding a new Action + +- Create a new directory for the action +- Implement the action +- Add a `README.md` file that describes (1) purpose, (2) inputs using a table, (3) example usage, and additional details if requried to the action directory +- Update the table in the main README (this file) with a new row. The list is sorted alphabetically. +- Update the `tag-release.yml` workflow in the `.forgejo/` directory if the action is a public action: Add the name to the option list. + +## Releasing a new Version + +**We only use Major-Versions, e.g. `1`, `2`, `3`, etc.** + +- Decide which Version to use + - Breaking Change: Increment the current version by one (e.g. `1 -> 2`) + - All non-breaking changes: Stay on the current major version (`1 -> 1`) +- Manually run the `tag-release.yml` workflow + - Branch: `main` + - Action: Name of the Action to release + - Version: The version to release + ## Usage Reference actions from your project's workflow: