[add] Job to generate a new SDK and creating a commit in SDK repository
This commit is contained in:
67
.github/actions/commit-changes/action.yml
vendored
Normal file
67
.github/actions/commit-changes/action.yml
vendored
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
name: 'Commit and push if the version file has changed'
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
name:
|
||||||
|
description: 'The name of the commiter'
|
||||||
|
required: true
|
||||||
|
default: 'github-actions[bot]'
|
||||||
|
email:
|
||||||
|
description: 'The email of the commiter'
|
||||||
|
required: true
|
||||||
|
default: 'github-actions[bot]@users.noreply.github.com'
|
||||||
|
message:
|
||||||
|
description: 'The commit message'
|
||||||
|
required: true
|
||||||
|
default: 'New release version(s)'
|
||||||
|
files:
|
||||||
|
description: 'The file(s) to add in the commit'
|
||||||
|
required: true
|
||||||
|
default: '*'
|
||||||
|
directory:
|
||||||
|
description: 'The directory in which the action will be performed'
|
||||||
|
required: true
|
||||||
|
default: '.'
|
||||||
|
branch:
|
||||||
|
description: 'Checkout (or create) on a specific branch before commit/push'
|
||||||
|
required: true
|
||||||
|
default: 'master'
|
||||||
|
secret:
|
||||||
|
description: 'A token allowing to push the commit on the repository'
|
||||||
|
required: true
|
||||||
|
default: '.'
|
||||||
|
repository:
|
||||||
|
description: 'The repository where to push'
|
||||||
|
required: true
|
||||||
|
default: ''
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: 'composite'
|
||||||
|
steps:
|
||||||
|
- name: Commit the changes
|
||||||
|
run: |
|
||||||
|
git config --global user.name ${{ inputs.name }}
|
||||||
|
ORIGIN="$(pwd)"
|
||||||
|
cd ${{ inputs.directory }}
|
||||||
|
git switch ${{ inputs.branch }} 2>/dev/null || git switch -c ${{ inputs.branch }}
|
||||||
|
git status
|
||||||
|
CHANGES="$(git status --porcelain ${{ inputs.files }})"
|
||||||
|
if [ -z "${CHANGES}" ]; \
|
||||||
|
then \
|
||||||
|
echo "No changes, stopping now"; \
|
||||||
|
cd ${origin} \
|
||||||
|
exit 0; \
|
||||||
|
fi
|
||||||
|
echo -e "Changes:\n${CHANGES}"
|
||||||
|
git add ${{ inputs.files }}
|
||||||
|
git commit -am "${{ inputs.message }}"
|
||||||
|
git log -n 2
|
||||||
|
cd ${ORIGIN}
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Push commit
|
||||||
|
uses: ad-m/github-push-action@master
|
||||||
|
with:
|
||||||
|
github_token: ${{ inputs.secret }}
|
||||||
|
branch: ${{ inputs.branch }}
|
||||||
|
directory: ${{ inputs.directory }}
|
||||||
|
repository: ${{ inputs.repository }}
|
||||||
43
.github/workflows/sdk-generation.yml
vendored
Normal file
43
.github/workflows/sdk-generation.yml
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
name: Updating the SDK
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- develop
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
updating_SDK:
|
||||||
|
name: Updating the SDK
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Clone
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
# by default the action uses fetch-depth = 1, which creates
|
||||||
|
# shallow repositories from which we can't push
|
||||||
|
fetch-depth: 0
|
||||||
|
submodules: recursive
|
||||||
|
# needed, else the push inside the action will use default credentials
|
||||||
|
# instead of provided ones
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Build new SDK
|
||||||
|
run: python tools/build_sdk.py
|
||||||
|
|
||||||
|
- name: Extract branch name
|
||||||
|
shell: bash
|
||||||
|
run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
|
||||||
|
id: extract_branch
|
||||||
|
|
||||||
|
- name: Commit & push changes in the SDK if any
|
||||||
|
uses: ./.github/actions/commit-changes
|
||||||
|
with:
|
||||||
|
name: 'ldg-github-ci'
|
||||||
|
directory: ethereum-plugin-sdk
|
||||||
|
branch: ${{ steps.extract_branch.outputs.branch }}
|
||||||
|
message: "[update] Branch ${{ steps.extract_branch.outputs.branch }} | Commit ${GITHUB_SHA}"
|
||||||
|
secret: ${{ secrets.CI_BOT_TOKEN }}
|
||||||
|
repository: LedgerHQ/ethereum-plugin-sdk
|
||||||
2
Makefile
2
Makefile
@@ -389,7 +389,7 @@ $(shell git submodule update --init)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
# rebuild
|
# rebuild
|
||||||
$(shell python3 ethereum-plugin-sdk/build_sdk.py)
|
$(shell python3 tools/build_sdk.py)
|
||||||
$(shell find ./ethereum-plugin-sdk -iname '*.h' -o -iname '*.c' | xargs clang-format-10 -i)
|
$(shell find ./ethereum-plugin-sdk -iname '*.h' -o -iname '*.c' | xargs clang-format-10 -i)
|
||||||
|
|
||||||
# check if a difference is noticed (fail if it happens in CI build)
|
# check if a difference is noticed (fail if it happens in CI build)
|
||||||
|
|||||||
180
tools/build_sdk.py
Executable file
180
tools/build_sdk.py
Executable file
@@ -0,0 +1,180 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
'''
|
||||||
|
This script extract a few specific definitions from app-ethereum that are
|
||||||
|
required to exchange information with ethereum external plugins.
|
||||||
|
It should always be launched from app-ethereum:
|
||||||
|
|
||||||
|
python3 ethereum-plugin-sdk/build_sdk.py
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
def extract_from_headers(sources, nodes_to_extract):
|
||||||
|
cat_sources = []
|
||||||
|
for source in sources:
|
||||||
|
with open(source, 'r') as f:
|
||||||
|
cat_sources += f.readlines()
|
||||||
|
|
||||||
|
sdk_body = []
|
||||||
|
for key, values in nodes_to_extract.items():
|
||||||
|
for value in values:
|
||||||
|
node = []
|
||||||
|
unclosed_curvy_brackets = False
|
||||||
|
unclosed_parantheses = False
|
||||||
|
for line in cat_sources:
|
||||||
|
if key in line and value in line:
|
||||||
|
node += [line]
|
||||||
|
unclosed_curvy_brackets = line.count('{') - line.count('}')
|
||||||
|
if unclosed_curvy_brackets == False:
|
||||||
|
break
|
||||||
|
elif (key == "fn" and value in line) or unclosed_parantheses:
|
||||||
|
node += [line]
|
||||||
|
unclosed_parantheses = line.find(")") == -1
|
||||||
|
if unclosed_parantheses == False:
|
||||||
|
break
|
||||||
|
elif unclosed_curvy_brackets:
|
||||||
|
node += [line]
|
||||||
|
unclosed_curvy_brackets += line.count(
|
||||||
|
'{') - line.count('}')
|
||||||
|
if unclosed_curvy_brackets:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
sdk_body += [''.join(node)]
|
||||||
|
|
||||||
|
return '\n'.join(sdk_body)
|
||||||
|
|
||||||
|
|
||||||
|
def extract_from_c_files(sources, nodes_to_extract):
|
||||||
|
cat_sources = []
|
||||||
|
for source in sources:
|
||||||
|
with open(source, 'r') as f:
|
||||||
|
cat_sources += f.readlines()
|
||||||
|
|
||||||
|
sdk_body = []
|
||||||
|
for node_name in nodes_to_extract:
|
||||||
|
node = []
|
||||||
|
copying = False
|
||||||
|
wait_curvy_bracket = True
|
||||||
|
for line in cat_sources:
|
||||||
|
if node_name in line:
|
||||||
|
copying = True
|
||||||
|
node += [line]
|
||||||
|
unclosed_curvy_brackets = line.count('{') - line.count('}')
|
||||||
|
elif copying:
|
||||||
|
node += [line]
|
||||||
|
unclosed_curvy_brackets += line.count('{') - line.count('}')
|
||||||
|
if wait_curvy_bracket:
|
||||||
|
wait_curvy_bracket = line.count('}') == 0
|
||||||
|
if unclosed_curvy_brackets != 0 or wait_curvy_bracket:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
sdk_body += [''.join(node)]
|
||||||
|
|
||||||
|
return '\n'.join(sdk_body)
|
||||||
|
|
||||||
|
|
||||||
|
def merge_headers(sources, nodes_to_extract):
|
||||||
|
includes = [
|
||||||
|
'#include "os.h"',
|
||||||
|
'#include "cx.h"',
|
||||||
|
'#include <stdbool.h>',
|
||||||
|
'#include <string.h>'
|
||||||
|
]
|
||||||
|
|
||||||
|
body = extract_from_headers(sources, nodes_to_extract)
|
||||||
|
|
||||||
|
eth_internals_h = '\n\n'.join([
|
||||||
|
"/* This file is auto-generated, don't edit it */",
|
||||||
|
"#pragma once",
|
||||||
|
'\n'.join(includes),
|
||||||
|
body
|
||||||
|
])
|
||||||
|
|
||||||
|
with open("ethereum-plugin-sdk/include/eth_internals.h", 'w') as f:
|
||||||
|
f.write(eth_internals_h)
|
||||||
|
|
||||||
|
|
||||||
|
def copy_header(header_to_copy, merged_headers):
|
||||||
|
|
||||||
|
merged_headers = [os.path.basename(path) for path in merged_headers]
|
||||||
|
|
||||||
|
with open(header_to_copy, 'r') as f:
|
||||||
|
source = f.readlines()
|
||||||
|
|
||||||
|
eth_plugin_interface_h = [
|
||||||
|
"/* This file is auto-generated, don't edit it */\n"]
|
||||||
|
for line in source:
|
||||||
|
eth_plugin_interface_h += [line]
|
||||||
|
for header in merged_headers:
|
||||||
|
if header in line:
|
||||||
|
del eth_plugin_interface_h[-1]
|
||||||
|
break
|
||||||
|
|
||||||
|
# add '#include "eth_internals.h"'
|
||||||
|
include_index = eth_plugin_interface_h.index('#include "cx.h"\n')
|
||||||
|
eth_plugin_interface_h.insert(
|
||||||
|
include_index+1, '#include "eth_internals.h"\n')
|
||||||
|
|
||||||
|
# dump to file
|
||||||
|
with open("ethereum-plugin-sdk/include/eth_plugin_interface.h", 'w') as f:
|
||||||
|
f.writelines(eth_plugin_interface_h)
|
||||||
|
|
||||||
|
|
||||||
|
def merge_c_files(sources, nodes_to_extract):
|
||||||
|
includes = [
|
||||||
|
'#include "eth_internals.h"'
|
||||||
|
]
|
||||||
|
|
||||||
|
body = extract_from_c_files(sources, nodes_to_extract)
|
||||||
|
|
||||||
|
eth_internals_h = '\n\n'.join([
|
||||||
|
"/* This file is auto-generated, don't edit it */",
|
||||||
|
'\n'.join(includes),
|
||||||
|
body
|
||||||
|
])
|
||||||
|
|
||||||
|
with open("ethereum-plugin-sdk/include/eth_internals.c", 'w') as f:
|
||||||
|
f.write(eth_internals_h)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
# some nodes will be extracted from these headers and merged into a new one, copied to sdk
|
||||||
|
headers_to_merge = [
|
||||||
|
"src/tokens.h",
|
||||||
|
"src/chainConfig.h",
|
||||||
|
"src/utils.h",
|
||||||
|
"src_common/ethUstream.h",
|
||||||
|
"src_common/ethUtils.h",
|
||||||
|
"src/shared_context.h",
|
||||||
|
"src/eth_plugin_internal.h",
|
||||||
|
"src/nft.h",
|
||||||
|
]
|
||||||
|
nodes_to_extract = {
|
||||||
|
"#define": ["MAX_TICKER_LEN", "ADDRESS_LENGTH", "INT256_LENGTH", "WEI_TO_ETHER", "SELECTOR_SIZE", "PARAMETER_LENGTH", "RUN_APPLICATION", "COLLECTION_NAME_MAX_LEN"],
|
||||||
|
"typedef enum": [],
|
||||||
|
"typedef struct": ["tokenDefinition_t", "txInt256_t", "txContent_t", "nftInfo_t"],
|
||||||
|
"typedef union": ["extraInfo_t"],
|
||||||
|
"__attribute__((no_instrument_function)) inline": ["int allzeroes"],
|
||||||
|
"const": ["HEXDIGITS"],
|
||||||
|
"fn": ["void getEthAddressStringFromBinary", "void getEthAddressFromKey", "void getEthDisplayableAddress", "bool adjustDecimals", "bool uint256_to_decimal", "void amountToString", "void u64_to_string", "void copy_address", "void copy_parameter"]
|
||||||
|
}
|
||||||
|
merge_headers(headers_to_merge, nodes_to_extract)
|
||||||
|
|
||||||
|
# this header will be stripped from all #include related to previously merged headers, then copied to sdk
|
||||||
|
copy_header("src/eth_plugin_interface.h", headers_to_merge)
|
||||||
|
|
||||||
|
# extract and merge function bodies
|
||||||
|
c_files_to_merge = [
|
||||||
|
"src/utils.c",
|
||||||
|
"src_common/ethUtils.c",
|
||||||
|
"src/eth_plugin_internal.c"
|
||||||
|
]
|
||||||
|
merge_c_files(c_files_to_merge, nodes_to_extract["fn"])
|
||||||
Reference in New Issue
Block a user