From 288b6b9205eb0839c1d946c00539ce9c06886bf1 Mon Sep 17 00:00:00 2001 From: Umberto Baldi Date: Tue, 25 Jan 2022 14:48:32 +0100 Subject: [PATCH 1/3] Add `release-go-crosscompile-task` workflow that use golang crosscompile Previously there was only a workflow in the assets repo handling the release of a go project. That workflow was based on the build process we have in the Arduino CLI, but that's not the only way of compiling. We use that one in the Arduino CLI because we need CGO enabled and is not possible with golang crosscompile. The easiest (and fastest) way of cross-compiling is by using environment variables to set the OS and ARCH we want to build for. See https://go.dev/doc/install/source#introduction --- .../DistTasks.yml | 166 +++++++++++++++++ .../release-go-crosscompile-task.yml | 173 ++++++++++++++++++ workflow-templates/publish-go-tester-task.md | 2 +- .../release-go-crosscompile-task.md | 110 +++++++++++ .../release-go-crosscompile-task.yml | 173 ++++++++++++++++++ workflow-templates/release-go-task.md | 4 +- 6 files changed, 625 insertions(+), 3 deletions(-) create mode 100644 workflow-templates/assets/release-go-crosscompile-task/DistTasks.yml create mode 100644 workflow-templates/dependabot/workflow-template-copies/.github/workflows/release-go-crosscompile-task.yml create mode 100644 workflow-templates/release-go-crosscompile-task.md create mode 100644 workflow-templates/release-go-crosscompile-task.yml diff --git a/workflow-templates/assets/release-go-crosscompile-task/DistTasks.yml b/workflow-templates/assets/release-go-crosscompile-task/DistTasks.yml new file mode 100644 index 00000000..65377c0f --- /dev/null +++ b/workflow-templates/assets/release-go-crosscompile-task/DistTasks.yml @@ -0,0 +1,166 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/release-go-task/go-crosscompile/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 +# +# The project MUST contain a LICENSE.txt file in the root folder or packaging will fail. + +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 ../LICENSE.txt -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 ../LICENSE.txt -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}} -C ../.. LICENSE.txt -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}} -C ../.. LICENSE.txt -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}} -C ../.. LICENSE.txt -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}} -C ../.. LICENSE.txt -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}} -C ../.. LICENSE.txt -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}} -C ../.. LICENSE.txt -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" diff --git a/workflow-templates/dependabot/workflow-template-copies/.github/workflows/release-go-crosscompile-task.yml b/workflow-templates/dependabot/workflow-template-copies/.github/workflows/release-go-crosscompile-task.yml new file mode 100644 index 00000000..0f7b7ee9 --- /dev/null +++ b/workflow-templates/dependabot/workflow-template-copies/.github/workflows/release-go-crosscompile-task.yml @@ -0,0 +1,173 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/release-go-task.md +name: Release + +env: + # As defined by the Taskfile's PROJECT_NAME variable + PROJECT_NAME: TODO + # 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.16 + +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 }} \ + -C ../../ LICENSE.txt + 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/workflow-templates/publish-go-tester-task.md b/workflow-templates/publish-go-tester-task.md index 554fadb3..2d16c34c 100644 --- a/workflow-templates/publish-go-tester-task.md +++ b/workflow-templates/publish-go-tester-task.md @@ -16,7 +16,7 @@ Install the [`publish-go-tester-task.yml`](publish-go-tester-task.yml) GitHub Ac - [`Taskfile.yml`](assets/release-go-task/Taskfile.yml) - [variables](https://taskfile.dev/#/usage?id=variables) providing project-specific data to the build system. - Install to: repository root (or merge into the existing `Taskfile.yml`). -- [`DistTasks.yml`](assets/release-go-task/DistTasks.yml) - general purpose tasks for making production builds of Go projects. +- [`DistTasks.yml`](assets/release-go-task/DistTasks.yml) - general purpose tasks for making production builds of Go projects using cgo and [elastic docker containers](https://github.com/elastic/golang-crossbuild). - Install to: repository root ### Readme badge diff --git a/workflow-templates/release-go-crosscompile-task.md b/workflow-templates/release-go-crosscompile-task.md new file mode 100644 index 00000000..0aac59d7 --- /dev/null +++ b/workflow-templates/release-go-crosscompile-task.md @@ -0,0 +1,110 @@ +# "Release" workflow (Go, Task) + +Make a production release of the [Go](https://golang.org/) project using [Golang crosscompile feature](https://go.dev/doc/install/source#introduction). + +This is the version of the workflow for projects using the [Task](https://taskfile.dev/#/) task runner tool. + +## Installation + +### Workflow + +Install the [`release-go-crosscompile-task.yml`](release-go-crosscompile-task.yml) GitHub Actions workflow to `.github/workflows/` + +### Assets + +- [`Taskfile.yml`](assets/release-go-task/Taskfile.yml) - [variables](https://taskfile.dev/#/usage?id=variables) providing project-specific data to the build system. + - Install to: repository root (or merge into the existing `Taskfile.yml`). +- [`DistTasks.yml`](assets/release-go-crosscompile-task/DistTasks.yml) - general purpose tasks for making production builds of Go projects using golang cross-compile. + - Install to: repository root +- [`gon.config.hcl`](assets/general/gon.config.hcl) - [gon](https://github.com/mitchellh/gon) configuration file for macOS signing and notarization. + - Install to: repository root +- [Installation script and documentation](../other/installation-script/README.md) + +### Configuration + +#### Taskfile + +The following project-specific variables must be set in `Taskfile.yml`: + +- `PROJECT_NAME` +- `CONFIGURATION_PACKAGE` + +`CONFIGURATION_PACKAGE` must be set to the golang package containing the version metadata for the project. For example for the following file: https://github.com/arduino/mdns-discovery/blob/master/version/version.go the `CONFIGURATION_PACKAGE` field must be set to the value: `github.com/arduino/mdns-discovery/version`. + +#### Workflow + +The following project-specific variables must be set/configured in `release-go-crosscompile-task.yml`: + +- `PROJECT_NAME` +- `AWS_PLUGIN_TARGET` +- `GO_VERSION`: version of Go used for development of the project + +#### gon + +The following project-specific variables must be set in `gon.config.hcl`: + +- `source` +- `bundle_id` + +#### Repository secrets + +The following [repository secrets](https://docs.github.com/en/actions/reference/encrypted-secrets#creating-encrypted-secrets-for-a-repository) must be defined: + +- `INSTALLER_CERT_MAC_P12` - the [Apple Developer ID](https://developer.apple.com/support/developer-id/) signing certificate, exported in [PKCS #12 format](https://en.wikipedia.org/wiki/PKCS_12) and then encoded into base64 as described [here](https://www.kencochrane.com/2020/08/01/build-and-sign-golang-binaries-for-macos-with-github-actions/#exporting-the-developer-certificate). +- `INSTALLER_CERT_MAC_PASSWORD` - the password used to encrypt the Apple Developer ID signing certificate during the export process. +- `AC_USERNAME` - the Apple ID username associated with the certificate. + - **Note**: not likely to be a problem when using Arduino's standard credentials, but in the event the username is a member of multiple Apple Developer Program teams, you will also need to define the App Store Connect provider via [the `AC_PROVIDER` environment variable](https://github.com/mitchellh/gon#configuration-file). You can use the ID of the certificate identity (e.g., `7KT7ZWMCJT`) for this. +- `AC_PASSWORD` - [App-specific password](https://support.apple.com/en-us/HT204397) created for the Apple ID. +- `DOWNLOADS_BUCKET` - [AWS bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingBucket.html) on the downloads server. +- `AWS_ACCESS_KEY_ID` - [AWS access key ID](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) for the downloads server. +- `AWS_SECRET_ACCESS_KEY` - [AWS secret access key](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) for the downloads server. + +### Readme badge + +Markdown badge: + +```markdown +[![Release status](https://github.com/REPO_OWNER/REPO_NAME/actions/workflows/release-go-crosscompile-task.yml/badge.svg)](https://github.com/REPO_OWNER/REPO_NAME/actions/workflows/release-go-crosscompile-task.yml) +``` + +Replace the `REPO_OWNER` and `REPO_NAME` placeholders in the URLs with the final repository owner and name ([example](https://raw.githubusercontent.com/arduino-libraries/ArduinoIoTCloud/master/README.md)). + +--- + +Asciidoc badge: + +```adoc +image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/release-go-crosscompile-task.yml/badge.svg["Release status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/release-go-crosscompile-task.yml"] +``` + +Define the `{repository-owner}` and `{repository-name}` attributes and use them throughout the readme ([example](https://raw.githubusercontent.com/arduino-libraries/WiFiNINA/master/README.adoc)). + +## Commit message + +``` +Add CI workflow to publish releases + +On every push of a tag named with a version format: + +- Build the project for all supported platforms. +- Sign and notarize the macOS build. +- Create a GitHub release. + - Builds and checksums are attached as release assets + - A changelog generated from the commit history is added to the release description + - If the tag has a pre-release version suffix, the GitHub release will be marked as a pre-release. +- Upload the builds to Arduino's downloads server. +``` + +## PR message + +```markdown +On every push of a tag named with a version format: + +- Build the project for all supported platforms. +- Use [gon](https://github.com/mitchellh/gon) to sign and notarize the macOS build. +- Create a [GitHub release](https://docs.github.com/en/github/administering-a-repository/releasing-projects-on-github/about-releases). + - Builds and checksums are attached as release assets + - A changelog generated by [`arduino/create-changelog`](https://github.com/arduino/create-changelog) from the commit history is added to the release description + - If the tag has [a pre-release version suffix](https://semver.org/), the GitHub release will be marked as a pre-release. +- Upload the builds to Arduino's downloads server. +``` diff --git a/workflow-templates/release-go-crosscompile-task.yml b/workflow-templates/release-go-crosscompile-task.yml new file mode 100644 index 00000000..0f7b7ee9 --- /dev/null +++ b/workflow-templates/release-go-crosscompile-task.yml @@ -0,0 +1,173 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/release-go-task.md +name: Release + +env: + # As defined by the Taskfile's PROJECT_NAME variable + PROJECT_NAME: TODO + # 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.16 + +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 }} \ + -C ../../ LICENSE.txt + 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/workflow-templates/release-go-task.md b/workflow-templates/release-go-task.md index 21f4badd..89192901 100644 --- a/workflow-templates/release-go-task.md +++ b/workflow-templates/release-go-task.md @@ -1,6 +1,6 @@ # "Release" workflow (Go, Task) -Make a production release of the [Go](https://golang.org/) project. +Make a production release of the [Go](https://golang.org/) with [CGO](https://go.dev/blog/cgo) enabled, using [elastic docker containers](https://github.com/elastic/golang-crossbuild). This is the version of the workflow for projects using the [Task](https://taskfile.dev/#/) task runner tool. @@ -14,7 +14,7 @@ Install the [`release-go-task.yml`](release-go-task.yml) GitHub Actions workflow - [`Taskfile.yml`](assets/release-go-task/Taskfile.yml) - [variables](https://taskfile.dev/#/usage?id=variables) providing project-specific data to the build system. - Install to: repository root (or merge into the existing `Taskfile.yml`). -- [`DistTasks.yml`](assets/release-go-task/DistTasks.yml) - general purpose tasks for making production builds of Go projects. +- [`DistTasks.yml`](assets/release-go-task/DistTasks.yml) - general purpose tasks for making production builds of Go projects using cgo and [elastic docker containers](https://github.com/elastic/golang-crossbuild). - Install to: repository root - [`gon.config.hcl`](assets/general/gon.config.hcl) - [gon](https://github.com/mitchellh/gon) configuration file for macOS signing and notarization. - Install to: repository root From 0a223193f2757e03f2df64c51ffb5e07a18e8a9c Mon Sep 17 00:00:00 2001 From: umbynos Date: Mon, 24 Jan 2022 18:41:13 +0100 Subject: [PATCH 2/3] fix typo --- workflow-templates/release-go-task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflow-templates/release-go-task.md b/workflow-templates/release-go-task.md index 89192901..65e4705d 100644 --- a/workflow-templates/release-go-task.md +++ b/workflow-templates/release-go-task.md @@ -103,7 +103,7 @@ On every push of a tag named with a version format: - Use [gon](https://github.com/mitchellh/gon) to sign and notarize the macOS build. - Create a [GitHub release](https://docs.github.com/en/github/administering-a-repository/releasing-projects-on-github/about-releases). - Builds and checksums are attached as release assets - - A changelog generated by [`arduino/create-changelog](https://github.com/arduino/create-changelog) from the commit history is added to the release description + - A changelog generated by [`arduino/create-changelog`](https://github.com/arduino/create-changelog) from the commit history is added to the release description - If the tag has [a pre-release version suffix](https://semver.org/), the GitHub release will be marked as a pre-release. - Upload the builds to Arduino's downloads server. ``` From e58a51a04d9d8f2598490f0d5be567a85075017d Mon Sep 17 00:00:00 2001 From: Umberto Baldi Date: Wed, 26 Jan 2022 11:11:50 +0100 Subject: [PATCH 3/3] apply suggestions from code review --- .../assets/release-go-crosscompile-task/DistTasks.yml | 2 +- .../.github/workflows/release-go-crosscompile-task.yml | 2 +- workflow-templates/release-go-crosscompile-task.md | 2 +- workflow-templates/release-go-crosscompile-task.yml | 2 +- workflow-templates/release-go-task.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/workflow-templates/assets/release-go-crosscompile-task/DistTasks.yml b/workflow-templates/assets/release-go-crosscompile-task/DistTasks.yml index 65377c0f..c5961148 100644 --- a/workflow-templates/assets/release-go-crosscompile-task/DistTasks.yml +++ b/workflow-templates/assets/release-go-crosscompile-task/DistTasks.yml @@ -1,4 +1,4 @@ -# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/release-go-task/go-crosscompile/DistTasks.yml +# 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 diff --git a/workflow-templates/dependabot/workflow-template-copies/.github/workflows/release-go-crosscompile-task.yml b/workflow-templates/dependabot/workflow-template-copies/.github/workflows/release-go-crosscompile-task.yml index 0f7b7ee9..ba03b3a2 100644 --- a/workflow-templates/dependabot/workflow-template-copies/.github/workflows/release-go-crosscompile-task.yml +++ b/workflow-templates/dependabot/workflow-template-copies/.github/workflows/release-go-crosscompile-task.yml @@ -1,4 +1,4 @@ -# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/release-go-task.md +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/release-go-crosscompile-task.md name: Release env: diff --git a/workflow-templates/release-go-crosscompile-task.md b/workflow-templates/release-go-crosscompile-task.md index 0aac59d7..94f03c2b 100644 --- a/workflow-templates/release-go-crosscompile-task.md +++ b/workflow-templates/release-go-crosscompile-task.md @@ -1,4 +1,4 @@ -# "Release" workflow (Go, Task) +# "Release" workflow (Go, Task, Crosscompile) Make a production release of the [Go](https://golang.org/) project using [Golang crosscompile feature](https://go.dev/doc/install/source#introduction). diff --git a/workflow-templates/release-go-crosscompile-task.yml b/workflow-templates/release-go-crosscompile-task.yml index 0f7b7ee9..ba03b3a2 100644 --- a/workflow-templates/release-go-crosscompile-task.yml +++ b/workflow-templates/release-go-crosscompile-task.yml @@ -1,4 +1,4 @@ -# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/release-go-task.md +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/release-go-crosscompile-task.md name: Release env: diff --git a/workflow-templates/release-go-task.md b/workflow-templates/release-go-task.md index 65e4705d..28f36287 100644 --- a/workflow-templates/release-go-task.md +++ b/workflow-templates/release-go-task.md @@ -1,4 +1,4 @@ -# "Release" workflow (Go, Task) +# "Release" workflow (Go, Task, CGO) Make a production release of the [Go](https://golang.org/) with [CGO](https://go.dev/blog/cgo) enabled, using [elastic docker containers](https://github.com/elastic/golang-crossbuild).