[AUTO] Model Tracker #101
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Generate Libraries | |
on: | |
pull_request: | |
branches: | |
- '**' | |
release: | |
types: | |
- published | |
workflow_dispatch: | |
inputs: | |
release_name: | |
description: 'Release name for manual dispatch' | |
required: true | |
# Workflow dependencies, also to avoid concurrent commits | |
# Ref.: https://github.com/orgs/community/discussions/26238 | |
workflow_run: | |
workflows: ["Generate Model"] | |
types: | |
- completed | |
jobs: | |
generate-libs: | |
runs-on: ubuntu-latest | |
# PyPi trusted publishing | Ref.: https://github.com/pypa/gh-action-pypi-publish?tab=readme-ov-file#trusted-publishing | |
permissions: | |
contents: write # For final commit | |
packages: write # For package upload | |
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing | |
steps: | |
- name: Set RELEASE_VERSION based on the trigger type | |
run: | | |
if [[ "${{ github.event_name }}" == "release" ]]; then | |
RELEASE_VERSION="${{ github.ref_name }}" | |
elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then | |
RELEASE_VERSION="${{ github.event.inputs.release_name }}" | |
elif [[ "${{ github.event_name }}" == "pull_request" ]]; then | |
# Include first chars of commit SHA and run attempt number to avoid collisions | |
COMMIT_SHA="${{ github.event.pull_request.head.sha }}" | |
SHORT_COMMIT_SHA=${COMMIT_SHA::7} | |
RELEASE_VERSION="0.0.0+${{ github.head_ref }}.$SHORT_COMMIT_SHA.${{ github.run_attempt }}" | |
fi | |
# Make the RELEASE_VERSION semver compatible (replacing non letter/digit/./+ chars with .) | |
RELEASE_VERSION=$(echo "$RELEASE_VERSION" | sed 's/[^a-zA-Z0-9\.\+]/./g') | |
# Display the RELEASE_VERSION for verification | |
echo "The RELEASE_VERSION is: $RELEASE_VERSION" | |
# Check if RELEASE_VERSION matches the semver allowed pattern | |
if [[ ! $RELEASE_VERSION =~ ^[0-9]+\.[0-9]+\.[0-9].* ]]; then | |
echo "RELEASE_VERSION is NOT semver compatible (1.1.1.xxx)" | |
exit 1 | |
fi | |
# Export the RELEASE_VERSION environment variable for future steps (in env.RELEASE_VERSION) | |
echo "RELEASE_VERSION=$RELEASE_VERSION" >> $GITHUB_ENV | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Install node env 🏗 | |
uses: actions/setup-node@v4 | |
with: | |
node-version: 16 | |
- name: Install openapi-generator-cli | |
run: npm install -g @openapitools/openapi-generator-cli | |
- name: Cleaning output directories | |
run: | | |
rm -r generator_ruby/gem/ generator_python/package/ generator_csharp/package/ || true | |
- name: Python - Generate classes | |
working-directory: ./generator_python | |
run: | | |
# Iterate over each file in the ./config directory, including the entire subfolder structure | |
# and then run @openapitools/openapi-generator-cli generate for each file found | |
# Important notice: | |
# Results of the find command are sorted in an alphabetic order before being passed to xargs | |
# This means that since the order of class generation is important, it's necessary to maintain an adequately | |
# named file structure in the ./config/** directories | |
# generator-config.json (if exists) -> usecase.generator-config.json -> wrapper.generator-config.json | |
# Add "| head -n 1" after sort for faster iterations while developing | |
find ./config/ -type f | sort -n | while read -r file; do npx @openapitools/openapi-generator-cli generate -c "$file" --skip-validate-spec; done | |
# There seems to be a bug in the handling of datetime & field_validator import in OpenAPI Generator | |
# ToDo: fix this cleanly with OpenAPI Generator Config | |
# For now, basic bash script that adds field_validator to all pydantic imports | |
find ./package/src/hubsante_model -type f -name "*.py" | while read -r file; do | |
# Check if 'field_validator' is missing in the 'from pydantic import' line | |
if grep -q 'field_validator' "$file" && ! grep -q '^from pydantic import .*field_validator.*$' "$file"; then | |
# Add field_validator to the import statement | |
sed -i '/^from pydantic import /s/$/, field_validator/' "$file" | |
fi | |
# Convert datetime to str | |
sed -i 's/: datetime = Field/: str = Field/g' "$file" | |
sed -i 's/: Optional\[datetime\] = Field/: Optional[str] = Field/g' "$file" | |
done | |
- name: Python - Prepare package files | |
working-directory: ./generator_python/ | |
run: | | |
# Add key package files | |
cp pyproject.toml ./package/ | |
cp README.md ./package/ | |
# Generate __init__.py file to import all the *_wrapper classes | |
echo "# Auto-generated imports" > ./package/src/hubsante_model/__init__.py | |
find ./package/src/hubsante_model -type f -name "*_wrapper.py" | while read -r file; do | |
# Extract the relative path from hubsante_model/ | |
rel_path=${file#*hubsante_model/} | |
# Convert path to Python import format | |
import_path=${rel_path%.py} | |
import_path=${import_path//\//.} | |
# Add import line | |
echo "from .$import_path import *" >> ./package/src/hubsante_model/__init__.py | |
done | |
- name: Python - Set up | |
uses: actions/setup-python@v4 | |
with: | |
python-version: '3.8' | |
- name: Python - Build package | |
working-directory: ./generator_python/package/ | |
run: | | |
pip install --upgrade build | |
# Set correct version | |
sed -i "s/version = .*/version = \"${{ env.RELEASE_VERSION }}\"/" pyproject.toml | |
python -m build | |
- name: Python - Upload package as artifact | |
uses: actions/upload-artifact@v3 | |
with: | |
name: python-package-artifact | |
path: ./generator_python/package/dist/ | |
# Leverages trusted publisher | Ref.: https://docs.pypi.org/trusted-publishers/adding-a-publisher/ | |
- name: Python - Publish package to pypi | |
uses: pypa/gh-action-pypi-publish@release/v1 | |
if: github.event_name != 'pull_request' | |
with: | |
packages-dir: ./generator_python/package/dist/ | |
- name: Ruby - Generate classes | |
working-directory: ./generator_ruby | |
run: | | |
# Iterate over each file in the ./config directory, including the entire subfolder structure | |
# and then run @openapitools/openapi-generator-cli generate for each file found | |
# Important notice: | |
# Results of the find command are sorted in an alphabetic order before being passed to xargs | |
# This means that since the order of class generation is important, it's necessary to maintain an adequately | |
# named file structure in the ./config/** directories | |
# generator-config.json (if exists) -> usecase.generator-config.json -> wrapper.generator-config.json | |
find ./config/ -type f | sort -n | while read -r file; do npx @openapitools/openapi-generator-cli generate -c "$file" --skip-validate-spec; done | |
- name: Ruby - Prepare Gem files | |
working-directory: ./generator_ruby | |
run: | | |
# Move generated classes to the correct location | |
for dir in gem/*/; do | |
package=$(basename "$dir") | |
mkdir -p "gem/lib/hubsanteModel/models/$package/" | |
mv "$dir"/lib/hubsanteModel/models/* "gem/lib/hubsanteModel/models/$package/" | |
rmdir "$dir/lib/hubsanteModel/models" && rmdir "$dir/lib/hubsanteModel" && rmdir "$dir/lib" && rmdir "$dir" | |
done; | |
# Add key gem files | |
cp hubsante_model.rb gem/lib/hubsanteModel/ | |
cp hubsante_model.gemspec gem/ | |
- name: Ruby - Set up | |
uses: ruby/setup-ruby@v1 | |
with: | |
ruby-version: '3.0' | |
bundler-cache: true | |
- name: Ruby - Build Gem | |
working-directory: ./generator_ruby/gem/ | |
run: | | |
GEM_VERSION=${{ env.RELEASE_VERSION }} | |
export GEM_VERSION=${GEM_VERSION//+/.} | |
gem build hubsante_model.gemspec | |
- name: Ruby - Upload Gem as artifact | |
uses: actions/upload-artifact@v3 | |
with: | |
name: ruby-gem-artifact | |
path: ./generator_ruby/gem/hubsante_model-*.gem | |
- name: Ruby - Push Gem to GitHub Packages | |
working-directory: ./generator_ruby/gem/ | |
run: gem push --key github --host https://rubygems.pkg.github.com/ansforge ./hubsante_model-*.gem | |
env: | |
GEM_HOST_API_KEY: ${{ secrets.GITHUB_TOKEN }} # GitHub token used to authenticate | |
- name: C# - Generate classes | |
working-directory: ./generator_csharp | |
run: | | |
# Iterate over each file in the ./config directory, including the entire subfolder structure | |
# and then run @openapitools/openapi-generator-cli generate for each file found | |
# Important notice: | |
# Results of the find command are sorted in an alphabetic order before being passed to xargs | |
# This means that since the order of class generation is important, it's necessary to maintain an adequately | |
# named file structure in the ./config/** directories | |
# generator-config.json (if exists) -> usecase.generator-config.json -> wrapper.generator-config.json | |
find ./config/ -type f | sort -n | while read -r file; do npx @openapitools/openapi-generator-cli generate -c "$file" --skip-validate-spec; done | |
# - name: C# - Prepare package files | |
# working-directory: ./generator_csharp/ | |
# run: | | |
# # Add key package files | |
# cp HubsanteModel.csproj ./package/src/ | |
# cp README.md ./package/ | |
# - name: C# - Set up .NET | |
# uses: actions/setup-dotnet@v3 | |
# with: | |
# dotnet-version: '6.0.x' | |
# - name: C# - Build package | |
# working-directory: ./generator_csharp/package/src/ | |
# run: | | |
# dotnet restore | |
# dotnet build --configuration Release | |
# dotnet pack --configuration Release -p:Version=${{ env.RELEASE_VERSION }} | |
# - name: C# - Upload package as artifact | |
# uses: actions/upload-artifact@v3 | |
# with: | |
# name: csharp-package-artifact | |
# path: ./generator_csharp/package/src/bin/Release/*.nupkg | |
# - name: C# - Push package to GitHub Packages | |
# working-directory: ./generator_csharp/package/src/ | |
# run: | | |
# dotnet nuget push bin/Release/*.nupkg --source https://nuget.pkg.github.com/ansforge/index.json --api-key ${{ secrets.GITHUB_TOKEN }} | |
- name: Commit and push changes | |
if: ${{ !env.ACT }} | |
uses: stefanzweifel/git-auto-commit-action@v5 | |
with: | |
commit_message: ⚙️ Auto-génération des librairies |