diff --git a/.forgejo/workflows/tag-release.yml b/.forgejo/workflows/tag-release.yml index 6dffa2a..428ec72 100644 --- a/.forgejo/workflows/tag-release.yml +++ b/.forgejo/workflows/tag-release.yml @@ -19,16 +19,22 @@ on: - cache - checkout - download-artifact + - esb-deploy - helm-deploy - i18n-sync - inject-content - maven-build - pnpm-build + - playwright-merge + - playwright-run + - publish-npm-package + - publish-rust-crate - publish-static-contents - rust-build - terraform-apply - terraform-validate - upload-artifact + - vacuum-lint major-version: description: 'Major version number (e.g. 1)' required: true diff --git a/README.md b/README.md index c35a5bb..66f3ecf 100644 --- a/README.md +++ b/README.md @@ -17,12 +17,16 @@ 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-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-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 | ## Security @@ -38,4 +42,4 @@ Reference actions from your project's workflow: # see each action's README for inputs ``` -Each action has its own README with inputs, usage examples, and notes. \ No newline at end of file +Each action has its own README with inputs, usage examples, and notes. diff --git a/esb-deploy/README.md b/esb-deploy/README.md new file mode 100644 index 0000000..ae02466 --- /dev/null +++ b/esb-deploy/README.md @@ -0,0 +1,32 @@ +# 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` | Yes | — | Name of the service to deploy | +| `stage` | No | true | If true this is a stage deployment | + +## Usage + +```yaml +- uses: https://schmalz-git.git.onstackit.cloud/schmalz/shared-actions/esb-deploy@esb-deploy-v1 + with: + service: my-service + docker-host: esbdocker2-stage.schmalzgroup.net + java-version: 8 + maven-profile: test + maven-settings: ${{ secrets.MAVEN_SETTINGS }} + stage: true +``` + +## 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..584274e --- /dev/null +++ b/esb-deploy/action.yml @@ -0,0 +1,64 @@ +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: true + stage: + description: Whether to deploy to stage environment (true) or production environment (false) + 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 }} + maven-profile: ${{ inputs.maven-profile}} + + - 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" diff --git a/maven-build/action.yml b/maven-build/action.yml index 961bc28..6b16ded 100644 --- a/maven-build/action.yml +++ b/maven-build/action.yml @@ -94,9 +94,11 @@ 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 \ + -P "$MAVEN_PROFILE" \ $EXTRA_ARGS - name: Deploy 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..570a9ac --- /dev/null +++ b/playwright-run/README.md @@ -0,0 +1,62 @@ +# 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. | +| `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: e2e + node-version: 22 + jfrog-token: ${{ secrets.JFROG_TOKEN }} +``` + +### 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 + +- 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..f521fdd --- /dev/null +++ b/playwright-run/action.yml @@ -0,0 +1,108 @@ +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" + 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 + 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 }} + NO_DEPS: ${{ inputs.no-deps }} + PROJECTS: ${{ inputs.projects }} + run: | + SHARD_ARG="" + if [ "${SHARD_TOTAL}" != "1" ]; then + SHARD_ARG="--shard=${SHARD_INDEX}/${SHARD_TOTAL}" + fi + 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() }} + 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 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" < + Validate and lint OpenAPI specifications using Vacuum. + +inputs: + spec-dir: + description: Directory containing OpenAPI spec + required: false + default: "spec" + spec-filename: + description: Filename of the OpenAPI spec + required: false + default: "openapi.json" + rules-filename: + description: Filename of the lint rules config file + required: false + default: "vacuum.rules.yaml" + ignore-filename: + description: Filename of the lint ignore file + required: false + default: "vacuum.ignore.yaml" + min-score: + description: Minimum linting score for the check to pass + required: false + default: "70" + +runs: + using: composite + steps: + # Pinned to commit SHA instead of a tag to prevent supply chain attacks. + - name: Install Vacuum + shell: bash + run: curl -fsSL https://raw.githubusercontent.com/daveshanley/vacuum/8222bba0c8b21a3a94faf472e06c4db06f06c6ce/bin/install.sh | sudo sh > /dev/null 2>&1 + + - name: Lint Spec + shell: bash + env: + SPEC_DIR: ${{ inputs.spec-dir }} + SPEC_FILE: ${{ inputs.spec-filename }} + RULES_FILE: ${{ inputs.rules-filename }} + IGNORE_FILE: ${{ inputs.ignore-filename }} + MIN_SCORE: ${{ inputs.min-score }} + run: | + echo "Linting: [$SPEC_DIR/$SPEC_FILE]" + + # base command + CMD="vacuum lint $SPEC_DIR/$SPEC_FILE -x --min-score $MIN_SCORE" + + # check for rules file + if [ -f "$SPEC_DIR/$RULES_FILE" ]; then + CMD="$CMD -r $SPEC_DIR/$RULES_FILE" + echo " - using ruleset [$SPEC_DIR/$RULES_FILE]" + fi + + # check for ignore file + if [ -f "$SPEC_DIR/$IGNORE_FILE" ]; then + CMD="$CMD --ignore-file $SPEC_DIR/$IGNORE_FILE" + echo " - using ignore file [$SPEC_DIR/$IGNORE_FILE]" + fi + + # execute command + $CMD + + echo "Linted: [$SPEC_DIR/$SPEC_FILE]" + echo ""