Skip to content
31 changes: 31 additions & 0 deletions .github/workflows/test-update.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Build & Update with Arduino CLI

on:
push:
branches:
- main
- test_package_update
- test_package_update_rebase
workflow_dispatch:

permissions:
contents: read

jobs:
build-and-update:
runs-on: ubuntu-22.04

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod

- name: Run dep package update test
env:
GH_TOKEN: ${{ secrets.ARDUINOBOT_TOKEN }}
run: |
go test -count=1 --timeout 30m -v ./internal/e2e/updatetest -- --arch amd64
46 changes: 44 additions & 2 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ vars:
RUNNER_VERSION: "0.5.0"
VERSION: # if version is not passed we hack the semver by encoding the commit as pre-release
sh: echo "${VERSION:-0.0.0-$(git rev-parse --short HEAD)}"
NEW_PACKAGE:
sh: ls -1 ./build/arduino-app-cli_*.deb 2>/dev/null | head -n 1
GITHUB_TOKEN_FILE: ./github_token.txt

tasks:
init:
Expand Down Expand Up @@ -52,7 +55,7 @@ tasks:
cmds:
- go build ./cmd/arduino-app-cli # needed for e2e tests
- task: generate
- go test ./internal/... ./cmd/... -v -race {{ .CLI_ARGS }}
- go test $(go list ./internal/... ./cmd/... | grep -v internal/e2e/updatetest) -v -race {{ .CLI_ARGS }} # exclude deb package update tests

test:pkg:
desc: Run only tests in the pkg directory
Expand Down Expand Up @@ -102,9 +105,10 @@ tasks:
deps:
- build-deb:clone-examples
cmds:
- docker build --build-arg BINARY_NAME=arduino-app-cli --build-arg DEB_NAME=arduino-app-cli --build-arg VERSION={{ .VERSION }} --build-arg ARCH={{ .ARCH }} --build-arg RELEASE={{ .RELEASE }} --output=./build -f debian/Dockerfile .
- docker build --build-arg BINARY_NAME=arduino-app-cli --build-arg DEB_NAME=arduino-app-cli --build-arg VERSION={{ .VERSION }} --build-arg ARCH={{ .ARCH }} --build-arg RELEASE={{ .RELEASE }} --output={{ .OUTPUT }} -f debian/Dockerfile .
vars:
ARCH: '{{.ARCH | default "arm64"}}'
OUTPUT: '{{.OUTPUT | default "./build"}}'

build-deb:clone-examples:
desc: "Clones the examples repo directly into the debian structure"
Expand All @@ -123,6 +127,44 @@ tasks:
echo "Examples successfully cloned."
silent: false

build-image:
desc: "Builds the mock-repo Docker image (requires GITHUB_TOKEN_FILE)"
deps: [build-deb]
vars:
PKG_PATH: "{{.NEW_PACKAGE}}"
cmds:
# --- MODIFIED ---
# Check for both the package and the token file
- |
if [ ! -f "{{.GITHUB_TOKEN_FILE}}" ]; then
echo "Error: GitHub token file not found at {{.GITHUB_TOKEN_FILE}}"
echo "Please create this file and add your GitHub PAT to it."
exit 1
fi
- |
echo "Using package: {{.PKG_PATH}}"
echo "Using GitHub token from: {{.GITHUB_TOKEN_FILE}}"

# Enable BuildKit and pass the secret
DOCKER_BUILDKIT=1 docker build \
--secret id=github_token,src={{.GITHUB_TOKEN_FILE}} \
--build-arg NEW_PACKAGE_PATH={{.PKG_PATH}} \
-t newdeb \
-f test.Dockerfile .
status:
- '[[ -f "{{.PKG_PATH}}" ]]'
- '[[ -f "{{.DOCKERFILE_NAME}}" ]]'
# Re-build if token file changes
- '[[ -f "{{.GITHUB_TOKEN_FILE}}" ]]'

test-deb:
desc: Test the debian package locally
deps:
- build-deb
cmds:
- docker build --no-cache -t mock-apt-repo -f test.Dockerfile .
- docker run --rm -it --privileged -v /sys/fs/cgroup:/sys/fs/cgroup:ro --name apt-test-update mock-apt-repo

arduino-app-cli:build:local:
desc: "Build the arduino-app-cli locally"
cmds:
Expand Down
122 changes: 122 additions & 0 deletions internal/e2e/updatetest/deb_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package updatetest

import (
"flag"
"fmt"
"os"
"testing"
"time"

"github.com/stretchr/testify/require"
)

var arch = flag.String("arch", "amd64", "target architecture")

const dockerFile = "test.Dockerfile"
const daemonHost = "127.0.0.1:8800"

func TestUpdatePackage(t *testing.T) {
fmt.Printf("***** ARCH %s ***** \n", *arch)

t.Run("Stable To Current", func(t *testing.T) {
t.Cleanup(func() { os.RemoveAll("build") })

tagAppCli := fetchDebPackageLatest(t, "build/stable", "arduino-app-cli")
fetchDebPackageLatest(t, "build/stable", "arduino-router")
majorTag := genMajorTag(t, tagAppCli)

fmt.Printf("Updating from stable version %s to unstable version %s \n", tagAppCli, majorTag)
fmt.Printf("Building local deb version %s \n", majorTag)
buildDebVersion(t, "build", majorTag, *arch)

const dockerImageName = "apt-test-update-image"
fmt.Println("**** BUILD docker image *****")
buildDockerImage(t, dockerFile, dockerImageName, *arch)
//TODO: t cleanup remove docker image

t.Run("CLI Command", func(t *testing.T) {
const containerName = "apt-test-update"
t.Cleanup(func() { stopDockerContainer(t, containerName) })

fmt.Println("**** RUN docker image *****")
startDockerContainer(t, containerName, dockerImageName)
waitForPort(t, daemonHost, 5*time.Second)

preUpdateVersion := getAppCliVersion(t, containerName)
require.Equal(t, "v"+preUpdateVersion, tagAppCli)
runSystemUpdate(t, containerName)
postUpdateVersion := getAppCliVersion(t, containerName)
require.Equal(t, "v"+postUpdateVersion, majorTag)
})

t.Run("HTTP Request", func(t *testing.T) {
const containerName = "apt-test-update-http"
t.Cleanup(func() { stopDockerContainer(t, containerName) })

startDockerContainer(t, containerName, dockerImageName)
waitForPort(t, daemonHost, 5*time.Second)

preUpdateVersion := getAppCliVersion(t, containerName)
require.Equal(t, "v"+preUpdateVersion, tagAppCli)

putUpdateRequest(t, daemonHost)
waitForUpgrade(t, daemonHost)

postUpdateVersion := getAppCliVersion(t, containerName)
require.Equal(t, "v"+postUpdateVersion, majorTag)
})

})

t.Run("CurrentToStable", func(t *testing.T) {
t.Cleanup(func() { os.RemoveAll("build") })

tagAppCli := fetchDebPackageLatest(t, "build", "arduino-app-cli")
fetchDebPackageLatest(t, "build/stable", "arduino-router")
minorTag := genMinorTag(t, tagAppCli)

fmt.Printf("Updating from unstable version %s to stable version %s \n", minorTag, tagAppCli)
fmt.Printf("Building local deb version %s \n", minorTag)
buildDebVersion(t, "build/stable", minorTag, *arch)

fmt.Println("**** BUILD docker image *****")
const dockerImageName = "test-apt-update-unstable-image"

buildDockerImage(t, dockerFile, dockerImageName, *arch)
//TODO: t cleanup remove docker image

t.Run("CLI Command", func(t *testing.T) {
const containerName = "apt-test-update-unstable"
t.Cleanup(func() { stopDockerContainer(t, containerName) })

fmt.Println("**** RUN docker image *****")
startDockerContainer(t, containerName, dockerImageName)
waitForPort(t, daemonHost, 5*time.Second)

preUpdateVersion := getAppCliVersion(t, containerName)
require.Equal(t, "v"+preUpdateVersion, minorTag)
runSystemUpdate(t, containerName)
postUpdateVersion := getAppCliVersion(t, containerName)
require.Equal(t, "v"+postUpdateVersion, tagAppCli)
})

t.Run("HTTP Request", func(t *testing.T) {
const containerName = "apt-test-update--unstable-http"
t.Cleanup(func() { stopDockerContainer(t, containerName) })

startDockerContainer(t, containerName, dockerImageName)
waitForPort(t, daemonHost, 5*time.Second)

preUpdateVersion := getAppCliVersion(t, containerName)
require.Equal(t, "v"+preUpdateVersion, minorTag)

putUpdateRequest(t, daemonHost)
waitForUpgrade(t, daemonHost)

postUpdateVersion := getAppCliVersion(t, containerName)
require.Equal(t, "v"+postUpdateVersion, tagAppCli)
})

})

}
Loading
Loading