From 29e5c2b4e7e850fa25ce2e8ebee0bd0da476603b Mon Sep 17 00:00:00 2001 From: Diego Abadan Date: Wed, 19 Aug 2026 10:46:07 -0300 Subject: [PATCH] Generate complete English release notes Centralize compatibility metadata, generated changes, installation guidance, exact version validation, and runtime-only packaging in the reusable workflow. Keep existing callers compatible, make English the canonical README, pin CI dependencies, and validate workflows with actionlint. Reviewed independently by a Sol agent. --- .github/workflows/generate-package.yml | 120 +++++++++++++++++++------ .github/workflows/validate.yml | 25 ++++++ README.md | 44 +++++---- docs/README-en.md | 45 ---------- docs/README-es.md | 18 +++- docs/README-pt_BR.md | 55 ++++++++++++ 6 files changed, 215 insertions(+), 92 deletions(-) create mode 100644 .github/workflows/validate.yml delete mode 100644 docs/README-en.md create mode 100644 docs/README-pt_BR.md diff --git a/.github/workflows/generate-package.yml b/.github/workflows/generate-package.yml index e979a5a..5f5bf98 100644 --- a/.github/workflows/generate-package.yml +++ b/.github/workflows/generate-package.yml @@ -2,8 +2,24 @@ on: workflow_call: inputs: plugin_name: + description: Plugin directory and package name required: true type: string + pkp_application: + description: PKP application displayed in the release notes, such as OJS, OMP, or OPS + required: false + type: string + default: '' + compatible_versions: + description: Compatible application versions displayed in the release notes, such as OJS 3.5.x + required: false + type: string + default: '' + release_branch: + description: Branch from which the release was prepared + required: false + type: string + default: '' name: Create release and tar.gz package for it @@ -17,40 +33,92 @@ jobs: PLUGIN_NAME: ${{ inputs.plugin_name }} steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 - name: Check version.xml + id: version + env: + RELEASE_TAG: ${{ github.ref_name }} run: | - sudo apt install -y xmlstarlet - application=$(xmlstarlet sel -t -v 'version/application' version.xml) - if [ "$application" != "$PLUGIN_NAME" ]; then - echo "Application mismatch: expected $PLUGIN_NAME, got $application" - exit 1 - fi - release=$(xmlstarlet sel -t -v 'version/release' version.xml) - tag=${{ github.ref }} - tag=${tag/refs\/tags\/v/} - if [[ "$release" != "$tag"* ]]; then - echo "Version mismatch: expected $tag, got $release" - exit 1 - fi - date_version=$(xmlstarlet sel -t -v 'version/date' version.xml) - current_date=$(date +'%Y-%m-%d') - if [ "$date_version" != "$current_date" ]; then - echo "Date mismatch: expected $current_date, got $date_version" - exit 1 - fi - shell: bash + python3 <<'PY' + import datetime + import os + import xml.etree.ElementTree as ET + + version = ET.parse('version.xml').getroot() + expected = { + 'application': os.environ['PLUGIN_NAME'], + 'release': os.environ['RELEASE_TAG'].removeprefix('v'), + 'date': datetime.date.today().isoformat(), + } + + for field, expected_value in expected.items(): + actual_value = version.findtext(field) + if actual_value != expected_value: + raise SystemExit( + f'version.xml: {field} is {actual_value!r}; ' + f'expected {expected_value!r}' + ) + + with open(os.environ['GITHUB_OUTPUT'], 'a', encoding='utf-8') as output: + print(f"release={expected['release']}", file=output) + PY - name: Create the tar.gz package run: | - mkdir $PLUGIN_NAME - shopt -s extglob - cp -r !($PLUGIN_NAME|.git*|.|..|tests|cypress|resources|CLAUDE.md|package.json|package-lock.json|vite.config.js|i18nExtractKeys.vite.js) $PLUGIN_NAME - tar -zcvf $PLUGIN_NAME.tar.gz $PLUGIN_NAME + git archive \ + --format=tar.gz \ + --prefix="${PLUGIN_NAME}/" \ + --output="${PLUGIN_NAME}.tar.gz" \ + HEAD \ + -- \ + . \ + ':(exclude).agents' \ + ':(exclude).codex' \ + ':(exclude).gitattributes' \ + ':(exclude).github' \ + ':(exclude).gitignore' \ + ':(exclude).gitlab-ci.yml' \ + ':(exclude).gitmodules' \ + ':(exclude)AGENTS.md' \ + ':(exclude)CLAUDE.md' \ + ':(exclude)cypress' \ + ':(exclude)tests' \ + ':(exclude)resources' \ + ':(exclude)package.json' \ + ':(exclude)package-lock.json' \ + ':(exclude)vite.config.js' \ + ':(exclude)i18nExtractKeys.vite.js' + + - name: Generate release notes + env: + GH_TOKEN: ${{ github.token }} + PKP_APPLICATION: ${{ inputs.pkp_application || 'Not specified; see the plugin README' }} + COMPATIBLE_VERSIONS: ${{ inputs.compatible_versions || 'Not specified; see the plugin README' }} + RELEASE_BRANCH: ${{ inputs.release_branch || 'Not specified; see the plugin README' }} + RELEASE_VERSION: ${{ steps.version.outputs.release }} + run: | + generated_notes=$(gh api \ + --method POST \ + "repos/${GITHUB_REPOSITORY}/releases/generate-notes" \ + --field "tag_name=${GITHUB_REF_NAME}" \ + --jq '.body') + + { + printf '## Compatibility\n\n' + printf -- '- Application: %s\n' "$PKP_APPLICATION" + printf -- '- Compatible versions: %s\n' "$COMPATIBLE_VERSIONS" + printf -- '- Branch: %s\n' "$RELEASE_BRANCH" + printf -- '- Plugin version: %s\n\n' "$RELEASE_VERSION" + printf '## Changes\n\n%s\n\n' "$generated_notes" + printf '## Installation\n\n' + printf 'Download the attached %s.tar.gz package and install it using the PKP application plugin manager.\n' "$PLUGIN_NAME" + } > release-notes.md shell: bash - name: Create release and upload package - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2 with: + name: Release ${{ github.ref_name }} + body_path: release-notes.md files: ${{ inputs.plugin_name }}.tar.gz diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 0000000..e590717 --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,25 @@ +name: Validate workflows + +on: + pull_request: + push: + branches: + - main + +permissions: + contents: read + +jobs: + actionlint: + name: Validate GitHub Actions workflows + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + + - name: Run actionlint + run: | + docker run --rm \ + --volume "$PWD:/repo" \ + --workdir /repo \ + rhysd/actionlint@sha256:b1934ee5f1c509618f2508e6eb47ee0d3520686341fec936f3b79331f9315667 diff --git a/README.md b/README.md index 8aaf9d9..28f1462 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,26 @@ # github-workflows -**Português Brasileiro** | [English](docs/README-en.md) | [Español](docs/README-es.md) +**English** | [Português Brasileiro](docs/README-pt_BR.md) | [Español](docs/README-es.md) -Workflows reutilizáveis do GitHub Actions para plugins da Lepidus. +Reusable GitHub Actions workflows for Lepidus plugins. -## Workflows disponíveis +## Available workflows ### `generate-package.yml` -Valida o `version.xml` e gera um pacote `.tar.gz` como asset de release ao criar uma tag. +Validates `version.xml`, generates a `.tar.gz` package, and publishes a complete English release when a tag is pushed. The release description contains compatibility metadata, automatically generated changes, and installation instructions. -**Validações realizadas:** -- O campo `application` do `version.xml` corresponde ao nome do plugin -- O campo `release` corresponde à tag criada -- O campo `date` corresponde à data atual +**Validations performed:** +- The `application` field in `version.xml` matches the plugin name +- The `release` field exactly matches the pushed tag without the `v` prefix +- The `date` field matches the current date -**Arquivos excluídos do pacote:** -`tests`, `cypress`, `resources`, `CLAUDE.md`, `package.json`, `package-lock.json`, `vite.config.js`, `i18nExtractKeys.vite.js` +**Files excluded from the package:** +`.agents`, `.codex`, `.gitattributes`, `.github`, `.gitignore`, `.gitlab-ci.yml`, `.gitmodules`, `AGENTS.md`, `CLAUDE.md`, `tests`, `cypress`, `resources`, `package.json`, `package-lock.json`, `vite.config.js`, `i18nExtractKeys.vite.js` -#### Como usar +#### Usage -No repositório do plugin, crie `.github/workflows/generate-package.yml`: +In the plugin repository, create `.github/workflows/generate-package.yml`: ```yaml on: @@ -34,12 +34,22 @@ jobs: create-release: uses: lepidus/github-workflows/.github/workflows/generate-package.yml@main with: - plugin_name: nomeDoseuPlugin + plugin_name: yourPluginName + pkp_application: OJS + compatible_versions: OJS 3.5.x + release_branch: stable-3_5_0 permissions: contents: write ``` -#### Pré-requisitos - -- O repositório deve ter um arquivo `version.xml` na raiz com os campos `application`, `release` e `date` -- As tags devem seguir o padrão `v*` (ex: `v1.0.0.0`) +#### Requirements + +- The repository must have a `version.xml` file at the root with `application`, `release`, and `date` fields +- Tags must follow the `v*` pattern (e.g. `v1.0.0.0`) +- `plugin_name` is required and must match `version/application` +- The compatibility inputs keep release metadata accurate and are strongly recommended: + - `pkp_application`: compatible PKP application, such as `OJS`, `OMP`, or `OPS` + - `compatible_versions`: compatible application versions, such as `OJS 3.5.x` + - `release_branch`: branch from which the release was prepared, such as `stable-3_5_0` +- Existing callers that only pass `plugin_name` remain compatible. Missing compatibility values and the release branch are identified in English as not specified instead of being inferred +- The caller must grant `contents: write` permission so the workflow can create the release and upload its package diff --git a/docs/README-en.md b/docs/README-en.md deleted file mode 100644 index 0c9d079..0000000 --- a/docs/README-en.md +++ /dev/null @@ -1,45 +0,0 @@ -# github-workflows - -[Português Brasileiro](../README.md) | **English** | [Español](README-es.md) - -Reusable GitHub Actions workflows for Lepidus plugins. - -## Available workflows - -### `generate-package.yml` - -Validates `version.xml` and generates a `.tar.gz` package as a release asset when a tag is pushed. - -**Validations performed:** -- The `application` field in `version.xml` matches the plugin name -- The `release` field matches the pushed tag -- The `date` field matches the current date - -**Files excluded from the package:** -`tests`, `cypress`, `resources`, `CLAUDE.md`, `package.json`, `package-lock.json`, `vite.config.js`, `i18nExtractKeys.vite.js` - -#### Usage - -In the plugin repository, create `.github/workflows/generate-package.yml`: - -```yaml -on: - push: - tags: - - 'v*' - -name: Create release and tar.gz package for it - -jobs: - create-release: - uses: lepidus/github-workflows/.github/workflows/generate-package.yml@main - with: - plugin_name: yourPluginName - permissions: - contents: write -``` - -#### Requirements - -- The repository must have a `version.xml` file at the root with `application`, `release`, and `date` fields -- Tags must follow the `v*` pattern (e.g. `v1.0.0.0`) diff --git a/docs/README-es.md b/docs/README-es.md index 33497a2..b531148 100644 --- a/docs/README-es.md +++ b/docs/README-es.md @@ -1,6 +1,6 @@ # github-workflows -[Português Brasileiro](../README.md) | [English](README-en.md) | **Español** +[English](../README.md) | [Português Brasileiro](README-pt_BR.md) | **Español** Workflows reutilizables de GitHub Actions para plugins de Lepidus. @@ -8,15 +8,15 @@ Workflows reutilizables de GitHub Actions para plugins de Lepidus. ### `generate-package.yml` -Valida el `version.xml` y genera un paquete `.tar.gz` como asset de release al crear una etiqueta. +Valida el `version.xml`, genera un paquete `.tar.gz` y publica una release completa en inglés al crear una etiqueta. La descripción de la release contiene metadatos de compatibilidad, cambios generados automáticamente e instrucciones de instalación. **Validaciones realizadas:** - El campo `application` del `version.xml` corresponde al nombre del plugin -- El campo `release` corresponde a la etiqueta creada +- El campo `release` corresponde exactamente a la etiqueta creada sin el prefijo `v` - El campo `date` corresponde a la fecha actual **Archivos excluidos del paquete:** -`tests`, `cypress`, `resources`, `CLAUDE.md`, `package.json`, `package-lock.json`, `vite.config.js`, `i18nExtractKeys.vite.js` +`.agents`, `.codex`, `.gitattributes`, `.github`, `.gitignore`, `.gitlab-ci.yml`, `.gitmodules`, `AGENTS.md`, `CLAUDE.md`, `tests`, `cypress`, `resources`, `package.json`, `package-lock.json`, `vite.config.js`, `i18nExtractKeys.vite.js` #### Cómo usar @@ -35,6 +35,9 @@ jobs: uses: lepidus/github-workflows/.github/workflows/generate-package.yml@main with: plugin_name: nombreDeSuPlugin + pkp_application: OJS + compatible_versions: OJS 3.5.x + release_branch: stable-3_5_0 permissions: contents: write ``` @@ -43,3 +46,10 @@ jobs: - El repositorio debe tener un archivo `version.xml` en la raíz con los campos `application`, `release` y `date` - Las etiquetas deben seguir el patrón `v*` (ej: `v1.0.0.0`) +- `plugin_name` es obligatorio y debe corresponder a `version/application` +- Las entradas de compatibilidad mantienen los metadatos correctos y son muy recomendables: + - `pkp_application`: aplicación PKP compatible, como `OJS`, `OMP` u `OPS` + - `compatible_versions`: versiones compatibles de la aplicación, como `OJS 3.5.x` + - `release_branch`: rama desde la cual se preparó la release, como `stable-3_5_0` +- Los workflows existentes que solo envían `plugin_name` siguen siendo compatibles. Los valores de compatibilidad y la rama de la release ausentes se identifican en inglés como no especificados, en lugar de inferirse +- El workflow llamador debe conceder el permiso `contents: write` para que el workflow cree la release y suba el paquete diff --git a/docs/README-pt_BR.md b/docs/README-pt_BR.md new file mode 100644 index 0000000..e54f22d --- /dev/null +++ b/docs/README-pt_BR.md @@ -0,0 +1,55 @@ +# github-workflows + +[English](../README.md) | **Português Brasileiro** | [Español](README-es.md) + +Workflows reutilizáveis do GitHub Actions para plugins da Lepidus. + +## Workflows disponíveis + +### `generate-package.yml` + +Valida o `version.xml`, gera um pacote `.tar.gz` e publica uma release completa em inglês ao criar uma tag. A descrição da release contém metadados de compatibilidade, alterações geradas automaticamente e instruções de instalação. + +**Validações realizadas:** +- O campo `application` do `version.xml` corresponde ao nome do plugin +- O campo `release` corresponde exatamente à tag criada sem o prefixo `v` +- O campo `date` corresponde à data atual + +**Arquivos excluídos do pacote:** +`.agents`, `.codex`, `.gitattributes`, `.github`, `.gitignore`, `.gitlab-ci.yml`, `.gitmodules`, `AGENTS.md`, `CLAUDE.md`, `tests`, `cypress`, `resources`, `package.json`, `package-lock.json`, `vite.config.js`, `i18nExtractKeys.vite.js` + +#### Como usar + +No repositório do plugin, crie `.github/workflows/generate-package.yml`: + +```yaml +on: + push: + tags: + - 'v*' + +name: Create release and tar.gz package for it + +jobs: + create-release: + uses: lepidus/github-workflows/.github/workflows/generate-package.yml@main + with: + plugin_name: nomeDoseuPlugin + pkp_application: OJS + compatible_versions: OJS 3.5.x + release_branch: stable-3_5_0 + permissions: + contents: write +``` + +#### Pré-requisitos + +- O repositório deve ter um arquivo `version.xml` na raiz com os campos `application`, `release` e `date` +- As tags devem seguir o padrão `v*` (ex: `v1.0.0.0`) +- `plugin_name` é obrigatório e deve corresponder a `version/application` +- As entradas de compatibilidade mantêm os metadados corretos e são fortemente recomendadas: + - `pkp_application`: aplicação PKP compatível, como `OJS`, `OMP` ou `OPS` + - `compatible_versions`: versões compatíveis da aplicação, como `OJS 3.5.x` + - `release_branch`: ramo a partir do qual a release foi preparada, como `stable-3_5_0` +- Chamadores existentes que informam apenas `plugin_name` permanecem compatíveis. Valores de compatibilidade e o ramo da release ausentes são identificados em inglês como não informados, em vez de serem inferidos +- O chamador deve conceder a permissão `contents: write` para que o workflow crie a release e envie o pacote