Skip to content

Commit

Permalink
Merge pull request #42 from LedgerHQ/lp/manifest
Browse files Browse the repository at this point in the history
Implementing #41
  • Loading branch information
lpascal-ledger authored Nov 3, 2023
2 parents aca886d + 663a7a5 commit 8fe54ca
Show file tree
Hide file tree
Showing 5 changed files with 233 additions and 104 deletions.
64 changes: 0 additions & 64 deletions .github/workflows/_check_is_rust.yaml

This file was deleted.

135 changes: 135 additions & 0 deletions .github/workflows/_get_app_metadata.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
name: Output metadata on the application, inferred from the local 'ledger_app.toml' manifest or not

on:
workflow_call:
inputs:
relative_app_directory:
description: |
The relative path in the repository where the application is built from (defaults to ".").
If the application is configured with a 'ledger_app.toml' manifest at its root, this
parameter is ignored.
required: false
default: .
type: string
compatible_devices:
description: |
The list of device(s) the CI will run on.
Defaults to the full list of device(s) supported by the application as configured in the
'ledger_app.toml' manifest.
If the manifest is missing, defaults to ALL (["nanos", "nanox", "nanosp", "stax"]).
required: false
default: 'None'
type: string
pytest_directory:
description: |
The directory where the Python tests are stored (a `conftest.py` file is expected there).
If the application is configured with a 'ledger_app.toml' manifest at its root with a
'tests.pytest_directory' field, this parameter is ignored.
required: false
default: 'None'
type: string
outputs:
is_rust:
description: Returns "true" if the app is using Rust SDK, else returns "false"
value: ${{ jobs.fetch_metadata.outputs.is_rust }}
build_directory:
description: |
Returns the relative 'build_directory' path, i.e the repository directory where can be
found either the root 'Makefile' of a C app, or the Cargo.toml of a Rust app.
value: ${{ jobs.fetch_metadata.outputs.build_directory }}
compatible_devices:
description:
The list of device(s) supported by the application.
value: ${{ jobs.fetch_metadata.outputs.compatible_devices }}
pytest_directory:
description: |
The directory where the Python tests are stored (a `conftest.py` file is expected there).
value: ${{ jobs.fetch_metadata.outputs.pytest_directory }}

env:
APP_MANIFEST: "ledger_app.toml"

jobs:
fetch_metadata:
name: Retrieve application metadata
runs-on: ubuntu-latest

steps:
- name: Clone app repository
uses: actions/checkout@v3

- name: Install dependencies
run: pip install ledgered

- name: Gather application metadata, from inputs or 'ledger_app.toml'
id: fetch_metadata
run: |
pytest_directory='${{ inputs.pytest_directory }}';
if [[ -f "$APP_MANIFEST" ]];
then
# 'ledger_app.toml' exists
if grep -q 'rust-app' "$APP_MANIFEST";
then
# legacy manifest -> Rust application
echo "Legacy manifest detected. Please update your manifest to the newest version";
# checking the manifest with the repo
ledger-manifest --legacy --check . "$APP_MANIFEST";
echo "build_directory=$(ledger-manifest --legacy --output-build-directory "$APP_MANIFEST")" >> "$GITHUB_OUTPUT";
compatible_devices='${{ inputs.compatible_devices }}';
echo "is_rust=true" >> "$GITHUB_OUTPUT";
else
# classic manifest -> can be either C or Rust
echo "Manifest detected.";
# checking the manifest with the repo
ledger-manifest --check . "$APP_MANIFEST";
echo "build_directory=$(ledger-manifest --output-build-directory "$APP_MANIFEST")" >> "$GITHUB_OUTPUT";
compatible_devices="$(ledger-manifest --output-devices "$APP_MANIFEST")";
set +e # when [tests.pytest_directory] is not set, ledger-manifest fails
if temp="$(ledger-manifest --output-pytest-directory "$APP_MANIFEST")";
then
pytest_directory="${temp}";
fi
set -e
if [[ "$(ledger-manifest --output-sdk "$APP_MANIFEST")" == "rust" ]];
then
echo "is_rust=true" >> "$GITHUB_OUTPUT";
else
echo "is_rust=false" >> "$GITHUB_OUTPUT";
fi
fi
else
# No 'ledger_app.toml' -> C application
echo "No manifest detected.";
echo "build_directory=${{ inputs.relative_app_directory }}" >> "$GITHUB_OUTPUT";
compatible_devices='${{ inputs.compatible_devices }}';
echo "is_rust=false" >> "$GITHUB_OUTPUT";
fi
if [[ "${compatible_devices}" == 'None' ]];
then
# no inputs and no classic manifest
compatible_devices='["nanos", "nanosp", "nanox", "stax"]';
else
if [[ '${{ inputs.compatible_devices }}' != 'None' ]];
then
# in case classic manifest with devices, the input takes precedence on it
compatible_devices='${{ inputs.compatible_devices }}';
fi
fi
echo "compatible_devices=${compatible_devices}" | sed 's/+/p/' >> "$GITHUB_OUTPUT";
echo "pytest_directory=${pytest_directory}" >> "$GITHUB_OUTPUT";
echo "Inferred metadata:"
cat "$GITHUB_OUTPUT"
outputs:
is_rust: ${{ steps.fetch_metadata.outputs.is_rust }}
compatible_devices: ${{ steps.fetch_metadata.outputs.compatible_devices }}
build_directory: ${{ steps.fetch_metadata.outputs.build_directory }}
pytest_directory: ${{ steps.fetch_metadata.outputs.pytest_directory }}
45 changes: 29 additions & 16 deletions .github/workflows/reusable_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ on:
default: ${{ github.ref }}
type: string
relative_app_directory:
description: 'The relative path in the repository where the application is built from (defaults to ".")'
description: |
The relative path in the repository where the application is built from (defaults to ".")
If the application is configured with a 'ledger_app.toml' file at its root, this parameter
is ignored.
required: false
default: '.'
type: string
Expand All @@ -34,9 +38,14 @@ on:
default: ''
type: string
run_for_devices:
description: 'The list of device(s) on which the test will run (defaults to ["nanos", "nanox", "nanosp", "stax"])'
description: |
The list of device(s) on which the CI will run.
Defaults to the full list of device(s) supported by the application as configured in the
'ledger_app.toml' manifest.
If the manifest is missing, defaults to ALL (["nanos", "nanox", "nanosp", "stax"]).
required: false
default: '["nanos", "nanox", "nanosp", "stax"]'
default: 'None'
type: string
builder:
description: "The docker image to build the application in (defaults to ledger-app-builder-lite)"
Expand All @@ -45,19 +54,23 @@ on:
type: string

jobs:
call_check_is_rust:
name: Check if app is based on Rust
uses: ./.github/workflows/_check_is_rust.yaml
call_get_app_metadata:
# This job digests inputs and repository metadata provided by the `ledger_app.toml` manifest
# file, in order to output relevant directories, compatible devices, and other variables needed
# by following jobs.
name: Retrieve application metadata
uses: ./.github/workflows/_get_app_metadata.yml
with:
relative_app_directory: ${{ inputs.relative_app_directory }}
compatible_devices: ${{ inputs.run_for_devices }}

build:
name: Build application for NanoS, X, S+, and Stax
needs: call_check_is_rust
needs: call_get_app_metadata
strategy:
fail-fast: false
matrix:
device: ${{ fromJSON(inputs.run_for_devices) }}
device: ${{ fromJSON(needs.call_get_app_metadata.outputs.compatible_devices) }}
runs-on: ubuntu-latest
container:
image: ghcr.io/ledgerhq/ledger-app-builder/${{ inputs.builder }}:latest
Expand All @@ -73,34 +86,34 @@ jobs:
- name: Build application
shell: bash
run: |
if [[ "${{ needs.call_check_is_rust.outputs.is_rust }}" == "true" ]];
if [[ "${{ needs.call_get_app_metadata.outputs.is_rust }}" == "true" ]];
then
DEVICE_NAME="$(echo ${{ matrix.device }} | sed 's/nanosp/nanosplus/')" && \
cd ${{ inputs.relative_app_directory }} && \
cd ${{ needs.call_get_app_metadata.outputs.build_directory }} && \
cargo ledger build ${DEVICE_NAME} -- -Zunstable-options --out-dir=./build/${{ matrix.device }}/bin/
else
eval "BOLOS_SDK=\$$(echo ${{ matrix.device }} | tr [:lower:] [:upper:])_SDK" && \
echo "BOLOS_SDK value will be: ${BOLOS_SDK}" && \
make -C ${{ inputs.relative_app_directory }} -j ${{ inputs.flags }} BOLOS_SDK=${BOLOS_SDK}
make -C ${{ needs.call_get_app_metadata.outputs.build_directory }} -j ${{ inputs.flags }} BOLOS_SDK=${BOLOS_SDK}
fi
- name: Remove build artifacts before upload
run: |
find ${{ inputs.relative_app_directory }}/build/ -mindepth 2 -type d ! -name 'bin' -exec rm -r {} +
find ${{ needs.call_get_app_metadata.outputs.build_directory }}/build/ -mindepth 2 -type d ! -name 'bin' -exec rm -r {} +
- name: Prepare to upload as lib
if: ${{ inputs.upload_as_lib_artifact != '' }}
shell: bash
run: |
DEVICE_NAME="$(echo ${{ matrix.device }} | tr nanosp nanos2)" && \
find ${{ inputs.relative_app_directory }}/build/${DEVICE_NAME}/ -type f -name 'app.elf' -exec mv {} ${{ inputs.upload_as_lib_artifact }}_${DEVICE_NAME}.elf \; && \
rm -r ${{ inputs.relative_app_directory }}/build/* && \
mv ${{ inputs.upload_as_lib_artifact }}_${DEVICE_NAME}.elf ${{ inputs.relative_app_directory }}/build/
find ${{ needs.call_get_app_metadata.outputs.build_directory }}/build/${DEVICE_NAME}/ -type f -name 'app.elf' -exec mv {} ${{ inputs.upload_as_lib_artifact }}_${DEVICE_NAME}.elf \; && \
rm -r ${{ needs.call_get_app_metadata.outputs.build_directory }}/build/* && \
mv ${{ inputs.upload_as_lib_artifact }}_${DEVICE_NAME}.elf ${{ needs.call_get_app_metadata.outputs.build_directory }}/build/
- name: Upload app binary
if: ${{ inputs.upload_app_binaries_artifact != '' }}
uses: actions/upload-artifact@v3
with:
name: ${{ inputs.upload_app_binaries_artifact }}
path: ${{ inputs.relative_app_directory }}/build/*
path: ${{ needs.call_get_app_metadata.outputs.build_directory }}/build/*
if-no-files-found: error
41 changes: 27 additions & 14 deletions .github/workflows/reusable_guidelines_enforcer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,21 @@ on:
workflow_call:
inputs:
run_for_devices:
description: 'The list of device(s) on which the checking will run (defaults to ["nanos", "nanox", "nanosp", "stax"])'
description: |
The list of device(s) on which the test will run.
Defaults to the full list of device(s) supported by the application as configured in the
'ledger_app.toml' manifest.
If the manifest is missing, defaults to ALL (["nanos", "nanox", "nanosp", "stax"]).
required: false
default: '["nanos", "nanox", "nanosp", "stax"]'
default: 'None'
type: string
relative_app_directory:
description: 'The relative path in the repository where the application is built from (defaults to ".")'
description: |
The relative path in the repository where the application is built from (defaults to ".")
If the application is configured with a 'ledger_app.toml' file at its root, this parameter
is ignored.
required: false
default: '.'
type: string
Expand All @@ -31,21 +40,25 @@ jobs:
secrets:
git_token: ${{ secrets.git_token }}

call_check_is_rust:
name: Check if app is based on Rust
uses: ./.github/workflows/_check_is_rust.yaml
call_get_app_metadata:
# This job digests inputs and repository metadata provided by the `ledger_app.toml` manifest
# file, in order to output relevant directories, compatible devices, and other variables needed
# by following jobs.
name: Retrieve application metadata
uses: ./.github/workflows/_get_app_metadata.yml
with:
relative_app_directory: ${{ inputs.relative_app_directory }}
compatible_devices: ${{ inputs.run_for_devices }}

call_get_app_manifest:
name: Dump app information
needs: [call_get_workflow_version, call_check_is_rust]
needs: [call_get_workflow_version, call_get_app_metadata]
uses: ./.github/workflows/_get_app_manifest.yml
with:
ledger-app-workflows_ref: ${{ needs.call_get_workflow_version.outputs.version }}
run_for_devices: ${{ inputs.run_for_devices }}
relative_app_directory: ${{ inputs.relative_app_directory }}
is_rust: ${{ needs.call_check_is_rust.outputs.is_rust }}
run_for_devices: ${{ needs.call_get_app_metadata.outputs.compatible_devices }}
relative_app_directory: ${{ needs.call_get_app_metadata.outputs.build_directory }}
is_rust: ${{ needs.call_get_app_metadata.outputs.is_rust }}
upload_manifest_artifact_name: manifests

call_check_icons:
Expand Down Expand Up @@ -81,9 +94,9 @@ jobs:

call_clang_static_analyzer:
name: Dispatch check
needs: call_check_is_rust
needs: call_get_app_metadata
uses: ./.github/workflows/_check_clang_static_analyzer.yml
with:
run_for_devices: ${{ inputs.run_for_devices }}
relative_app_directory: ${{ inputs.relative_app_directory }}
is_rust: ${{ needs.call_check_is_rust.outputs.is_rust }}
run_for_devices: ${{ needs.call_get_app_metadata.outputs.compatible_devices }}
relative_app_directory: ${{ needs.call_get_app_metadata.outputs.build_directory }}
is_rust: ${{ needs.call_get_app_metadata.outputs.is_rust }}
Loading

0 comments on commit 8fe54ca

Please sign in to comment.