Skip to content

Commit

Permalink
Merge pull request #1 from gonner22/master
Browse files Browse the repository at this point in the history
Initial commit
lemois-1337 authored Sep 20, 2024
2 parents 9e14b65 + 4bbb46f commit 3964c7e
Showing 7 changed files with 20 additions and 413 deletions.
146 changes: 7 additions & 139 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Build the docker images and push them to GitHub Packages
# Build and push only the legacy Docker image

name: Publish Docker images

@@ -37,13 +37,10 @@ jobs:
GHCR_TOKEN=$(echo ${{ secrets.GITHUB_TOKEN }} | base64)
# Get tags of all images from GHCR
TAGS_FULL=$(curl -H "Authorization: Bearer ${GHCR_TOKEN}" https://ghcr.io/v2/${REPO_PATH,,}/${REPO_NAME,,}/tags/list)
TAGS_LITE=$(curl -H "Authorization: Bearer ${GHCR_TOKEN}" https://ghcr.io/v2/${REPO_PATH,,}/${REPO_NAME,,}-lite/tags/list)
TAGS_LEGACY=$(curl -H "Authorization: Bearer ${GHCR_TOKEN}" https://ghcr.io/v2/${REPO_PATH,,}/${REPO_NAME,,}-legacy/tags/list)
TAGS_DEV_TOOLS=$(curl -H "Authorization: Bearer ${GHCR_TOKEN}" https://ghcr.io/v2/${REPO_PATH,,}/ledger-app-dev-tools/tags/list)
# Concatenate all tags from json fields in one string without brackets
ALL_TAGS=$(echo $TAGS_FULL $TAGS_LITE $TAGS_LEGACY $TAGS_DEV_TOOLS | jq -s '.[0].tags + .[1].tags + .[2].tags + .[3].tags' | tr -d '[]')
ALL_TAGS=$(echo $TAGS_LEGACY | jq -s '.[0].tags' | tr -d '[]')
# Get the tag to find
TAG_TO_FIND=${{ steps.get-current-version.outputs.current_version }}
@@ -58,7 +55,6 @@ jobs:
outputs:
current_version: ${{ steps.get-current-version.outputs.current_version }}


mods_list:
name: Get modified files
runs-on: ubuntu-latest
@@ -74,59 +70,18 @@ jobs:
outputs:
modified_files: ${{ steps.get-changes.outputs.all_modified_files }}

builder_lite:
name: App Builder Lite
builder_legacy:
name: App Builder Legacy
runs-on: ubuntu-latest
needs: [mods_list, check_changelog]
if: needs.check_changelog.result == 'success' && contains(needs.mods_list.outputs.modified_files, 'lite/Dockerfile')
if: always() && needs.check_changelog.result == 'success' && (needs.builder_lite.result == 'success' || (contains(needs.mods_list.outputs.modified_files, 'legacy/Dockerfile')))
permissions:
packages: write

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

- name: Login to registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Make full image name
run: |
echo "IMAGE=${REGISTRY}/${REPO_PATH,,}/${REPO_NAME,,}-lite" >>${GITHUB_ENV}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.IMAGE }}

- name: Set-up QEMU
uses: docker/setup-qemu-action@v2

- name: Set-up Buildx
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Build and push container
uses: docker/build-push-action@v3
with:
file: lite/Dockerfile
platforms: ${{ env.BUILD_PLATFORMS }}
tags: ${{ env.IMAGE }}:${{ github.sha }},${{ env.IMAGE }}:latest,${{ env.IMAGE }}:${{ needs.check_changelog.outputs.current_version }}
labels: ${{ steps.meta.outputs.labels }}
push: false

builder_legacy:
name: App Builder Legacy
runs-on: ubuntu-latest
needs: [mods_list, check_changelog, builder_lite]
if: always() && needs.check_changelog.result == 'success' && (needs.builder_lite.result == 'success' || (needs.builder_lite.result == 'skipped' && contains(needs.mods_list.outputs.modified_files, 'legacy/Dockerfile')))
permissions:
packages: write

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

@@ -151,94 +106,7 @@ jobs:
uses: docker/build-push-action@v3
with:
file: legacy/Dockerfile
tags: ${{ env.IMAGE }}:${{ github.sha }},${{ env.IMAGE }}:latest,${{ env.IMAGE }}:${{ needs.check_changelog.outputs.current_version }}
labels: ${{ steps.meta.outputs.labels }}
push: false

builder:
name: App Builder
runs-on: ubuntu-latest
needs: [mods_list, check_changelog, builder_lite]
if: always() && needs.check_changelog.result == 'success' && (needs.builder_lite.result == 'success' || (needs.builder_lite.result == 'skipped' && contains(needs.mods_list.outputs.modified_files, 'full/Dockerfile')))
permissions:
packages: write

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

- name: Login to registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Make full image name
run: |
echo "IMAGE=${REGISTRY}/${REPO_PATH,,}/${REPO_NAME,,}" >>${GITHUB_ENV}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.IMAGE }}

- name: Set-up QEMU
uses: docker/setup-qemu-action@v2

- name: Set-up Buildx
uses: docker/setup-buildx-action@v2

- name: Build and push container
uses: docker/build-push-action@v3
with:
file: full/Dockerfile
platforms: ${{ env.BUILD_PLATFORMS }}
tags: ${{ env.IMAGE }}:${{ github.sha }},${{ env.IMAGE }}:latest,${{ env.IMAGE }}:${{ needs.check_changelog.outputs.current_version }}
labels: ${{ steps.meta.outputs.labels }}
push: false

dev_tools:
name: App Developer Tools
runs-on: ubuntu-latest
needs: [mods_list, check_changelog, builder]
if: always() && needs.check_changelog.result == 'success' && (needs.builder.result == 'success' || (needs.builder.result == 'skipped' && contains(needs.mods_list.outputs.modified_files, 'dev-tools/Dockerfile')))
permissions:
packages: write

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

- name: Login to registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Make full image name
run: |
echo "IMAGE=${REGISTRY}/${REPO_PATH,,}/ledger-app-dev-tools" >>${GITHUB_ENV}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.IMAGE }}

- name: Set-up QEMU
uses: docker/setup-qemu-action@v2

- name: Set-up Buildx
uses: docker/setup-buildx-action@v2

- name: Build and push container
uses: docker/build-push-action@v3
with:
file: dev-tools/Dockerfile
platforms: ${{ env.BUILD_PLATFORMS }}
tags: ${{ env.IMAGE }}:${{ github.sha }},${{ env.IMAGE }}:latest,${{ env.IMAGE }}:${{ needs.check_changelog.outputs.current_version }}
labels: ${{ steps.meta.outputs.labels }}
push: false
push: true
90 changes: 11 additions & 79 deletions README.md
Original file line number Diff line number Diff line change
@@ -2,29 +2,20 @@

These container images contain all dependencies to compile an application for Ledger devices

The four images are stored in the following directories:
The image is stored in the following directory:

- `lite` is based on `Alpine` and is the lightest of the app-builder docker images. It contains the sufficient tools to build and load applications in the `C` language. It does **not** contain the `glibc`, so tools/analyzers using it won't work.
- `full` is the default image. It derives from `lite` and contains tools allowing `Rust` compilation.
- `dev-tools` is based on the `full` image and contains more tools for testing : the [Ragger](https://github.com/LedgerHQ/ragger) test framework and the [Speculos](https://github.com/LedgerHQ/speculos) emulator. Mostly useful for macOS and Windows users who want to quickly setup a more complete development environment.
- `legacy` contains all needed tools to compile `C` and `Rust` applications. This image is quite heavy, but based on Ubuntu 22.04, so it is a good pick for tools using the `glibc`, such as `SonarQube` or `CodeQL`.

## Using Ledger images
## Using Ledger image

To use or build these container images, first install Docker on you computer.

The images corresponding to the previous Dockerfiles are built and pushed on [ghcr.io](ghcr.io) every time the SDK is updated.
They can be pulled via these commands:

```bash
# pull the default, full image, built from `full/Dockerfile`
$ docker pull ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest
# pull the lite image, built from `lite/Dockerfile`
$ docker pull ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest
# pull the dev-tools image, built from `dev-tools/Dockerfile`
$ docker pull ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest
# pull the legacy image, built from `legacy/Dockerfile`
$ docker pull ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-legacy:latest
$ docker pull ghcr.io/karlsen-network/ledger-app-builder/ledger-app-builder-legacy:latest
```

## Compile your app in the container
@@ -35,100 +26,40 @@ In the source folder of your application, you can compile with the following com

* For Nano S
```bash
$ sudo docker run --rm -ti -v "$(realpath .):/app" --user $(id -u $USER):$(id -g $USER) ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest
$ sudo docker run --rm -ti -v "$(realpath .):/app" --user root ghcr.io/karlsen-network/ledger-app-builder/ledger-app-builder-legacy:latest
bash$ BOLOS_SDK=$NANOS_SDK make
```

* For Nano X
```bash
$ sudo docker run --rm -ti -v "$(realpath .):/app" --user $(id -u $USER):$(id -g $USER) ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest
bash$ BOLOS_SDK=$NANOX_SDK make
```

* For Nano S+
```bash
$ sudo docker run --rm -ti -v "$(realpath .):/app" --user $(id -u $USER):$(id -g $USER) ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest
$ sudo docker run --rm -ti -v "$(realpath .):/app" --user root ghcr.io/karlsen-network/ledger-app-builder/ledger-app-builder-legacy:latest
bash$ BOLOS_SDK=$NANOSP_SDK make
```

* For Stax
```bash
$ sudo docker run --rm -ti -v "$(realpath .):/app" --user $(id -u $USER):$(id -g $USER) ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest
$ sudo docker run --rm -ti -v "$(realpath .):/app" --user root ghcr.io/karlsen-network/ledger-app-builder/ledger-app-builder-legacy:latest
bash$ BOLOS_SDK=$STAX_SDK make
```

* For Flex
```bash
$ sudo docker run --rm -ti -v "$(realpath .):/app" --user $(id -u $USER):$(id -g $USER) ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest
bash$ BOLOS_SDK=$FLEX_SDK make
```

### Code static analysis

The Docker images include the [Clang Static Analyzer](https://clang-analyzer.llvm.org/), which can be invoked with:

```bash
$ sudo docker run --rm -ti -v "$(realpath .):/app" --user $(id -u $USER):$(id -g $USER) ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest
$ sudo docker run --rm -ti -v "$(realpath .):/app" --user root ghcr.io/karlsen-network/ledger-app-builder/ledger-app-builder-legacy:latest
bash$ BOLOS_SDK=$NANOS_SDK make scan-build
```

## App testing

With the `ledger-app-dev-tools` image, whether you are developing on macOS, Windows or Linux, you can quickly test your app with the [Speculos](https://github.com/LedgerHQ/speculos) emulator or the [Ragger](https://github.com/LedgerHQ/ragger) test framework.
For examples of functional tests implemented with Ragger, you can have a look at the [app-boilerplate](https://github.com/LedgerHQ/app-boilerplate)

First, run the `ledger-app-dev-tools` docker image. Depending on your platform, the command will change slightly :

**Linux (Ubuntu)**

```bash
sudo docker run --rm -ti -v "$(realpath .):/app" --user $(id -u):$(id -g) -v "/tmp/.X11-unix:/tmp/.X11-unix" -e DISPLAY=$DISPLAY ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest
```

**Windows (with PowerShell)**

Assuming you already have a running X server like [VcXsrv](https://sourceforge.net/projects/vcxsrv/) configured to accept client connections.

```bash
docker run --rm -ti -v "$(Get-Location):/app" -e DISPLAY="host.docker.internal:0" ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest
```

**macOS**

Assuming you already have a running X server like [XQuartz](https://www.xquartz.org/) configured to accept client connections.

```bash
sudo docker run --rm -ti -v "$(pwd -P):/app" --user $(id -u):$(id -g) -v "/tmp/.X11-unix:/tmp/.X11-unix" -e DISPLAY="host.docker.internal:0" ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest
```

Then you can test your app either with the Speculos emulator :

```bash
# Run your app on Speculos
bash$ speculos build/nanos/bin/app.elf --model nanos
```

Or you can run your Ragger functional tests if you have implemented them :

```bash
# Creating a virtualenv so that the non-root user can install Python dependencies
bash$ python -m virtualenv venv --system-site-package
bash$ source ./venv/bin/activate
# Install tests dependencies
(venv) bash$ pip install -r tests/requirements.txt
# Run ragger functional tests
(venv) bash$ python -m pytest tests/ --tb=short -v --device nanos --display
```

## Load the app on a physical device

:warning: Only Nano S, Nano S+, Stax and Flex devices allow application side-loading. This section will not work with a Nano X.
:warning: Only Nano S, Nano S+ and Stax devices allow application side-loading. This section will not work with a Nano X.

To load the app from the container, you will need additional docker arguments in order to allow Docker to access your USB port.
Your physical device must be connected, unlocked and the screen showing the dashboard (not inside an application). Same as for compilation, `BOLOS_SDK` variable is used to specify the target device. Use the following docker command to load the app (here for Nano S device) :

```bash
$ sudo docker run --rm -ti -v "$(realpath .):/app" --privileged -v "/dev/bus/usb:/dev/bus/usb" --user $(id -u $USER):$(id -g $USER) ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest
$ sudo docker run --rm -ti -v "$(realpath .):/app" --privileged -v "/dev/bus/usb:/dev/bus/usb" --user root ghcr.io/karlsen-network/ledger-app-builder/ledger-app-builder-legacy:latest
bash$ BOLOS_SDK=$NANOS_SDK make load
```

@@ -142,7 +73,7 @@ If the provided images does not suit your needs or you want to tinker with them,
Containers can be built using `Docker`:

```bash
$ (cd full && sudo docker build -t ledger-app-builder:latest .)
$ (cd full && sudo docker build -t ledger-app-builder-legacy:latest .)
```

### App Scanner
@@ -156,3 +87,4 @@ Then, build container from the `coverity/` directory with:
```bash
$ (cd full && sudo docker build -t ledger-app-scanner:latest .)
```

23 changes: 0 additions & 23 deletions dev-tools/Dockerfile

This file was deleted.

Loading

0 comments on commit 3964c7e

Please sign in to comment.