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..c5961148 --- /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-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 +# +# 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..ba03b3a2 --- /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-crosscompile-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..94f03c2b --- /dev/null +++ b/workflow-templates/release-go-crosscompile-task.md @@ -0,0 +1,110 @@ +# "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). + +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..ba03b3a2 --- /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-crosscompile-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..28f36287 100644 --- a/workflow-templates/release-go-task.md +++ b/workflow-templates/release-go-task.md @@ -1,6 +1,6 @@ -# "Release" workflow (Go, Task) +# "Release" workflow (Go, Task, CGO) -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 @@ -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. ```