diff --git a/.github/workflows/release-go-crosscompile-task.yml b/.github/workflows/release-go-crosscompile-task.yml new file mode 100644 index 0000000..4c1d7a5 --- /dev/null +++ b/.github/workflows/release-go-crosscompile-task.yml @@ -0,0 +1,172 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/release-go-crosscompile-task.md +name: Release + +env: + # As defined by the Taskfile's PROJECT_NAME variable + PROJECT_NAME: arduino-cslt + # As defined by the Taskfile's DIST_DIR variable + DIST_DIR: dist + # The project's folder on Arduino's download server for uploading builds + # AWS_PLUGIN_TARGET: TODO + ARTIFACT_NAME: dist + # See: https://github.com/actions/setup-go/tree/v2#readme + GO_VERSION: 1.17 + +on: + push: + tags: + - "[0-9]+.[0-9]+.[0-9]+*" + +jobs: + create-release-artifacts: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Create changelog + uses: arduino/create-changelog@v1 + with: + tag-regex: '^[0-9]+\.[0-9]+\.[0-9]+.*$' + filter-regex: '^\[(skip|changelog)[ ,-](skip|changelog)\].*' + case-insensitive-regex: true + changelog-file-path: "${{ env.DIST_DIR }}/CHANGELOG.md" + + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Install Task + uses: arduino/setup-task@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + version: 3.x + + - name: Build + run: task dist:all + + - name: Upload artifacts + uses: actions/upload-artifact@v2 + with: + if-no-files-found: error + name: ${{ env.ARTIFACT_NAME }} + path: ${{ env.DIST_DIR }} + + notarize-macos: + runs-on: macos-latest + needs: create-release-artifacts + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Download artifacts + uses: actions/download-artifact@v2 + with: + name: ${{ env.ARTIFACT_NAME }} + path: ${{ env.DIST_DIR }} + + - name: Import Code-Signing Certificates + env: + KEYCHAIN: "sign.keychain" + INSTALLER_CERT_MAC_PATH: "/tmp/ArduinoCerts2020.p12" + KEYCHAIN_PASSWORD: keychainpassword # Arbitrary password for a keychain that exists only for the duration of the job, so not secret + run: | + echo "${{ secrets.INSTALLER_CERT_MAC_P12 }}" | base64 --decode > "${{ env.INSTALLER_CERT_MAC_PATH }}" + security create-keychain -p "${{ env.KEYCHAIN_PASSWORD }}" "${{ env.KEYCHAIN }}" + security default-keychain -s "${{ env.KEYCHAIN }}" + security unlock-keychain -p "${{ env.KEYCHAIN_PASSWORD }}" "${{ env.KEYCHAIN }}" + security import \ + "${{ env.INSTALLER_CERT_MAC_PATH }}" \ + -k "${{ env.KEYCHAIN }}" \ + -f pkcs12 \ + -A \ + -T "/usr/bin/codesign" \ + -P "${{ secrets.INSTALLER_CERT_MAC_PASSWORD }}" + security set-key-partition-list \ + -S apple-tool:,apple: \ + -s \ + -k "${{ env.KEYCHAIN_PASSWORD }}" \ + "${{ env.KEYCHAIN }}" + + - name: Install gon for code signing and app notarization + run: | + wget -q https://github.com/mitchellh/gon/releases/download/v0.2.3/gon_macos.zip + unzip gon_macos.zip -d /usr/local/bin + + - name: Sign and notarize binary + env: + AC_USERNAME: ${{ secrets.AC_USERNAME }} + AC_PASSWORD: ${{ secrets.AC_PASSWORD }} + run: | + gon gon.config.hcl + + - name: Re-package binary and update checksum + # This step performs the following: + # 1. Repackage the signed binary replaced in place by Gon (ignoring the output zip file) + # 2. Recalculate package checksum and replace it in the nnnnnn-checksums.txt file + run: | + # GitHub's upload/download-artifact@v2 actions don't preserve file permissions, + # so we need to add execution permission back until the action is made to do this. + chmod +x ${{ env.DIST_DIR }}/${{ env.PROJECT_NAME }}_osx_darwin_amd64/${{ env.PROJECT_NAME }} + TAG="${GITHUB_REF/refs\/tags\//}" + tar -czvf "${{ env.DIST_DIR }}/${{ env.PROJECT_NAME }}_${TAG}_macOS_64bit.tar.gz" \ + -C ${{ env.DIST_DIR }}/${{ env.PROJECT_NAME }}_osx_darwin_amd64/ ${{ env.PROJECT_NAME }} + CHECKSUM="$(shasum -a 256 ${{ env.DIST_DIR }}/${{ env.PROJECT_NAME }}_${TAG}_macOS_64bit.tar.gz | cut -d " " -f 1)" + perl \ + -pi \ + -w \ + -e "s/.*${{ env.PROJECT_NAME }}_${TAG}_macOS_64bit.tar.gz/${CHECKSUM} ${{ env.PROJECT_NAME }}_${TAG}_macOS_64bit.tar.gz/g;" \ + ${{ env.DIST_DIR }}/*-checksums.txt + + - name: Upload artifacts + uses: actions/upload-artifact@v2 + with: + if-no-files-found: error + name: ${{ env.ARTIFACT_NAME }} + path: ${{ env.DIST_DIR }} + + create-release: + runs-on: ubuntu-latest + needs: notarize-macos + + steps: + - name: Download artifact + uses: actions/download-artifact@v2 + with: + name: ${{ env.ARTIFACT_NAME }} + path: ${{ env.DIST_DIR }} + + - name: Identify Prerelease + # This is a workaround while waiting for create-release action + # to implement auto pre-release based on tag + id: prerelease + run: | + wget -q -P /tmp https://github.com/fsaintjacques/semver-tool/archive/3.0.0.zip + unzip -p /tmp/3.0.0.zip semver-tool-3.0.0/src/semver >/tmp/semver && chmod +x /tmp/semver + if [[ "$(/tmp/semver get prerel "${GITHUB_REF/refs\/tags\//}")" ]]; then echo "::set-output name=IS_PRE::true"; fi + + - name: Create Github Release and upload artifacts + uses: ncipollo/release-action@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + bodyFile: ${{ env.DIST_DIR }}/CHANGELOG.md + draft: false + prerelease: ${{ steps.prerelease.outputs.IS_PRE }} + # NOTE: "Artifact is a directory" warnings are expected and don't indicate a problem + # (all the files we need are in the DIST_DIR root) + artifacts: ${{ env.DIST_DIR }}/* + + # - name: Upload release files on Arduino downloads servers + # uses: docker://plugins/s3 + # env: + # PLUGIN_SOURCE: "${{ env.DIST_DIR }}/*" + # PLUGIN_TARGET: ${{ env.AWS_PLUGIN_TARGET }} + # PLUGIN_STRIP_PREFIX: "${{ env.DIST_DIR }}/" + # PLUGIN_BUCKET: ${{ secrets.DOWNLOADS_BUCKET }} + # AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + # AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} diff --git a/.gitignore b/.gitignore index 683ed08..2ee3a72 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ arduino-cslt .vscode -lib* \ No newline at end of file +lib* +dist \ No newline at end of file diff --git a/DistTasks.yml b/DistTasks.yml new file mode 100644 index 0000000..4f489b8 --- /dev/null +++ b/DistTasks.yml @@ -0,0 +1,165 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/release-go-crosscompile-task/DistTasks.yml +version: "3" + +# This taskfile is ideally meant to be project agnostic and could be dropped in +# on other Go projects with minimal or no changes. +# +# To use it simply add the following lines to your main taskfile: +# includes: +# dist: ./DistTasks.yml +# +# The following variables must be declared in the including taskfile for the +# build process to work correctly: +# * DIST_DIR: the folder that will contain the final binaries and packages +# * PROJECT_NAME: the name of the project, used in package name +# * VERSION: the version of the project, used in package name and checksum file +# * LD_FLAGS: flags used at build time +# + +vars: + CHECKSUM_FILE: "{{.VERSION}}-checksums.txt" + +tasks: + all: + desc: Build for distribution for all platforms + cmds: + - task: Windows_32bit + - task: Windows_64bit + - task: Linux_32bit + - task: Linux_64bit + - task: Linux_ARMv6 + - task: Linux_ARMv7 + - task: Linux_ARM64 + - task: macOS_64bit + + Windows_32bit: + desc: Builds Windows 32 bit binaries + env: + GOOS: "windows" + GOARCH: "386" + GO386: "softfloat" + cmds: + - | + go build -o {{.DIST_DIR}}/{{.PLATFORM_DIR}}/{{.PROJECT_NAME}}.exe {{.LDFLAGS}} + cd {{.DIST_DIR}} + zip {{.PACKAGE_NAME}} {{.PLATFORM_DIR}}/{{.PROJECT_NAME}}.exe -j + sha256sum {{.PACKAGE_NAME}} >> {{.CHECKSUM_FILE}} + vars: + PLATFORM_DIR: "{{.PROJECT_NAME}}_windows_386" + PACKAGE_PLATFORM: "Windows_32bit" + PACKAGE_NAME: "{{.PROJECT_NAME}}_{{.VERSION}}_{{.PACKAGE_PLATFORM}}.zip" + + Windows_64bit: + desc: Builds Windows 64 bit binaries + env: + GOOS: "windows" + GOARCH: "amd64" + cmds: + - | + go build -o {{.DIST_DIR}}/{{.PLATFORM_DIR}}/{{.PROJECT_NAME}}.exe {{.LDFLAGS}} + cd {{.DIST_DIR}} + zip {{.PACKAGE_NAME}} {{.PLATFORM_DIR}}/{{.PROJECT_NAME}}.exe -j + sha256sum {{.PACKAGE_NAME}} >> {{.CHECKSUM_FILE}} + vars: + PLATFORM_DIR: "{{.PROJECT_NAME}}_windows_amd64" + PACKAGE_PLATFORM: "Windows_64bit" + PACKAGE_NAME: "{{.PROJECT_NAME}}_{{.VERSION}}_{{.PACKAGE_PLATFORM}}.zip" + + Linux_32bit: + desc: Builds Linux 32 bit binaries + env: + GOOS: "linux" + GOARCH: "386" + GO386: "softfloat" + cmds: + - | + go build -o {{.DIST_DIR}}/{{.PLATFORM_DIR}}/{{.PROJECT_NAME}} {{.LDFLAGS}} + cd {{.DIST_DIR}} + tar cz -C {{.PLATFORM_DIR}} {{.PROJECT_NAME}} -f {{.PACKAGE_NAME}} + sha256sum {{.PACKAGE_NAME}} >> {{.CHECKSUM_FILE}} + vars: + PLATFORM_DIR: "{{.PROJECT_NAME}}_linux_amd32" + PACKAGE_PLATFORM: "Linux_32bit" + PACKAGE_NAME: "{{.PROJECT_NAME}}_{{.VERSION}}_{{.PACKAGE_PLATFORM}}.tar.gz" + + Linux_64bit: + desc: Builds Linux 64 bit binaries + env: + GOOS: "linux" + GOARCH: "amd64" + cmds: + - | + go build -o {{.DIST_DIR}}/{{.PLATFORM_DIR}}/{{.PROJECT_NAME}} {{.LDFLAGS}} + cd {{.DIST_DIR}} + tar cz -C {{.PLATFORM_DIR}} {{.PROJECT_NAME}} -f {{.PACKAGE_NAME}} + sha256sum {{.PACKAGE_NAME}} >> {{.CHECKSUM_FILE}} + vars: + PLATFORM_DIR: "{{.PROJECT_NAME}}_linux_amd64" + PACKAGE_PLATFORM: "Linux_64bit" + PACKAGE_NAME: "{{.PROJECT_NAME}}_{{.VERSION}}_{{.PACKAGE_PLATFORM}}.tar.gz" + + Linux_ARMv7: + desc: Builds Linux ARMv7 binaries + env: + GOOS: "linux" + GOARCH: "arm" + GOARM: 7 + cmds: + - | + go build -o {{.DIST_DIR}}/{{.PLATFORM_DIR}}/{{.PROJECT_NAME}} {{.LDFLAGS}} + cd {{.DIST_DIR}} + tar cz -C {{.PLATFORM_DIR}} {{.PROJECT_NAME}} -f {{.PACKAGE_NAME}} + sha256sum {{.PACKAGE_NAME}} >> {{.CHECKSUM_FILE}} + vars: + PLATFORM_DIR: "{{.PROJECT_NAME}}_linux_arm_7" + PACKAGE_PLATFORM: "Linux_ARMv7" + PACKAGE_NAME: "{{.PROJECT_NAME}}_{{.VERSION}}_{{.PACKAGE_PLATFORM}}.tar.gz" + + Linux_ARMv6: + desc: Builds Linux ARMv6 binaries + env: + GOOS: "linux" + GOARCH: "arm" + GOARM: 6 + cmds: + - | + go build -o {{.DIST_DIR}}/{{.PLATFORM_DIR}}/{{.PROJECT_NAME}} {{.LDFLAGS}} + cd {{.DIST_DIR}} + tar cz -C {{.PLATFORM_DIR}} {{.PROJECT_NAME}} -f {{.PACKAGE_NAME}} + sha256sum {{.PACKAGE_NAME}} >> {{.CHECKSUM_FILE}} + vars: + PLATFORM_DIR: "{{.PROJECT_NAME}}_linux_arm_6" + PACKAGE_PLATFORM: "Linux_ARMv6" + PACKAGE_NAME: "{{.PROJECT_NAME}}_{{.VERSION}}_{{.PACKAGE_PLATFORM}}.tar.gz" + + Linux_ARM64: + desc: Builds Linux ARM64 binaries + env: + GOOS: "linux" + GOARCH: "arm64" + cmds: + - | + go build -o {{.DIST_DIR}}/{{.PLATFORM_DIR}}/{{.PROJECT_NAME}} {{.LDFLAGS}} + cd {{.DIST_DIR}} + tar cz -C {{.PLATFORM_DIR}} {{.PROJECT_NAME}} -f {{.PACKAGE_NAME}} + sha256sum {{.PACKAGE_NAME}} >> {{.CHECKSUM_FILE}} + vars: + PLATFORM_DIR: "{{.PROJECT_NAME}}_linux_arm_64" + PACKAGE_PLATFORM: "Linux_ARM64" + PACKAGE_NAME: "{{.PROJECT_NAME}}_{{.VERSION}}_{{.PACKAGE_PLATFORM}}.tar.gz" + + macOS_64bit: + desc: Builds Mac OS X 64 bit binaries + env: + GOOS: "darwin" + GOARCH: "amd64" + cmds: + - | + go build -o {{.DIST_DIR}}/{{.PLATFORM_DIR}}/{{.PROJECT_NAME}} {{.LDFLAGS}} + cd {{.DIST_DIR}} + tar cz -C {{.PLATFORM_DIR}} {{.PROJECT_NAME}} -f {{.PACKAGE_NAME}} + sha256sum {{.PACKAGE_NAME}} >> {{.CHECKSUM_FILE}} + vars: + PLATFORM_DIR: "{{.PROJECT_NAME}}_osx_darwin_amd64" + PACKAGE_PLATFORM: "macOS_64bit" + PACKAGE_NAME: "{{.PROJECT_NAME}}_{{.VERSION}}_{{.PACKAGE_PLATFORM}}.tar.gz" \ No newline at end of file diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000..2e242ec --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,41 @@ +# See: https://taskfile.dev/#/usage +version: "3" + +includes: + dist: ./DistTasks.yml + +vars: + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/release-go-task/Taskfile.yml + PROJECT_NAME: arduino-cslt + DIST_DIR: "dist" + # build vars + COMMIT: + sh: echo "$(git log --no-show-signature -n 1 --format=%h)" + TIMESTAMP: + sh: echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" + TIMESTAMP_SHORT: + sh: echo "{{now | date "20060102"}}" + TAG: + sh: echo "$(git tag --points-at=HEAD 2> /dev/null | head -n1)" + VERSION: "{{if .NIGHTLY}}nightly-{{.TIMESTAMP_SHORT}}{{else if .TAG}}{{.TAG}}{{else}}{{.PACKAGE_NAME_PREFIX}}git-snapshot{{end}}" + CONFIGURATION_PACKAGE: github.com/arduino/arduino-cslt/version + # Path of the project's primary Go module: + DEFAULT_GO_MODULE_PATH: ./ + DEFAULT_GO_PACKAGES: + sh: | + echo $(cd {{default .DEFAULT_GO_MODULE_PATH .GO_MODULE_PATH}} && go list ./... | tr '\n' ' ' || echo '"ERROR: Unable to discover Go packages"') + # `-ldflags` flag to use for `go build` command + LDFLAGS: >- + -ldflags + ' + -X {{.CONFIGURATION_PACKAGE}}.Version={{.VERSION}} + -X {{.CONFIGURATION_PACKAGE}}.Commit={{.COMMIT}} + -X {{.CONFIGURATION_PACKAGE}}.Timestamp={{.TIMESTAMP}} + ' +tasks: + # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/go-task/Taskfile.yml + go:build: + desc: Build the Go code + dir: "{{.DEFAULT_GO_MODULE_PATH}}" + cmds: + - go build -v {{.LDFLAGS}} \ No newline at end of file diff --git a/gon.config.hcl b/gon.config.hcl new file mode 100644 index 0000000..1eb6b86 --- /dev/null +++ b/gon.config.hcl @@ -0,0 +1,15 @@ + +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/general/gon.config.hcl +# See: https://github.com/mitchellh/gon#configuration-file +source = ["dist/arduino-cslt_osx_darwin_amd64/arduino-cslt"] +bundle_id = "cc.arduino.arduino-cslt" + +sign { + application_identity = "Developer ID Application: ARDUINO SA (7KT7ZWMCJT)" +} + +# Ask Gon for zip output to force notarization process to take place. +# The CI will ignore the zip output, using the signed binary only. +zip { + output_path = "unused.zip" +} \ No newline at end of file diff --git a/version/version.go b/version/version.go new file mode 100644 index 0000000..ffcc028 --- /dev/null +++ b/version/version.go @@ -0,0 +1,10 @@ +package version + +// Version is the current version +var Version = "unknown" + +// Commit is the current git tag +var Commit = "unknown" + +// Timestamp is the current timestamp +var Timestamp = "unknown"