Skip to content

LoRa E2E CI

LoRa E2E CI #536

Workflow file for this run

name: LoRa E2E CI
concurrency: e2e
on: # rebuild any PRs and main branch changes
schedule:
- cron: '59 23 * * 1,2,3,4,5'
pull_request:
types: [labeled]
workflow_dispatch:
inputs:
RunE2ETestsOnly:
description: 'Run E2E tests only'
default: false
RunLoadTests:
description: 'Include Load Tests in current run'
default: 'false'
TestsToRun:
default: '[SensorDecodingTest,OTAAJoinTest,ABPTest,OTAATest,MacTest,ClassCTest,C2DMessageTest,MultiGatewayTest,MultiConcentratorTest,CupsTest,LnsDiscoveryTest,CloudDeploymentTest]'
description: 'tests to run'
TxPower:
description: 'TXPower value to use in E2E tests'
default: '6'
env:
BUILD_CONFIGURATION: 'Release'
TESTS_FOLDER: Tests
TESTS_RESULTS_FOLDER: Tests/TestResults
# these environments variable are for the deployment to IoT Edge
CONTAINER_REGISTRY_ADDRESS: "${{ secrets.CI_ACR_NAME }}.azurecr.io"
CONTAINER_REGISTRY_USERNAME: "${{ secrets.CI_ACR_NAME }}"
CONTAINER_REGISTRY_PASSWORD: ${{ secrets.CI_ACR_CREDENTIALS }}
IOT_EDGE_DEPLOYMENT_ID: ""
NET_SRV_LOG_LEVEL: 1
NET_SRV_LOG_TO_HUB: false
NET_SRV_LOG_TO_TCP: true
NET_SRV_IOTEDGE_TIMEOUT: 0
EDGEHUB_ROUTE: "FROM /* INTO $upstream"
RESET_PIN: 7
REGION: "EU"
EDGEHUB_OPTIMIZEFORPERFORMANCE: false
EDGEHUB_MQTTSETTINGS_ENABLED: false
EDGEHUB_HTTPSETTINGS_ENABLED: false
# these are used for the docker tag computation
BUILD_BUILDID: ${{ github.run_id }}
DEV_IMAGE_TAG: dev
MASTER_IMAGE_TAG: master
MAJOR_VERSION: 2
jobs:
env_var:
name: Set environment variables
runs-on: ubuntu-latest
steps:
- id: e2e_list_step
shell: bash
name: Set E2E tests to run
run: |
if [ ${{ github.event_name }} == 'workflow_dispatch' ]; then
echo "Set up for workflow dispatch"
echo "::set-output name=E2ETestsToRun::${{ github.event.inputs.TestsToRun }}"
elif [ ${{ github.event_name }} == 'pull_request' ]; then
echo "Set up for pull request"
echo "::set-output name=E2ETestsToRun::[SensorDecodingTest,OTAAJoinTest,ABPTest,OTAATest,MacTest,ClassCTest,C2DMessageTest,MultiGatewayTest,MultiConcentratorTest,CupsTest,LnsDiscoveryTest,CloudDeploymentTest]"
else
echo "Set up for cron trigger"
echo "::set-output name=E2ETestsToRun::[SensorDecodingTest,OTAAJoinTest,ABPTest,OTAATest,MacTest,ClassCTest,C2DMessageTest,MultiGatewayTest,MultiConcentratorTest,CupsTest,LnsDiscoveryTest,CloudDeploymentTest]"
fi
- id: check-if-run
name: Check if deploy on local ci
shell: bash
if: github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'fullci' ) != true
run: |
echo "::set-output name=StopFullCi::true"
- id: set_txpower
name: Set TXPower value
shell: bash
run: |
if [ ${{ github.event.inputs.TxPower }} -ge 1 ] && [ ${{ github.event.inputs.TxPower }} -le 14 ]; then
txPower=${{ github.event.inputs.TxPower }}
else
txPower=14
fi
echo "Setting TxPower to $txPower"
echo "::set-output name=TxPower::$txPower"
outputs:
RunE2ETestsOnly: ${{ github.event.inputs.RunE2ETestsOnly == 'true' || contains(github.event.client_payload.labels.*.name, 'RunE2ETestsOnly') == true}}
E2ETestsToRun: ${{ steps.e2e_list_step.outputs.E2ETestsToRun }}
StopFullCi: ${{ steps.check-if-run.outputs.StopFullCi }}
TxPower: ${{ steps.set_txpower.outputs.TxPower }}
CertRemotePath: "/var/lorastarterkit/certs"
power_on_azure_vm:
name: Power ON EFLOW
if: needs.env_var.outputs.StopFullCi != 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Power ON Azure VM
uses: ./.github/actions/power-azure-vm
with:
AZURE_VM_NAME: eflow
AZURE_RG_NAME: lorae2etests
POWER_SWITCH: true
AZURE_SP_CLIENTID: ${{ secrets.AZURE_SP_CLIENTID }}
AZURE_SP_SECRET: ${{ secrets.AZURE_SP_SECRET }}
AZURE_TENANTID: ${{ secrets.AZURE_TENANTID }}
reset_redis_cache:
name: Reset the Redis Cache
if: needs.env_var.outputs.StopFullCi != 'true'
runs-on: ubuntu-latest
steps:
- name: Flush the database
shell: bash
run: |
wget https://github.com/IBM-Cloud/redli/releases/download/v0.5.2/redli_0.5.2_linux_amd64.tar.gz
tar xzf redli_0.5.2_linux_amd64.tar.gz
chmod +x redli
./redli --tls -h ${{ secrets.REDIS_HOSTNAME }}.redis.cache.windows.net -p 6380 -a ${{ secrets.REDIS_PASSWORD }} FLUSHALL
# Build and deploy Facade Azure Function
deploy_facade_function:
environment:
name: CI_AZURE_ENVIRONMENT
needs:
- env_var
name: Build and Deploy Facade Azure Function
runs-on: ubuntu-latest
if: needs.env_var.outputs.RunE2ETestsOnly != 'true' && needs.env_var.outputs.StopFullCi != 'true'
env:
AZURE_FUNCTIONAPP_PACKAGE_PATH: 'LoRaEngine/LoraKeysManagerFacade/'
steps:
- uses: actions/checkout@v3
name: Checkout current branch
- uses: actions/setup-dotnet@v3.0.1
with:
dotnet-version: '6.0.x'
- name: 'Resolve Project Dependencies Using Dotnet'
shell: bash
run: |
pushd './${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}'
dotnet build --configuration ${{ env.BUILD_CONFIGURATION }} --output ./output
popd
- name: 'Run Azure Functions Action'
uses: Azure/functions-action@v1
id: fa
with:
app-name: ${{ secrets.FUNCTION_FACADE_APP_NAME }}
package: '${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}output'
publish-profile: ${{ secrets.AZURE_FUNCTIONAPP_PUBLISH_PROFILE }}
build_push_docker_images:
needs:
- env_var
name: Build and Push Docker images
runs-on: ubuntu-latest
env:
DEV_IMAGE_TAG: dev
MASTER_IMAGE_TAG: master
if: needs.env_var.outputs.RunE2ETestsOnly != 'true' && needs.env_var.outputs.StopFullCi != 'true'
steps:
- uses: actions/checkout@v3
name: Checkout current branch
with:
fetch-depth: '2'
- id: image_tag_definition
run: |
if [ ${{ github.ref }} = "refs/heads/dev" ]; then
echo "dev"
IMAGE_TAG="$DEV_IMAGE_TAG"
elif [ ${{ github.ref }} = "refs/heads/master" ]; then
echo "master"
IMAGE_TAG="$MASTER_IMAGE_TAG"
elif [ ${{ github.event_name }} == "pull_request" ]; then
echo "pull request"
IMAGE_TAG="pr-${{ github.event.number}}"
else
echo "all others"
IMAGE_TAG="custom-${GITHUB_REF##*/}"
fi
echo "Using image tag prefix $IMAGE_TAG"
IMAGE_TAG="$MAJOR_VERSION.${{ github.run_number }}.$IMAGE_TAG-${{ github.run_attempt }}"
echo "Using image tag $IMAGE_TAG"
echo "::set-env name=NET_SRV_VERSION::$IMAGE_TAG"
echo "::set-env name=LBS_VERSION::$IMAGE_TAG"
echo "::set-output name=imagetag::$IMAGE_TAG"
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
- uses: docker/setup-buildx-action@v2
id: buildx
with:
install: true
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Build Docker LoRaWanNetworkServer images
run: |
echo ${{ env.CONTAINER_REGISTRY_PASSWORD }} | docker login "${{ env.CONTAINER_REGISTRY_ADDRESS }}" --username "${{ env.CONTAINER_REGISTRY_USERNAME }}" --password-stdin
docker buildx bake --push LoRaWanNetworkServerarm32 LoRaWanNetworkServerarm64v8 LoRaWanNetworkServerx64
working-directory: LoRaEngine
env:
CONTAINER_REGISTRY_ADDRESS: ${{ env.CONTAINER_REGISTRY_ADDRESS }}
# This image is very costly to rebuild and we rebuild it only when something change in the folders since last commit.
- name: Build Docker LoRaWanBasicsStation images
run: |
git diff --quiet HEAD HEAD~1 -- modules/LoRaBasicsStationModule/ || docker buildx bake --push LoraBasicsStationarm32v7 LoraBasicsStationarm64v8 --set *.args.SOURCE_CONTAINER_REGISTRY_ADDRESS=${{ env.CONTAINER_REGISTRY_ADDRESS }}
working-directory: LoRaEngine
env:
CONTAINER_REGISTRY_ADDRESS: ${{ env.CONTAINER_REGISTRY_ADDRESS }}
outputs:
imagetag: ${{ steps.image_tag_definition.outputs.imagetag }}
# Generate root and server certificates and copy required files to RPi
certificates_job :
timeout-minutes: 5
name: Generate and copy certificates
environment:
name: CI_AZURE_ENVIRONMENT
if: needs.env_var.outputs.RunE2ETestsOnly != 'true' && needs.env_var.outputs.StopFullCi != 'true'
needs:
- env_var
runs-on: [ self-hosted, x64 ]
steps:
- uses: actions/checkout@v3
name: Checkout current branch
- id: generate_step
shell: bash
name: Generate server and client certificates
env:
SERVER_PFX_PASSWORD: ${{ secrets.SERVER_PFX_PASSWORD }}
SSH_PRIVATE_KEY_PATH: ${{ secrets.SSH_PRIVATE_KEY_PATH }}
RPI_USERNAME: ${{ secrets.RPI_USERNAME }}
RPI_HOST: ${{ secrets.RPI_HOST }}
CERT_REMOTE_PATH: ${{ needs.env_var.outputs.CertRemotePath }}
CUPS_STATION_EUI: ${{ secrets.DEFAULTCUPSSTATIONEUI }}
CUPS_CREDENTIALS_BLOB_URL: ${{ secrets.CUPSCREDENTIALSBLOBURL }}
CUPS_FIRMWARE_BLOB_URL: ${{ secrets.CUPSFIRMWAREBLOBURL }}
run: |
# -- Credential generation section --
chmod +x ./Tools/BasicStation-Certificates-Generation/certificate-generate.sh
./Tools/BasicStation-Certificates-Generation/certificate-generate.sh server $RPI_HOST $SERVER_PFX_PASSWORD
./Tools/BasicStation-Certificates-Generation/certificate-generate.sh client $CUPS_STATION_EUI
# following copy commands are copying trust certificate to a pre-created $CERT_REMOTE_PATH location in local ci
cp ./Tools/BasicStation-Certificates-Generation/ca/root-ca.crt $CERT_REMOTE_PATH/tc.trust
cp ./Tools/BasicStation-Certificates-Generation/ca/root-ca.crt $CERT_REMOTE_PATH/cups.trust
cp ./Tools/BasicStation-Certificates-Generation/client/$CUPS_STATION_EUI.crt $CERT_REMOTE_PATH/cups.crt
cp ./Tools/BasicStation-Certificates-Generation/client/$CUPS_STATION_EUI.key $CERT_REMOTE_PATH/cups.key
curl -X PUT -T ./Tools/BasicStation-Certificates-Generation/client/$CUPS_STATION_EUI.bundle -H "x-ms-date: $(date -u)" -H "x-ms-blob-type: BlockBlob" "$CUPS_CREDENTIALS_BLOB_URL"
echo "::set-output name=clientbundlecrc::$(cat ./Tools/BasicStation-Certificates-Generation/client/$CUPS_STATION_EUI.bundle | gzip -1 | tail -c 8 | od -t ${1:-u}4 -N 4 -An --endian=little | xargs echo)"
echo "::set-output name=clientthumbprint::$(sha1sum $CERT_REMOTE_PATH/cups.crt | awk '{print $1;}')"
# -- Firmware upgrade generation section --
chmod +x ./Tools/Cups-Firmware-Upgrade/firmwarePrep.sh
NEW_FW_VERSION=$(date -u +%s)
sed -i "s/1.0.1-e2e/$NEW_FW_VERSION/g" ./Tools/Cups-Firmware-Upgrade/fwUpdateSample.sh
./Tools/Cups-Firmware-Upgrade/firmwarePrep.sh $CUPS_STATION_EUI "$(realpath ./Tools/Cups-Firmware-Upgrade/fwUpdateSample.sh)"
cp ./Tools/Cups-Firmware-Upgrade/$CUPS_STATION_EUI/sig-0.key $CERT_REMOTE_PATH/sig-0.key
echo "::set-output name=clientsigkeycrc::$(cat ./Tools/Cups-Firmware-Upgrade/$CUPS_STATION_EUI/sig-0.crc)"
echo "::set-output name=clientfwdigest::$(cat ./Tools/Cups-Firmware-Upgrade/$CUPS_STATION_EUI/fwUpdate.digest)"
echo "::set-output name=clientfwversion::$NEW_FW_VERSION"
curl -X PUT -T ./Tools/Cups-Firmware-Upgrade/fwUpdateSample.sh -H "x-ms-date: $(date -u)" -H "x-ms-blob-type: BlockBlob" "$CUPS_FIRMWARE_BLOB_URL"
# following commands are copying to remote "aio" device the required server and trust certificates
ssh -i $SSH_PRIVATE_KEY_PATH $RPI_USERNAME@$RPI_HOST "sudo rm -rf $CERT_REMOTE_PATH && sudo mkdir -p $CERT_REMOTE_PATH && sudo chown -R "'$(whoami)'" $CERT_REMOTE_PATH"
scp -i $SSH_PRIVATE_KEY_PATH ./Tools/BasicStation-Certificates-Generation/ca/root-ca.crt $RPI_USERNAME@$RPI_HOST:$CERT_REMOTE_PATH/tc.trust
scp -i $SSH_PRIVATE_KEY_PATH ./Tools/BasicStation-Certificates-Generation/server/$RPI_HOST.pfx $RPI_USERNAME@$RPI_HOST:$CERT_REMOTE_PATH/server.pfx
# following is needed for the proper setup of trusted ca certificate
openssl x509 -in ./Tools/BasicStation-Certificates-Generation/ca/root-ca.crt -inform DER -out ./Tools/BasicStation-Certificates-Generation/ca/root-ca.crt.pem -outform PEM
scp -i $SSH_PRIVATE_KEY_PATH ./Tools/BasicStation-Certificates-Generation/ca/root-ca.crt.pem $RPI_USERNAME@$RPI_HOST:$CERT_REMOTE_PATH/client.ca.crt
- id: get_self_hosted_runner_ip_address
shell: bash
name: Get internal Ip address of the itestup device
run: |
echo "::set-output name=itestupip::$(ip address list tun0 | grep -Po 'inet \K[\d.]+')"
outputs:
itestupip: ${{ steps.get_self_hosted_runner_ip_address.outputs.itestupip }}
clientthumbprint: ${{ steps.generate_step.outputs.clientthumbprint }}
clientbundlecrc: ${{ steps.generate_step.outputs.clientbundlecrc }}
clientsigkeycrc: ${{ steps.generate_step.outputs.clientsigkeycrc }}
clientfwdigest: ${{ steps.generate_step.outputs.clientfwdigest }}
clientfwversion: ${{ steps.generate_step.outputs.clientfwversion }}
# Deploy Cloud based LoRaWAN Network Server
deploy_cloud_lns:
needs:
- env_var
- build_push_docker_images
- certificates_job
runs-on: ubuntu-latest
if: needs.env_var.outputs.RunE2ETestsOnly != 'true' && needs.env_var.outputs.StopFullCi != 'true'
name: Deploy Cloud based LNS
steps:
- name: "Deploy container instance"
id: "deploycloudlns"
shell: bash
run: |
az login --service-principal -u ${{ secrets.AZURE_SP_CLIENTID }} -p ${{ secrets.AZURE_SP_SECRET }} --tenant ${{ secrets.AZURE_TENANTID }}
az container create --resource-group ${{ secrets.AZURE_RG }} --ip-address Private --location westeurope --name cloudlns \
--environment-variables LOG_TO_TCP_ADDRESS=${{ needs.certificates_job.outputs.itestupip }} LOG_TO_TCP_PORT=6100 LOG_TO_TCP=true LOG_LEVEL=1 IOTHUBHOSTNAME=${{secrets.IOTHUB_HOSTNAME}} ENABLE_GATEWAY=false CLOUD_DEPLOYMENT=true \
--image ${{ env.CONTAINER_REGISTRY_ADDRESS }}/lorawannetworksrvmodule:${{needs.build_push_docker_images.outputs.imagetag}}-amd64 \
--ports 5000 \
--protocol TCP \
--registry-username ${{ env.CONTAINER_REGISTRY_USERNAME }} \
--registry-password ${{ env.CONTAINER_REGISTRY_PASSWORD }} \
--restart-policy Never \
--secure-environment-variables FACADE_AUTH_CODE=${{ secrets.FUNCTION_FACADE_AUTH_CODE }} FACADE_SERVER_URL=${{ secrets.FUNCTION_FACADE_SERVER_URL }} REDIS_CONNECTION_STRING=${{ secrets.REDIS_HOSTNAME }}.redis.cache.windows.net:6380,password=${{ secrets.REDIS_PASSWORD }},ssl=True,abortConnect=False \
--subnet ${{ secrets.AZURE_SUBNET_NAME }} \
--vnet ${{ secrets.AZURE_VNET_NAME }} --output none
echo "::set-output name=cloudlnsprivateip::$(az container show --name cloudlns --resource-group ${{ secrets.AZURE_RG }} --query ipAddress.ip -o tsv)"
outputs:
cloudlnsprivateip: ${{ steps.deploycloudlns.outputs.cloudlnsprivateip }}
# Deploy IoT Edge solution to ARM gateway
deploy_arm_gw_iot_edge:
timeout-minutes: 20
environment:
name: CI_ALL_IN_ONE_ARM_GATEWAY
needs:
- env_var
- build_push_docker_images
- certificates_job
if: needs.env_var.outputs.RunE2ETestsOnly != 'true' && needs.env_var.outputs.StopFullCi != 'true'
runs-on: ubuntu-latest
name: Deploy IoT Edge on All-In-One ARM gateway
env:
EDGE_AGENT_VERSION: 1.2.6
EDGE_HUB_VERSION: 1.2.6
steps:
- uses: actions/checkout@v3
name: Checkout current branch
- name: Iot Edge Push Solution
uses: ./.github/actions/deployedge
id: deploy_edge
env:
LBS_FIXED_STATION_EUI: ${{ secrets.LBS_FIXED_STATION_EUI }}
IOTHUB_CONNECTION_STRING: ${{ secrets.IOTHUB_OWNER_CONNECTION_STRING }}
DEVICE_ID: ${{ secrets.DEVICE_ID }}
IOT_EDGE_DEPLOYMENT_ID: ${{ secrets.IOT_EDGE_DEPLOYMENT_ID }}
FACADE_SERVER_URL: ${{ secrets.FUNCTION_FACADE_SERVER_URL }}
FACADE_AUTH_CODE: ${{ secrets.FUNCTION_FACADE_AUTH_CODE }}
IOT_HUB_RESOURCE_ID: ${{ secrets.IOT_HUB_RESOURCE_ID }}
LOG_ANALYTICS_WORKSPACE_ID: ${{ secrets.LOG_ANALYTICS_WORKSPACE_ID }}
LOG_ANALYTICS_SHARED_KEY: ${{ secrets.LOG_ANALYTICS_SHARED_KEY }}
APPLICATIONINSIGHTS_CONNECTION_STRING: ${{ secrets.APPLICATIONINSIGHTS_CONNECTION_STRING }}
CERT_REMOTE_PATH: ${{ needs.env_var.outputs.CertRemotePath }}
SERVER_PFX_PASSWORD: ${{ secrets.SERVER_PFX_PASSWORD }}
NET_SRV_LOG_TO_TCP_ADDRESS: "itestup"
with:
deployment_file_name: '${{ secrets.DEPLOYMENT_FILE_NAME }}'
architecture: '${{ secrets.ARCHITECTURE }}'
iot_edge_deployment_id: '${{ secrets.IOT_EDGE_DEPLOYMENT_ID }}'
# Deploy IoT Edge solution to EFLOW gateway
deploy_eflow_gw_iot_edge:
timeout-minutes: 20
environment:
name: CI_EFLOW_AZURE_VM
needs:
- env_var
- build_push_docker_images
- certificates_job
if: needs.env_var.outputs.RunE2ETestsOnly != 'true' && needs.env_var.outputs.StopFullCi != 'true'
runs-on: ubuntu-latest
name: Deploy IoT Edge on EFLOW VM gateway
env:
DEVICE_ID: ${{ secrets.DEVICE_ID }}
NET_SRV_LOG_TO_TCP_ADDRESS: ${{ needs.certificates_job.outputs.itestupip }}
IOTHUB_CONNECTION_STRING: ${{ secrets.IOTHUB_OWNER_CONNECTION_STRING }}
FACADE_SERVER_URL: ${{ secrets.FUNCTION_FACADE_SERVER_URL }}
FACADE_AUTH_CODE: ${{ secrets.FUNCTION_FACADE_AUTH_CODE }}
EDGE_AGENT_VERSION: 1.1.8
EDGE_HUB_VERSION: 1.1.8
IOT_HUB_RESOURCE_ID: ${{ secrets.IOT_HUB_RESOURCE_ID }}
LOG_ANALYTICS_WORKSPACE_ID: ${{ secrets.LOG_ANALYTICS_WORKSPACE_ID }}
LOG_ANALYTICS_SHARED_KEY: ${{ secrets.LOG_ANALYTICS_SHARED_KEY }}
APPLICATIONINSIGHTS_CONNECTION_STRING: ${{ secrets.APPLICATIONINSIGHTS_CONNECTION_STRING }}
steps:
- uses: actions/checkout@v3
name: Checkout current branch
- name: Iot Edge Push Solution
uses: ./.github/actions/deployedge
id: deploy_edge
env:
IOTHUB_CONNECTION_STRING: ${{ secrets.IOTHUB_OWNER_CONNECTION_STRING }}
DEVICE_ID: ${{ secrets.DEVICE_ID }}
IOT_EDGE_DEPLOYMENT_ID: ${{ secrets.IOT_EDGE_DEPLOYMENT_ID }}
with:
deployment_file_name: '${{ secrets.DEPLOYMENT_FILE_NAME }}'
architecture: '${{ secrets.ARCHITECTURE }}'
iot_edge_deployment_id: '${{ secrets.IOT_EDGE_DEPLOYMENT_ID }}'
# Deploy IoT Edge solution to standalone Concentrator
deploy_eflow_concentrator_iot_edge:
timeout-minutes: 20
needs:
- env_var
- build_push_docker_images
environment:
name: CI_CONCENTRATOR_EFLOW_ARM32
if: needs.env_var.outputs.RunE2ETestsOnly != 'true' && needs.env_var.outputs.StopFullCi != 'true'
runs-on: ubuntu-latest
name: Deploy IoT Edge on ItestArm2 concentrator
env:
DEVICE_ID: ${{ secrets.DEVICE_ID }}
LBS_TC_URI: ${{ secrets.TC_URI }}
IOTHUB_CONNECTION_STRING: ${{ secrets.IOTHUB_OWNER_CONNECTION_STRING }}
FACADE_SERVER_URL: ${{ secrets.FUNCTION_FACADE_SERVER_URL }}
FACADE_AUTH_CODE: ${{ secrets.FUNCTION_FACADE_AUTH_CODE }}
EDGE_AGENT_VERSION: 1.1.8
EDGE_HUB_VERSION: 1.1.8
steps:
- uses: actions/checkout@v3
name: Checkout current branch
- name: Iot Edge Push Solution
uses: ./.github/actions/deployedge
id: deploy_edge
env:
IOTHUB_CONNECTION_STRING: ${{ secrets.IOTHUB_OWNER_CONNECTION_STRING }}
DEVICE_ID: ${{ secrets.DEVICE_ID }}
IOT_EDGE_DEPLOYMENT_ID: ${{ secrets.IOT_EDGE_DEPLOYMENT_ID }}
LBS_FIXED_STATION_EUI: ${{ secrets.LBS_FIXED_STATION_EUI }}
IOT_HUB_RESOURCE_ID: ${{ secrets.IOT_HUB_RESOURCE_ID }}
LOG_ANALYTICS_WORKSPACE_ID: ${{ secrets.LOG_ANALYTICS_WORKSPACE_ID }}
LOG_ANALYTICS_SHARED_KEY: ${{ secrets.LOG_ANALYTICS_SHARED_KEY }}
APPLICATIONINSIGHTS_CONNECTION_STRING: ${{ secrets.APPLICATIONINSIGHTS_CONNECTION_STRING }}
with:
deployment_file_name: '${{ secrets.DEPLOYMENT_FILE_NAME }}'
architecture: '${{ secrets.ARCHITECTURE }}'
iot_edge_deployment_id: '${{ secrets.IOT_EDGE_DEPLOYMENT_ID }}'
waitForLnsDeployment: false
load_test_job:
timeout-minutes: 150
name: Run Load Tests
environment:
name: CI_AZURE_ENVIRONMENT
url: ${{ needs.env_var.outputs.CheckSuiteUrl }}
if: always() && (github.event_name == 'schedule' || github.event.inputs.RunLoadTests == 'true') && needs.deploy_arm_gw_iot_edge.result == 'success' && needs.deploy_eflow_gw_iot_edge.result == 'success' && needs.deploy_facade_function.result == 'success' && needs.env_var.outputs.StopFullCi != 'true'
needs:
- deploy_arm_gw_iot_edge
- deploy_eflow_gw_iot_edge
- deploy_facade_function
- deploy_eflow_concentrator_iot_edge
- env_var
- certificates_job
runs-on: [ self-hosted, x64 ]
env:
INTEGRATIONTEST_IoTHubEventHubConnectionString: ${{ secrets.IOTHUB_EVENT_HUB_CONNECTION_STRING }}
INTEGRATIONTEST_IoTHubEventHubConsumerGroup: ${{ secrets.IOTHUB_CI_CONSUMER_GROUP }}
INTEGRATIONTEST_IoTHubConnectionString: ${{ secrets.IOTHUB_OWNER_CONNECTION_STRING }}
INTEGRATIONTEST_LeafDeviceGatewayID: itestarm1
INTEGRATIONTEST_DevicePrefix: '03'
INTEGRATIONTEST_RunningInCI: true
INTEGRATIONTEST_LoadTestLnsEndpoints: ${{ secrets.LOAD_TEST_LNS_ENDPOINTS }}
INTEGRATIONTEST_NumberOfLoadTestDevices: 10
INTEGRATIONTEST_NumberOfLoadTestConcentrators: 4
INTEGRATIONTEST_FunctionAppCode: ${{ secrets.FUNCTION_FACADE_AUTH_CODE }}
INTEGRATIONTEST_FunctionAppBaseUrl: ${{ secrets.FUNCTION_FACADE_SERVER_URL }}
INTEGRATIONTEST_TcpLogPort: 6000
steps:
- uses: actions/checkout@v3
name: Checkout current branch
- name: Setup .NET
uses: actions/setup-dotnet@v3.0.1
with:
dotnet-version: '6.0.x' # SDK Version to use.
- name: .NET SDK Information
run:
dotnet --info
- name: Configuration for load tests
uses: cschleiden/replace-tokens@v1
with:
files: '${{ env.TESTS_FOLDER }}/Simulation/appsettings.json'
- name: Build load tests
run: |
dotnet build --configuration ${{ env.BUILD_CONFIGURATION }} ${{ env.TESTS_FOLDER }}/Simulation/LoRaWan.Tests.Simulation.csproj
- name: Runs load tests
shell: bash
run: |
dotnet test --logger trx --no-build --configuration ${{ env.BUILD_CONFIGURATION }} \
-r ${{ env.TESTS_RESULTS_FOLDER }}/LoadTest/ --filter "SimulatedLoadTests" \
${{ env.TESTS_FOLDER }}/Simulation/LoRaWan.Tests.Simulation.csproj
# Upload test results as artifact
- uses: actions/upload-artifact@v3
if: always()
with:
name: load-test-results
path: ${{ env.TESTS_RESULTS_FOLDER }}/LoadTest/
cloud_test_job:
timeout-minutes: 150
name: Run cloud only deployment Tests
environment:
name: CI_AZURE_ENVIRONMENT
url: ${{ needs.env_var.outputs.CheckSuiteUrl }}
if: always() && needs.deploy_cloud_lns.result == 'success' && needs.deploy_facade_function.result == 'success' && needs.env_var.outputs.StopFullCi != 'true' && contains(needs.env_var.outputs.E2ETestsToRun, 'CloudDeploymentTest') && !(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'CloudDeploymentTest'))
needs:
- deploy_facade_function
- deploy_cloud_lns
- env_var
- certificates_job
runs-on: [ self-hosted, x64 ]
env:
INTEGRATIONTEST_IoTHubEventHubConnectionString: ${{ secrets.IOTHUB_EVENT_HUB_CONNECTION_STRING }}
INTEGRATIONTEST_IoTHubEventHubConsumerGroup: ${{ secrets.IOTHUB_CI_CONSUMER_GROUP }}
INTEGRATIONTEST_IoTHubConnectionString: ${{ secrets.IOTHUB_OWNER_CONNECTION_STRING }}
INTEGRATIONTEST_LeafDeviceGatewayID: itestarm1
INTEGRATIONTEST_DevicePrefix: '12'
INTEGRATIONTEST_RunningInCI: true
INTEGRATIONTEST_LoadTestLnsEndpoints: "{ \\\"1\\\": \\\"ws://${{ needs.deploy_cloud_lns.outputs.cloudlnsprivateip }}:5000\\\" }"
INTEGRATIONTEST_NumberOfLoadTestDevices: 1
INTEGRATIONTEST_NumberOfLoadTestConcentrators: 2
INTEGRATIONTEST_FunctionAppCode: ${{ secrets.FUNCTION_FACADE_AUTH_CODE }}
INTEGRATIONTEST_FunctionAppBaseUrl: ${{ secrets.FUNCTION_FACADE_SERVER_URL }}
INTEGRATIONTEST_TcpLogPort: 6100
steps:
- uses: actions/checkout@v2
name: Checkout current branch
- name: Setup .NET
uses: actions/setup-dotnet@v3.0.1
with:
dotnet-version: '6.0.x' # SDK Version to use.
- name: .NET SDK Information
run:
dotnet --info
- name: Configuration for simulated cloud tests
uses: cschleiden/replace-tokens@v1
with:
files: '${{ env.TESTS_FOLDER }}/Simulation/appsettings.json'
- name: Build simulated cloud tests
run: |
dotnet build --configuration ${{ env.BUILD_CONFIGURATION }} ${{ env.TESTS_FOLDER }}/Simulation/LoRaWan.Tests.Simulation.csproj
- name: Runs simulated cloud tests
shell: bash
run: |
dotnet test --logger trx --no-build --configuration ${{ env.BUILD_CONFIGURATION }} \
-r ${{ env.TESTS_RESULTS_FOLDER }}/LoadTest/ --filter "SimulatedCloudTests" \
${{ env.TESTS_FOLDER }}/Simulation/LoRaWan.Tests.Simulation.csproj
- name: Add CloudDeploymentTest Test Label
uses: buildsville/add-remove-label@v1
if: github.event_name == 'pull_request' && success()
with:
token: ${{ github.token }}
label: 'CloudDeploymentTest'
type: add
# Upload simulated cloud results as artifact
- uses: actions/upload-artifact@v1
if: always()
with:
name: simulated-cloud-test-results
path: ${{ env.TESTS_RESULTS_FOLDER }}/LoadTest/
# Runs E2E tests in dedicated agent, while having modules deployed into PI (arm32v7)
e2e_tests_job:
timeout-minutes: 150
name: Run E2E Tests
environment:
name: CI_AZURE_ENVIRONMENT
url: ${{ needs.env_var.outputs.CheckSuiteUrl }}
if: always() && (needs.env_var.outputs.RunE2ETestsOnly == 'true' || (needs.deploy_arm_gw_iot_edge.result == 'success' && needs.deploy_eflow_gw_iot_edge.result == 'success' && needs.deploy_facade_function.result == 'success')) && needs.env_var.outputs.StopFullCi != 'true'
needs:
- deploy_arm_gw_iot_edge
- deploy_eflow_gw_iot_edge
- deploy_facade_function
- deploy_eflow_concentrator_iot_edge
- env_var
- certificates_job
- load_test_job
runs-on: [ self-hosted, x64 ]
env:
E2ETESTS_LeafDeviceSerialPort: '/dev/ttyACM0'
E2ETESTS_IoTHubEventHubConsumerGroup: ${{ secrets.IOTHUB_CI_CONSUMER_GROUP }}
E2ETESTS_LeafDeviceGatewayID: itestarm1
E2ETESTS_DevicePrefix: '01'
E2ETESTS_EnsureHasEventDelayBetweenReadsInSeconds: 15
E2ETESTS_EnsureHasEventMaximumTries: 5
E2ETESTS_IoTHubConnectionString: ${{ secrets.IOTHUB_OWNER_CONNECTION_STRING }}
E2ETESTS_IoTHubEventHubConnectionString: ${{ secrets.IOTHUB_EVENT_HUB_CONNECTION_STRING }}
E2ETESTS_FunctionAppCode: ${{ secrets.FUNCTION_FACADE_AUTH_CODE }}
E2ETESTS_FunctionAppBaseUrl: ${{ secrets.FUNCTION_FACADE_SERVER_URL }}
E2ETESTS_RunningInCI: true
E2ETESTS_RemoteConcentratorConnection: ${{ secrets.REMOTECONCENTRATORCONNECTION }}
E2ETESTS_BasicStationExecutablePath: ${{ secrets.BASICSTATIONEXECUTABLEPATH }}
E2ETESTS_SshPrivateKeyPath: ${{ secrets.SSHPRIVATEKEYPATH }}
E2ETESTS_SharedLnsEndpoint: ${{ secrets.SHAREDLNSENDPOINT }}
E2ETESTS_SharedCupsEndpoint: ${{ secrets.SHAREDCUPSENDPOINT }}
E2ETESTS_DefaultBasicStationEui: ${{ secrets.DEFAULTCISTATIONEUI }}
E2ETESTS_RadioDev: ${{ secrets.CIBASICSTATIONRADIODEV }}
E2ETESTS_CupsBasicStationEui: ${{ secrets.DEFAULTCUPSSTATIONEUI }}
E2ETESTS_IsCorecellBasicStation: false
E2ETESTS_ClientThumbprint: ${{ needs.certificates_job.outputs.clientthumbprint }}
E2ETESTS_ClientBundleCrc: ${{ needs.certificates_job.outputs.clientbundlecrc }}
E2ETESTS_CupsSigKeyChecksum: ${{ needs.certificates_job.outputs.clientsigkeycrc }}
E2ETESTS_CupsFwDigest: ${{ needs.certificates_job.outputs.clientfwdigest }}
E2ETESTS_CupsBasicStationVersion: "2.0.6(rak833x64/std)"
E2ETESTS_CupsBasicStationPackage: ${{ needs.certificates_job.outputs.clientfwversion }}
E2ETESTS_CupsFwUrl: ${{ secrets.CUPSFIRMWAREBLOBURL }}
TestsToRun: ${{ needs.env_var.outputs.E2ETestsToRun }}
E2ETESTS_TxPower: ${{ needs.env_var.outputs.TxPower }}
steps:
- uses: actions/checkout@v3
name: Checkout current branch
- name: Setup .NET
uses: actions/setup-dotnet@v3.0.1
with:
dotnet-version: '6.0.x' # SDK Version to use.
- name: .NET SDK Information
run:
dotnet --info
- name: Configuration for E2E tests
uses: cschleiden/replace-tokens@v1
with:
files: '${{ env.TESTS_FOLDER }}/E2E/appsettings.json'
# Builds and runs E2E tests
- name: Build E2E tests
run: |
echo "killing process listening on TCP 6000"
sudo lsof -i:6000 -t | xargs -r sudo kill
dotnet build --configuration ${{ env.BUILD_CONFIGURATION }} ${{ env.TESTS_FOLDER }}/E2E/LoRaWan.Tests.E2E.csproj
# The tests need to run if:
# - In PRs, when DON'T have the matchin test label
# - In other runs, all the tests present in env.TestsToRun
- name: Runs SensorDecoding E2E tests
if: always() && contains(env.TestsToRun, 'SensorDecodingTest') && !(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'SensorDecodingTest'))
uses: ./.github/actions/rune2etest
id: e2e_tests_sensordecoding
with:
test_name: 'SensorDecodingTest'
- name: Runs OTAAJoin E2E tests
if: always() && contains(env.TestsToRun, 'OTAAJoinTest') && !(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'OTAAJoinTest'))
uses: ./.github/actions/rune2etest
id: e2e_tests_otaajointest
with:
test_name: 'OTAAJoinTest'
- name: Runs ABP E2E tests
if: always() && contains(env.TestsToRun, 'ABPTest') && !(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'ABPTest'))
uses: ./.github/actions/rune2etest
id: e2e_tests_abptest
with:
test_name: 'ABPTest'
- name: Runs OTAA E2E tests
if: always() && contains(env.TestsToRun, 'OTAATest') && !(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'OTAATest'))
uses: ./.github/actions/rune2etest
id: e2e_tests_otaatest
with:
test_name: 'OTAATest'
- name: Runs MacTest E2E tests
if: always() && contains(env.TestsToRun, 'MacTest') && !(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'MacTest'))
uses: ./.github/actions/rune2etest
id: e2e_tests_mactest
with:
test_name: 'MacTest'
- name: Runs ClassC E2E tests
if: always() && contains(env.TestsToRun, 'ClassCTest') && !(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'ClassCTest'))
uses: ./.github/actions/rune2etest
id: e2e_tests_classctest
with:
test_name: 'ClassCTest'
- name: Runs C2D E2E tests
if: always() && contains(env.TestsToRun, 'C2DMessageTest') && !(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'C2DMessageTest'))
uses: ./.github/actions/rune2etest
id: e2e_tests_c2dctest
with:
test_name: 'C2DMessageTest'
- name: Runs MultiGatewayTest E2E tests
if: always() && contains(env.TestsToRun, 'MultiGatewayTest') && !(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'MultiGatewayTest'))
uses: ./.github/actions/rune2etest
id: e2e_tests_multigwtest
with:
test_name: 'MultiGatewayTest'
- name: Runs MultiConcentrator E2E tests
if: always() && contains(env.TestsToRun, 'MultiConcentratorTest') && !(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'MultiConcentratorTest'))
uses: ./.github/actions/rune2etest
id: e2e_tests_multiconctest
with:
test_name: 'MultiConcentratorTest'
- name: Runs CUPS E2E tests
if: always() && contains(env.TestsToRun, 'CupsTest') && !(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'CupsTest'))
uses: ./.github/actions/rune2etest
id: e2e_tests_cupstest
with:
test_name: 'CupsTest'
- name: Runs LNS discovery E2E tests
if: always() && contains(env.TestsToRun, 'LnsDiscoveryTest') && !(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'LnsDiscoveryTest'))
uses: ./.github/actions/rune2etest
id: e2e_tests_lnsdiscoverytest
with:
test_name: 'LnsDiscoveryTest'
# Upload test results as artifact
- uses: actions/upload-artifact@v3
if: always()
with:
name: e2e-test-results
path: ${{ env.TESTS_RESULTS_FOLDER }}/E2E/
power_off_azure_vm:
name: Power OFF EFLOW
if: always()
runs-on: ubuntu-latest
needs:
- e2e_tests_job
steps:
- uses: actions/checkout@v3
- name: Power OFF Azure VM
uses: ./.github/actions/power-azure-vm
with:
AZURE_VM_NAME: eflow
AZURE_RG_NAME: lorae2etests
POWER_SWITCH: false
AZURE_SP_CLIENTID: ${{ secrets.AZURE_SP_CLIENTID }}
AZURE_SP_SECRET: ${{ secrets.AZURE_SP_SECRET }}
AZURE_TENANTID: ${{ secrets.AZURE_TENANTID }}
delete_cloud_lns:
name: Delete cloud LNS
if: always()
runs-on: ubuntu-latest
needs:
- e2e_tests_job
steps:
- uses: actions/checkout@v2
- name: "Delete azure container instance for cloudlns"
shell: bash
run: |
az login --service-principal -u ${{ secrets.AZURE_SP_CLIENTID }} -p ${{ secrets.AZURE_SP_SECRET }} --tenant ${{ secrets.AZURE_TENANTID }}
az container logs -g ${{ secrets.AZURE_RG }} --name cloudlns
az container delete --yes --resource-group ${{ secrets.AZURE_RG }} --name cloudlns --output none