Multibuild #205
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Multibuild | |
on: | |
push: | |
tags: | |
- "v*.*.*" | |
workflow_dispatch: | |
inputs: | |
main_build_only: | |
description: "Run non-dockerx builds only" | |
required: true | |
default: false | |
type: boolean | |
permissions: # added using https://github.com/step-security/secure-repo | |
contents: read | |
jobs: | |
verify_tags: | |
permissions: | |
contents: write # Needed to create workflow branch | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
- name: Create action branch | |
run: | | |
git config --global user.name 'Atsign Robot' | |
git config --global user.email '41898282+github-actions[bot]@users.noreply.github.com' | |
git checkout -b multibuild-${{github.run_number}} | |
- name: | |
Ensure pubspec.yaml matches git ref (if current git ref is a version | |
tag) | |
shell: bash | |
if: startsWith(github.ref, 'refs/tags/v') | |
working-directory: ./packages/dart/sshnoports | |
run: | | |
REF=${{ github.ref }} | |
VER=${REF:11} | |
sed -i "0,/version:/{s/version: \(.*\)/version: "${VER}"/}" pubspec.yaml | |
if [ "$(git status --porcelain)" ]; then | |
git add . | |
git commit -m 'ci: Updated version to tag' | |
fi | |
- name: Push changes to branch | |
run: git push --set-upstream origin multibuild-${{github.run_number}} | |
main_build: | |
needs: verify_tags | |
runs-on: ${{ matrix.os }} | |
defaults: | |
run: | |
working-directory: ./packages/dart/sshnoports | |
strategy: | |
matrix: | |
include: | |
- os: ubuntu-latest | |
output-name: sshnp-linux-x64 | |
ext: "" | |
bundle: "shell" | |
- os: ubuntu-24.04-arm | |
output-name: sshnp-linux-arm64 | |
ext: "" | |
bundle: "shell" | |
- os: macos-13 | |
output-name: sshnp-macos-x64 | |
ext: "" | |
bundle: "shell" | |
- os: macos-14 | |
output-name: sshnp-macos-arm64 | |
ext: "" | |
bundle: "shell" | |
- os: windows-latest | |
output-name: sshnp-windows-x64 | |
ext: ".exe" | |
bundle: "windows" | |
steps: | |
- name: Checkout multibuild branch | |
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
with: | |
ref: multibuild-${{github.run_number}} | |
- name: Setup dart | |
uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 # v1.7.0 | |
- name: Create directories | |
run: | | |
mkdir sshnp | |
mkdir tarball | |
- name: Create debug directory (Windows only) | |
if: ${{ matrix.os != 'windows-latest' }} | |
run: mkdir sshnp/debug | |
- name: Compile binaries | |
run: | | |
dart pub get --enforce-lockfile | |
dart run build_runner build --delete-conflicting-outputs | |
dart compile exe bin/activate_cli.dart -v -o sshnp/at_activate${{ matrix.ext }} | |
dart compile exe bin/sshnp.dart -v -o sshnp/sshnp${{ matrix.ext }} | |
dart compile exe bin/npt.dart -v -o sshnp/npt${{ matrix.ext }} | |
dart compile exe bin/npp_file.dart -v -o sshnp/npa_file${{ matrix.ext }} | |
dart compile exe bin/npp_file.dart -v -o sshnp/npp_file${{ matrix.ext }} | |
dart compile exe bin/sshnpd.dart -v -o sshnp/sshnpd${{ matrix.ext }} | |
dart compile exe bin/srv.dart -v -o sshnp/srv${{ matrix.ext }} | |
dart compile exe bin/npp_atserver.dart -v -o sshnp/npp_atserver${{ matrix.ext }} | |
- name: Build admin API | |
working-directory: ./apps/admin/admin_api | |
run: | | |
dart pub get --enforce-lockfile | |
dart compile exe bin/np_admin.dart -v -o ../../../packages/dart/sshnoports/sshnp/np_admin${{ matrix.ext }} | |
- name: Compile debug binaries (Windows only) | |
if: ${{ matrix.os != 'windows-latest' }} | |
run: | | |
dart compile exe bin/srvd.dart -v -o sshnp/srvd${{ matrix.ext }} | |
dart compile exe bin/srvd.dart -D ENABLE_SNOOP=true -v -o sshnp/debug/srvd${{ matrix.ext }} | |
- name: Copy additional bundle items to build | |
run: | | |
cp -r bundles/core/* sshnp/ | |
cp -r bundles/${{ matrix.bundle }}/* sshnp/ | |
cp LICENSE sshnp | |
- name: Codesign (MacOS only) | |
if: ${{ matrix.os == 'macos-13' || matrix.os == 'macos-14' }} | |
env: | |
MACOS_CODESIGN_CERT: ${{ secrets.MACOS_CODESIGN_CERT }} | |
MACOS_CODESIGN_CERT_PASSWORD: | |
${{ secrets.MACOS_CODESIGN_CERT_PASSWORD }} | |
MACOS_SIGNING_IDENTITY: ${{ secrets.MACOS_SIGNING_IDENTITY }} | |
MACOS_KEYCHAIN_PASSWORD: ${{ secrets.MACOS_KEYCHAIN_PASSWORD }} | |
run: | | |
# Load certificate | |
CERT_PATH=$RUNNER_TEMP/noports-codesign.p12 | |
echo -n "$MACOS_CODESIGN_CERT" | base64 --decode -o $CERT_PATH | |
# create temp keychain | |
KEYCHAIN_PATH=$RUNNER_TEMP/build.keychain | |
security create-keychain -p "$MACOS_KEYCHAIN_PASSWORD" $KEYCHAIN_PATH | |
security default-keychain -s $KEYCHAIN_PATH | |
security unlock-keychain -p "$MACOS_KEYCHAIN_PASSWORD" $KEYCHAIN_PATH | |
security import $CERT_PATH -k $KEYCHAIN_PATH -P "$MACOS_CODESIGN_CERT_PASSWORD" -T /usr/bin/codesign | |
security set-key-partition-list -S apple-tool:apple,:,codesign: -s -k "$MACOS_KEYCHAIN_PASSWORD" $KEYCHAIN_PATH | |
# codesign | |
/usr/bin/codesign \ | |
--force \ | |
-s "$MACOS_SIGNING_IDENTITY" \ | |
--options=runtime \ | |
--entitlements ./tools/templates/entitlements.plist \ | |
--prefix "com.atsign." \ | |
--timestamp \ | |
-v \ | |
sshnp/{sshnp,sshnpd,srv,srvd,at_activate,debug/srvd,npt,npa_file,npp_file,npp_atserver,np_admin} | |
- name: Compress to zip (MacOS only) | |
if: ${{ matrix.os == 'macos-13' || matrix.os == 'macos-14' }} | |
run: | |
ditto -c -k --keepParent sshnp tarball/${{ matrix.output-name }}.zip | |
- name: Compress to tgz (Linux only) | |
if: ${{ matrix.os == 'ubuntu-latest' }} | |
run: tar -cvzf tarball/${{ matrix.output-name }}.tgz sshnp | |
- name: Compress to zip (Windows Only) | |
if: ${{ matrix.os == 'windows-latest' }} | |
run: | |
Compress-Archive -Path sshnp -Destination tarball/${{ | |
matrix.output-name }}.zip | |
- name: Notarize the build (MacOS only) | |
if: ${{ matrix.os == 'macos-13' || matrix.os == 'macos-14' }} | |
env: | |
MACOS_APPLE_ID: ${{ secrets.MACOS_APPLE_ID }} | |
MACOS_TEAM_ID: ${{ secrets.MACOS_TEAM_ID }} | |
MACOS_APPLE_ID_PASSWORD: ${{ secrets.MACOS_APPLE_ID_PASSWORD }} | |
run: | | |
xcrun notarytool submit tarball/${{ matrix.output-name }}.zip \ | |
--apple-id "$MACOS_APPLE_ID" \ | |
--team-id "$MACOS_TEAM_ID" \ | |
--password "$MACOS_APPLE_ID_PASSWORD" \ | |
--wait | |
- name: Upload the build | |
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 | |
with: | |
name: | |
${{ matrix.output-name | |
}}-${{github.ref_name}}-${{github.run_number}}-${{github.run_attempt}} | |
path: ./packages/dart/sshnoports/tarball | |
if-no-files-found: error | |
other_build: | |
needs: verify_tags | |
runs-on: ubuntu-24.04-arm | |
strategy: | |
matrix: | |
# platform: [linux/arm/v7, linux/riscv64] | |
platform: [linux/arm/v7] | |
include: | |
- platform: linux/arm/v7 | |
output-name: sshnp-linux-arm | |
# - platform: linux/riscv64 | |
# output-name: sshnp-linux-riscv64 | |
steps: | |
- name: Checkout multibuild branch | |
if: ${{ ! inputs.main_build_only }} | |
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
with: | |
ref: multibuild-${{github.run_number}} | |
- name: Setup QEMU | |
if: ${{ ! inputs.main_build_only }} | |
uses: docker/setup-qemu-action@53851d14592bedcffcf25ea515637cff71ef929a # v3.3.0 | |
- name: Setup Docker BuildX | |
if: ${{ ! inputs.main_build_only }} | |
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0 | |
- name: Run build inside of Docker | |
if: ${{ ! inputs.main_build_only }} | |
run: | | |
docker buildx build -t atsigncompany/sshnptarball -f ./tools/multibuild/Dockerfile.package \ | |
--platform ${{ matrix.platform }} -o type=tar,dest=bins.tar . | |
mkdir tarballs | |
tar -xvf bins.tar -C tarballs | |
- name: Upload the build | |
if: ${{ ! inputs.main_build_only }} | |
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 | |
with: | |
name: | |
${{ matrix.output-name | |
}}-${{github.ref_name}}-${{github.run_number}}-${{github.run_attempt}} | |
path: ./tarballs/${{ matrix.output-name }}.tgz | |
if-no-files-found: error | |
web_build: | |
needs: verify_tags | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout multibuild branch | |
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
with: | |
ref: multibuild-${{github.run_number}} | |
- name: Setup node-version | |
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 | |
with: | |
node-version: '20.17.0' | |
- name: setup required npm version | |
run: | | |
npm install -g [email protected] | |
- name: Build admin webapp | |
working-directory: ./apps/admin/webapp | |
run: | | |
mkdir -p sshnp/web/admin | |
mkdir tarball | |
npm ci | |
npm run build | |
cp -r dist/* sshnp/web/admin/ | |
tar -cvzf tarball/sshnp-web-admin-noarch.tgz sshnp | |
- name: Upload the build | |
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 | |
with: | |
name: | |
sshnp-web-admin-noarch-${{github.ref_name}}-${{github.run_number | |
}}-${{github.run_attempt}} | |
path: ./apps/admin/webapp/tarball | |
if-no-files-found: error | |
universal_sh: | |
if: startsWith(github.ref, 'refs/tags/v') | |
defaults: | |
run: | |
working-directory: ./packages/dart/sshnoports/bundles | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
- run: | | |
write_metadata() { | |
start_line="# SCRIPT METADATA" | |
end_line="# END METADATA" | |
file=$1 | |
variable=$2 | |
value=$3 | |
# since this is linux only, sed -i is safe without a file ext. | |
sed -i "/$start_line/,/$end_line/s|$variable=\".*\"|$variable=\"$value\"|g" "$file" | |
} | |
REF=${{ github.ref }} | |
TAG=${REF:11} | |
write_metadata universal.sh sshnp_version "$TAG" | |
- uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 | |
with: | |
name: universal.sh-${{github.ref_name}}-${{github.run_number}}-${{github.run_attempt}} | |
path: ./packages/dart/sshnoports/bundles/universal.sh | |
if-no-files-found: error | |
universal_ps1: | |
if: startsWith(github.ref, 'refs/tags/v') | |
defaults: | |
run: | |
working-directory: ./packages/dart/sshnoports/bundles | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
- uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 | |
with: | |
name: universal.ps1-${{github.ref_name}}-${{github.run_number}}-${{github.run_attempt}} | |
path: ./packages/dart/sshnoports/bundles/universal.ps1 | |
if-no-files-found: error | |
github-release: | |
name: >- | |
Upload artifacts and generate SBOMs and checksums for provenance | |
needs: [main_build, other_build, web_build, universal_sh, universal_ps1] | |
runs-on: ubuntu-latest | |
outputs: | |
hashes: ${{ steps.hash.outputs.hashes }} | |
permissions: | |
contents: write # Mandatory for making GitHub Releases | |
id-token: write # Mandatory for sigstore | |
attestations: write | |
steps: | |
- name: Checkout pubspec.lock | |
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
with: | |
sparse-checkout: packages/dart/sshnoports/pubspec.lock | |
sparse-checkout-cone-mode: false | |
- name: Download all the tarballs | |
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 | |
with: | |
path: tarballs/ | |
- name: Generate SBOM | |
uses: sbomify/github-action@a04e82ca42a0d9e6bdb57a2cb1a8978e96b4f45c # v0.3.0 | |
env: | |
TOKEN: ${{ secrets.SBOMIFY_TOKEN }} | |
COMPONENT_ID: '-93khk8pUi' | |
LOCK_FILE: './packages/dart/sshnoports/pubspec.lock' | |
SBOM_VERSION: ${{github.ref_name}} | |
OUTPUT_FILE: 'tarballs/noports_dart-${{github.ref_name}}-sbom.cdx.json' | |
AUGMENT: true | |
ENRICH: true | |
UPLOAD: true | |
- name: Move packages for signing | |
run: | | |
cd tarballs | |
mv */*.sh . | |
mv */*.ps1 . | |
mv */*.tgz . | |
mv */*.zip . | |
rm -Rf -- */ | |
- name: Generate SHA256 checksums | |
working-directory: tarballs | |
run: sha256sum * > checksums.txt | |
- name: Upload artifacts to GitHub Release | |
env: | |
GITHUB_TOKEN: ${{ github.token }} | |
# Upload to GitHub Release using the `gh` CLI. | |
# `tarballs/` contains the built packages, and the | |
# sbomify produced SBOMs | |
run: >- | |
gh release upload '${{ github.ref_name }}' tarballs/** --repo '${{ | |
github.repository }}' | |
- id: hash | |
name: Pass artifact hashes for SLSA provenance | |
working-directory: tarballs | |
run: | | |
echo "hashes=$(cat checksums.txt | base64 -w0)" >> "$GITHUB_OUTPUT" | |
- uses: actions/attest-build-provenance@520d128f165991a6c774bcb264f323e3d70747f4 # v2.2.0 | |
with: | |
subject-path: "tarballs/**" | |
provenance: | |
needs: [github-release] | |
permissions: | |
actions: read # Needed for detection of GitHub Actions environment. | |
id-token: write # Needed for provenance signing and ID | |
contents: write # Needed for release uploads | |
uses: slsa-framework/slsa-github-generator/.github/workflows/[email protected] # 5a775b367a56d5bd118a224a811bba288150a563 | |
with: | |
base64-subjects: "${{ needs.github-release.outputs.hashes }}" | |
upload-assets: true | |
cleanup: | |
name: Clean up temporary branch | |
needs: [main_build, other_build] | |
runs-on: ubuntu-latest | |
permissions: | |
contents: write # Needed to delete workflow branch | |
steps: | |
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
with: | |
ref: multibuild-${{github.run_number}} | |
- name: Delete workflow branch | |
run: git push origin --delete multibuild-${{github.run_number}} | |
notify_on_completion: | |
needs: [github-release, cleanup] | |
runs-on: ubuntu-latest | |
steps: | |
- name: Google Chat Notification | |
uses: Co-qn/google-chat-notification@3691ccf4763537d6e544bc6cdcccc1965799d056 # v1 | |
with: | |
name: | |
SSH no ports binaries were built by GitHub Action ${{ | |
github.run_number }} | |
url: ${{ secrets.GOOGLE_CHAT_WEBHOOK }} | |
status: ${{ job.status }} | |
notify_on_failure: | |
if: failure() | |
needs: [github-release, cleanup] | |
runs-on: ubuntu-latest | |
steps: | |
- name: Google Chat Notification | |
uses: Co-qn/google-chat-notification@3691ccf4763537d6e544bc6cdcccc1965799d056 # v1 | |
with: | |
name: | |
SSH no ports binaries build by GitHub Action ${{ github.run_number | |
}} | |
url: ${{ secrets.GOOGLE_CHAT_WEBHOOK }} | |
status: failure |