diff --git a/.github/workflows/git-push.yml b/.github/workflows/git-push.yml index 423fc97d..f6613675 100644 --- a/.github/workflows/git-push.yml +++ b/.github/workflows/git-push.yml @@ -69,6 +69,10 @@ jobs: id: native_ci_build run: | ./ci.cmd build + - name: Execute repo's AutomataCI - NOTARIZE + id: native_ci_notarize + run: | + ./ci.cmd notarize - name: Execute repo's AutomataCI - PACKAGE id: native_ci_package run: | diff --git a/CONFIG.toml b/CONFIG.toml index 965235ff..688845d8 100644 --- a/CONFIG.toml +++ b/CONFIG.toml @@ -142,7 +142,7 @@ PROJECT_C = '' # # To enable it: simply supply the path (e.g. default is 'srcGO'). # To disable it: simply supply an empty path (e.g. default is ''). -PROJECT_GO = '' +PROJECT_GO = 'srcGO' # PROJECT_PATH_GO_ENGINE @@ -165,7 +165,7 @@ PROJECT_PATH_GO_ENGINE = "go-engine" # # To enable it: simply supply the path (e.g. default is 'srcPYTHON'). # To disable it: simply supply an empty path (e.g. default is ''). -PROJECT_PYTHON = 'srcPYTHON' +PROJECT_PYTHON = '' # PROJECT_PATH_PYTHON_ENGINE @@ -213,12 +213,6 @@ PROJECT_CONTACT_EMAIL = "contact@youremail.example" PROJECT_CONTACT_WEBSITE = "https://your-product.website.here" -# PROJECT_GPG_ID -# Your GPG ID for signing here. Note that this requires GPG to be installed in -# the system and the secret key is available for performing such transaction. -PROJECT_GPG_ID = "" - - # PROJECT_CHANGELOG_TITLE # The title of the changelog file. PROJECT_CHANGELOG_TITLE = "Changelog | 更新日志 | Endringslogg | Cacatan Perubahan | Ändringslogg | 変更履歴" diff --git a/automataCI/SECRETS-template.toml b/automataCI/SECRETS-template.toml index 1dbef3b4..fd1470dc 100644 --- a/automataCI/SECRETS-template.toml +++ b/automataCI/SECRETS-template.toml @@ -34,3 +34,71 @@ CONTAINER_USERNAME = "" # Use to login your container image's registry's service provider (e.g. Docker, # GitHub Packages) etc. This is the account password or token value. CONTAINER_PASSWORD = "" + + + + +########################## +# MICROSOFT # +########################## +# MICROSOFT_CERT +# The cert file for Microsoft Windows' code-signing certifcate use. The format +# can be normal certifcate, SPC, or PKCS12. +MICROSOFT_CERT = "" + + +# MICROSOFT_CERT_HASH +# The shasum algorithm of the certificate for Microsoft Windows' code-signing +# certifcate use. It can be of the following values: +# 1) 'SHA256' +# 2) 'MD5' +# 3) 'SHA1' +# 4) 'SHA2' +# 5) 'SHA384' +# 6) 'SHA512' +MICROSOFT_CERT_HASH = "" + + +# MICROSOFT_CERT_TYPE +# The cert type for Microsoft Windows' code-signing certifcate use. It can only +# be the following values: +# 1. 'CERT' - conventional cert format +# 2. 'SPC' - SPC format +# 3. 'PKCS12' - PKCS12 container format +MICROSOFT_CERT_TYPE = "" + + +# MICROSOFT_CERT_TIMESTAMP +# The URL for sourcing the timestamp used in Microsoft Windows' code-signing +# process. Although specification stated not required, AutomataCI set it as +# compulsory. Known good cert location are: +# 1. http://timestamp.digicert.com +# 2. http://timestamp.sectigo.com +MICROSOFT_CERT_TIMESTAMP = "" + + +# MICROSOFT_KEYFILE +# The private keyfile for Microsoft Windows' code-signing certifcate use. It is +# optional if MICROSOFT_CERT is a PKCS12 format. +MICROSOFT_CERT_KEYFILE = "" + + +# MICROSOFT_CERT_PASSWORD +# Private password to unlock the Microsoft Windows' code-signing certifcate and +# private key for signing. Only used with osslsigncode and equivalent usually +# in Notary stage. +MICROSOFT_CERT_PASSWORD = "" + + + + +########################## +# APPLE # +########################## +# APPLE_DEVELOPER_ID +# The developer ID used for notarization process. +APPLE_DEVELOPER_ID = "" + +# APPLE_KEYCHAIN_PROFILE +# The keychain access used for accessing notarization credentials. +APPLE_KEYCHAIN_PROFILE = "" diff --git a/automataCI/ci.ps1 b/automataCI/ci.ps1 index 035f7b14..4cb4c791 100755 --- a/automataCI/ci.ps1 +++ b/automataCI/ci.ps1 @@ -167,6 +167,9 @@ switch ($args[0]) { } { $_ -in 'build', 'Build', 'BUILD' } { $env:PROJECT_CI_JOB = "build" $__exit = . "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PATH_AUTOMATA}\common_windows-any.ps1" +} { $_ -in 'notarize', 'Notarize', 'NOTARIZE' } { + $env:PROJECT_CI_JOB = "notarize" + $__exit = . "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PATH_AUTOMATA}\notarize_windows-any.ps1" } { $_ -in 'package', 'Package', 'PACKAGE' } { $env:PROJECT_CI_JOB = "package" $__exit = . "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PATH_AUTOMATA}\package_windows-any.ps1" @@ -200,6 +203,7 @@ switch ($args[0]) { Write-Host " To test the repo 🠚 $ ./ci.cmd test" Write-Host " Like build but only for host 🠚 $ ./ci.cmd materialize" Write-Host " To build the repo 🠚 $ ./ci.cmd build" + Write-Host " To notarize the builds 🠚 $ ./ci.cmd notarize" Write-Host " To package the repo product 🠚 $ ./ci.cmd package" Write-Host " To release the repo product 🠚 $ ./ci.cmd release" Write-Host " To stop a development 🠚 $ ./ci.cmd stop" diff --git a/automataCI/ci.sh b/automataCI/ci.sh index d3e67c3d..274cc8b3 100755 --- a/automataCI/ci.sh +++ b/automataCI/ci.sh @@ -225,6 +225,11 @@ build|Build|BUILD) . "${PROJECT_PATH_ROOT}/${PROJECT_PATH_AUTOMATA}/common_unix-any.sh" code=$? ;; +notarize|Notarize|NOTARIZE) + export PROJECT_CI_JOB="notarize" + . "${PROJECT_PATH_ROOT}/${PROJECT_PATH_AUTOMATA}/notarize_unix-any.sh" + code=$? + ;; package|Package|PACKAGE) export PROJECT_CI_JOB="package" . "${PROJECT_PATH_ROOT}/${PROJECT_PATH_AUTOMATA}/package_unix-any.sh" @@ -270,6 +275,7 @@ purge|Purge|PURGE) printf " To test the repo 🠚 $ ./ci.cmd test\n" printf " Like build but only for host 🠚 $ ./ci.cmd materialize\n" printf " To build the repo 🠚 $ ./ci.cmd build\n" + printf " To notarize the builds 🠚 $ ./ci.cmd notarize\n" printf " To package the repo product 🠚 $ ./ci.cmd package\n" printf " To release the repo product 🠚 $ ./ci.cmd release\n" printf " To stop a development 🠚 $ ./ci.cmd stop\n" diff --git a/automataCI/docs/AutomataCI-Engineering-Specification.odt b/automataCI/docs/AutomataCI-Engineering-Specification.odt index 184400e6..6371e492 100644 Binary files a/automataCI/docs/AutomataCI-Engineering-Specification.odt and b/automataCI/docs/AutomataCI-Engineering-Specification.odt differ diff --git a/automataCI/env_unix-any.sh b/automataCI/env_unix-any.sh index 5d8c0341..8a5133de 100644 --- a/automataCI/env_unix-any.sh +++ b/automataCI/env_unix-any.sh @@ -59,6 +59,14 @@ if [ $? -ne 0 ]; then fi +OS::print_status info "Installing osslsigncode...\n" +INSTALLER::setup_osslsigncode +if [ $? -ne 0 ]; then + OS::print_status error "install failed.\n" + return 1 +fi + + if [ ! -z "$PROJECT_PYTHON" ]; then OS::print_status info "Installing python...\n" INSTALLER::setup_python diff --git a/automataCI/notarize_unix-any.sh b/automataCI/notarize_unix-any.sh new file mode 100644 index 00000000..c66b4217 --- /dev/null +++ b/automataCI/notarize_unix-any.sh @@ -0,0 +1,187 @@ +#!/bin/sh +# Copyright 2023 (Holloway) Chew, Kean Ho +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at: +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + + + + +# initialize +if [ "$PROJECT_PATH_ROOT" = "" ]; then + >&2 printf "[ ERROR ] - Please run me from ci.cmd instead!\n" + return 1 +fi + +. "${PROJECT_PATH_ROOT}/${PROJECT_PATH_AUTOMATA}/services/io/os.sh" +. "${PROJECT_PATH_ROOT}/${PROJECT_PATH_AUTOMATA}/services/io/fs.sh" +. "${PROJECT_PATH_ROOT}/${PROJECT_PATH_AUTOMATA}/services/io/strings.sh" + + + + +# source locally provided functions +__recipe="${PROJECT_PATH_ROOT}/${PROJECT_PATH_SOURCE}/${PROJECT_PATH_CI}" +__recipe="${__recipe}/notarize_unix-any.sh" +FS::is_file "$__recipe" +if [ $? -eq 0 ]; then + OS::print_status info "sourcing content assembling functions: ${__recipe}\n" + . "$__recipe" + if [ $? -ne 0 ]; then + OS::print_status error "Sourcing failed\n" + return 1 + fi +fi + + + + +# source from Python and overrides existing +if [ ! -z "$PROJECT_PYTHON" ]; then + __recipe="${PROJECT_PATH_ROOT}/${PROJECT_PYTHON}/${PROJECT_PATH_CI}" + __recipe="${__recipe}/notarize_unix-any.sh" + FS::is_file "$__recipe" + if [ $? -eq 0 ]; then + OS::print_status info \ + "sourcing Python content assembling functions: ${__recipe}\n" + . "$__recipe" + if [ $? -ne 0 ]; then + OS::print_status error "Sourcing failed\n" + return 1 + fi + fi +fi + + + + +# source from Go and overrides existing +if [ ! -z "$PROJECT_GO" ]; then + __recipe="${PROJECT_PATH_ROOT}/${PROJECT_GO}/${PROJECT_PATH_CI}" + __recipe="${__recipe}/notarize_unix-any.sh" + FS::is_file "$__recipe" + if [ $? -eq 0 ]; then + OS::print_status info "sourcing Go content assembling functions: ${__recipe}\n" + . "$__recipe" + if [ $? -ne 0 ]; then + OS::print_status error "Sourcing failed\n" + return 1 + fi + fi +fi + + + + +# source from C and overrides existing +if [ ! -z "$PROJECT_C" ]; then + __recipe="${PROJECT_PATH_ROOT}/${PROJECT_C}/${PROJECT_PATH_CI}" + __recipe="${__recipe}/notarize_unix-any.sh" + FS::is_file "$__recipe" + if [ $? -eq 0 ]; then + OS::print_status info "sourcing C content assembling functions: ${__recipe}\n" + . "$__recipe" + if [ $? -ne 0 ]; then + OS::print_status error "Sourcing failed\n" + return 1 + fi + fi +fi + + + + +# source from Nim and overrides existing +if [ ! -z "$PROJECT_NIM" ]; then + __recipe="${PROJECT_PATH_ROOT}/${PROJECT_NIM}/${PROJECT_PATH_CI}" + __recipe="${__recipe}/notarize_unix-any.sh" + FS::is_file "$__recipe" + if [ $? -eq 0 ]; then + OS::print_status info "sourcing Nim content assembling functions: ${__recipe}\n" + . "$__recipe" + if [ $? -ne 0 ]; then + OS::print_status error "Sourcing failed\n" + return 1 + fi + fi +fi + + + + +# begin notarize +for i in "${PROJECT_PATH_ROOT}/${PROJECT_PATH_BUILD}"/*; do + if [ -d "$i" ]; then + continue + fi + + if [ ! -f "$i" ]; then + continue + fi + + + # parse build candidate + OS::print_status info "detected ${PROJECT_PATH_ROOT}/${PROJECT_PATH_BUILD}/${i}\n" + TARGET_FILENAME="${i##*${PROJECT_PATH_ROOT}/${PROJECT_PATH_BUILD}/}" + TARGET_FILENAME="${TARGET_FILENAME%.*}" + TARGET_OS="${TARGET_FILENAME##*_}" + TARGET_FILENAME="${TARGET_FILENAME%%_*}" + TARGET_ARCH="${TARGET_OS##*-}" + TARGET_OS="${TARGET_OS%%-*}" + + if [ -z "$TARGET_OS" ] || [ -z "$TARGET_ARCH" ] || [ -z "$TARGET_FILENAME" ]; then + OS::print_status warning "failed to parse file. Skipping.\n" + continue + fi + + STRINGS::has_prefix "$PROJECT_SKU" "$TARGET_FILENAME" + if [ $? -ne 0 ]; then + OS::print_status warning "incompatible file. Skipping.\n" + continue + fi + + + # execute + OS::is_command_available "NOTARY::certify" + if [ $? -eq 0 ]; then + NOTARY::certify \ + "$i" \ + "${PROJECT_PATH_ROOT}/${PROJECT_PATH_BUILD}" \ + "$TARGET_FILENAME" \ + "$TARGET_OS" \ + "$TARGET_ARCH" + case $? in + 12) + OS::print_status warning "simulating successful notarization...\n" + ;; + 11) + OS::print_status warning "notarization unavailable. Skipping...\n" + ;; + 10) + OS::print_status warning "notarization is not applicable. Skipping...\n" + ;; + 0) + OS::print_status success "\n\n" + ;; + *) + OS::print_status error "notarization failed.\n" + return 1 + ;; + esac + else + OS::print_status warning "NOTARY::certify is unavailable. Skipping...\n" + fi +done + + + + +# report status +return 0 diff --git a/automataCI/notarize_windows-any.ps1 b/automataCI/notarize_windows-any.ps1 new file mode 100644 index 00000000..e6915fe3 --- /dev/null +++ b/automataCI/notarize_windows-any.ps1 @@ -0,0 +1,185 @@ +# Copyright 2023 (Holloway) Chew, Kean Ho +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at: +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + + + +# initialize +if (-not (Test-Path -Path $env:PROJECT_PATH_ROOT)) { + Write-Error "[ ERROR ] - Please run me from ci.cmd instead!\n" + return 1 +} + +. "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PATH_AUTOMATA}\services\io\os.ps1" +. "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PATH_AUTOMATA}\services\io\fs.ps1" +. "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PATH_AUTOMATA}\services\io\strings.ps1" + + + + +# source locally provided functions +$__recipe = "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PATH_SOURCE}\${env:PROJECT_PATH_CI}" +$__recipe = "${__recipe}\notarize_windows-any.ps1" +$__process = FS-Is-File "${__recipe}" +if ($__process -eq 0) { + OS-Print-Status info "sourcing content assembling functions: ${__recipe}" + $__process = . "${__recipe}" + if ($__process -ne 0) { + OS-Print-Status error "Source failed." + return 1 + } +} + + + + +# source from Python and overrides existing +if (-not [string]::IsNullOrEmpty(${env:PROJECT_PYTHON})) { + $__recipe = "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PYTHON}\${env:PROJECT_PATH_CI}" + $__recipe = "${__recipe}\notarize_windows-any.ps1" + $__process = FS-Is-File "${__recipe}" + if ($__process -eq 0) { + OS-Print-Status info "sourcing Python content assembling functions: ${__recipe}" + $__process = . "${__recipe}" + if ($__process -ne 0) { + OS-Print-Status error "Source failed." + return 1 + } + } +} + + + + +# source from Go and overrides existing +if (-not [string]::IsNullOrEmpty(${env:PROJECT_GO})) { + $__recipe = "${env:PROJECT_PATH_ROOT}\${env:PROJECT_GO}\${env:PROJECT_PATH_CI}" + $__recipe = "${__recipe}\notarize_windows-any.ps1" + $__process = FS-Is-File "${__recipe}" + if ($__process -eq 0) { + OS-Print-Status info "sourcing Go content assembling functions: ${__recipe}" + $__process = . "${__recipe}" + if ($__process -ne 0) { + OS-Print-Status error "Source failed." + return 1 + } + } +} + + + + +# source from C and overrides existing +if (-not [string]::IsNullOrEmpty(${env:PROJECT_C})) { + $__recipe = "${env:PROJECT_PATH_ROOT}\${env:PROJECT_C}\${env:PROJECT_PATH_CI}" + $__recipe = "${__recipe}\notarize_windows-any.ps1" + $__process = FS-Is-File "${__recipe}" + if ($__process -eq 0) { + OS-Print-Status info "sourcing C content assembling functions: ${__recipe}" + $__process = . "${__recipe}" + if ($__process -ne 0) { + OS-Print-Status error "Source failed." + return 1 + } + } +} + + + + +# source from Nim and overrides existing +if (-not [string]::IsNullOrEmpty(${env:PROJECT_NIM})) { + $__recipe = "${env:PROJECT_PATH_ROOT}\${env:PROJECT_NIM}\${env:PROJECT_PATH_CI}" + $__recipe = "${__recipe}\notarize_windows-any.ps1" + $__process = FS-Is-File "${__recipe}" + if ($__process -eq 0) { + OS-Print-Status info "sourcing Nim content assembling functions: ${__recipe}" + $__process = . "${__recipe}" + if ($__process -ne 0) { + OS-Print-Status error "Source failed." + return 1 + } + } +} + + + + +# begin notarize +foreach ($i in (Get-ChildItem -Path "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PATH_BUILD}")) { + $i = "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PATH_BUILD}\${i}" + $__process = FS-Is-Directory "$i" + if ($__process -eq 0) { + continue + } + + $__process = FS-Is-File "$i" + if ($__process -ne 0) { + continue + } + + + # parse build candidate + OS-Print-Status info "detected $i" + $TARGET_FILENAME = Split-Path -Leaf $i + $TARGET_FILENAME = $TARGET_FILENAME -replace ` + (Join-Path $env:PROJECT_PATH_ROOT $env:PROJECT_PATH_BUILD), "" + $TARGET_FILENAME = $TARGET_FILENAME -replace "\..*$" + $TARGET_OS = $TARGET_FILENAME -replace ".*_" + $TARGET_FILENAME = $TARGET_FILENAME -replace "_.*" + $TARGET_ARCH = $TARGET_OS -replace ".*-" + $TARGET_OS = $TARGET_OS -replace "-.*" + + if ([string]::IsNullOrEmpty($TARGET_OS) -or + [string]::IsNullOrEmpty($TARGET_ARCH) -or + [string]::IsNullOrEmpty($TARGET_FILENAME)) { + OS-Print-Status warning "failed to parse file. Skipping." + continue + } + + $__process = STRINGS-Has-Prefix "${env:PROJECT_SKU}" "$TARGET_FILENAME" + if ($__process -ne 0) { + OS-Print-Status warning "incompatible file. Skipping." + continue + } + + $__process = OS-Is-Command-Available "NOTARY-Certify" + if ($__process -eq 0) { + $__process = NOTARY-Certify ` + "$i" ` + "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PATH_BUILD}" ` + "$TARGET_FILENAME" ` + "$TARGET_OS" ` + "$TARGET_ARCH" + switch ($__process) { + 12 { + OS-Print-Status warning "simulating successful notarization..." + } 11 { + OS-Print-Status warning "notarization unavailable. Skipping..." + } 10 { + OS-Print-Status warning "notarization is not applicable. Skipping..." + } 0 { + OS-Print-Status success "`n" + } default { + OS-Print-Status error "notarization failed." + return 1 + }} + } else { + OS-Print-Status warning "NOTARY-Certify is unavailable. Skipping..." + } +} + + + + +# report status +return 0 diff --git a/automataCI/package_unix-any.sh b/automataCI/package_unix-any.sh index e3dce875..65fed380 100644 --- a/automataCI/package_unix-any.sh +++ b/automataCI/package_unix-any.sh @@ -70,6 +70,10 @@ for i in "${PROJECT_PATH_ROOT}/${PROJECT_PATH_BUILD}"/*; do continue fi + if [ ! -f "$i" ]; then + continue + fi + # parse build candidate OS::print_status info "detected ${PROJECT_PATH_ROOT}/${PROJECT_PATH_BUILD}/${i}\n" diff --git a/automataCI/package_windows-any.ps1 b/automataCI/package_windows-any.ps1 index e48cde51..e3c4d57a 100644 --- a/automataCI/package_windows-any.ps1 +++ b/automataCI/package_windows-any.ps1 @@ -71,6 +71,11 @@ foreach ($i in (Get-ChildItem -Path "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PATH continue } + $__process = FS-Is-File "$i" + if ($__process -ne 0) { + continue + } + # parse build candidate OS-Print-Status info "detected $i" diff --git a/automataCI/services/compilers/installer.sh b/automataCI/services/compilers/installer.sh index 7de0d5e4..8e0027f3 100644 --- a/automataCI/services/compilers/installer.sh +++ b/automataCI/services/compilers/installer.sh @@ -308,6 +308,34 @@ INSTALLER::setup_nim() { +INSTALLER::setup_osslsigncode() { + # validate input + OS::is_command_available "brew" + if [ $? -ne 0 ]; then + return 1 + fi + + OS::is_command_available "osslsigncode" + if [ $? -eq 0 ]; then + return 0 + fi + + + # execute + brew install osslsigncode + + + # report status + if [ $? -eq 0 ]; then + return 0 + fi + + return 1 +} + + + + INSTALLER::setup_python() { # validate input OS::is_command_available "brew" diff --git a/automataCI/services/crypto/apple.ps1 b/automataCI/services/crypto/apple.ps1 new file mode 100644 index 00000000..d448d4d3 --- /dev/null +++ b/automataCI/services/crypto/apple.ps1 @@ -0,0 +1,114 @@ +# Copyright 2023 (Holloway) Chew, Kean Ho +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at: +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +. "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PATH_AUTOMATA}\services\io\os.ps1" +. "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PATH_AUTOMATA}\services\io\fs.ps1" + + + + +function APPLE-Sign { + param ( + [string]$__file, + [string]$__destination + ) + + + # validate input + $__process = APPLE-Is-Available + if ($__process -ne 0) { + return 1 + } + + if ([string]::IsNullOrEmpty($__file) -or + [string]::IsNullOrEmpty($__destination) -or + (-not (Test-Path -Path "${__file}"))) { + return 1 + } + + + # execute + $__arguments = "--force " ` + + "--options " ` + + "runtime " ` + + "--deep " ` + + "--sign " ` + + "${env:APPLE_DEVELOPER_ID} " ` + + "${__file}" + $__process = OS-Exec "codesign" "${__arguments}" + if ($__process -ne 0) { + return 1 + } + + $__process = OS-Exec "ditto" "-c -k --keepParent ${__file} ${__file}.zip" + if ($__process -ne 0) { + return 1 + } + + $__arguments = "notarytool " ` + + "submit " ` + + "${__file}.zip " ` + + "--keychain-profile `"${env:APPLE_KEYCHAIN_PROFILE}`" " ` + + "--wait" + $__process = OS-Exec "xcrun" "${__arguments}" + if ($__process -ne 0) { + return 1 + } + + $null = FS-Remove-Silently "${__file}.zip" + + $__process = OS-Exec "xcrun" "stapler staple `"${__file}`"" + if ($__process -ne 0) { + return 1 + } + + $__process = FS-Move "${__file}" "${__destination}" + if ($__process -ne 0) { + return 1 + } + + + # report status + return 0 +} + + + + +function APPLE-Is-Available { + # execute + $__process = OS-Is-Command-Available "codesign" + if ($__process -ne 0) { + return 1 + } + + $__process = OS-Is-Command-Available "ditto" + if ($__process -ne 0) { + return 1 + } + + $__process = OS-Is-Command-Available "xcrun" + if ($__process -ne 0) { + return 1 + } + + if ([string]::IsNullOrEmpty(${env:APPLE_DEVELOPER_ID})) { + return 1 + } + + if ([string]::IsNullOrEmpty(${env:APPLE_KEYCHAIN_PROFILE})) { + return 1 + } + + + # report status + return 0 +} diff --git a/automataCI/services/crypto/apple.sh b/automataCI/services/crypto/apple.sh new file mode 100644 index 00000000..9f75afd0 --- /dev/null +++ b/automataCI/services/crypto/apple.sh @@ -0,0 +1,99 @@ +#!/bin/sh +# Copyright 2023 (Holloway) Chew, Kean Ho +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at: +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +. "${PROJECT_PATH_ROOT}/${PROJECT_PATH_AUTOMATA}/services/io/fs.sh" + + + + +APPLE::sign() { + #__destination="$1" + #__file="$2" + + + # validate input + APPLE::is_available + if [ $? -ne 0 ]; then + return 1 + fi + + if [ -z "$1" ] || [ -z "$2" ] || [ ! -f "$2" ]; then + return 1 + fi + + + # execute + codesign --force --options runtime --deep --sign "$APPLE_DEVELOPER_ID" "$2" + if [ $? -ne 0 ]; then + return 1 + fi + + ditto -c -k --keepParent "$2" "${2}.zip" + if [ $? -ne 0 ]; then + return 1 + fi + + xcrun notarytool \ + submit \ + "${2}.zip" \ + --keychain-profile "$APPLE_KEYCHAIN_PROFILE" \ + --wait + if [ $? -ne 0 ]; then + return 1 + fi + + FS::remove_silently "${2}.zip" + + xcrun stapler staple "$2" + if [ $? -ne 0 ]; then + return 1 + fi + + FS::move "$2" "$1" + if [ $? -ne 0 ]; then + return 1 + fi + + + # report status + return 0 +} + + + + +APPLE::is_available() { + # execute + if [ -z "$(type -t codesign)" ]; then + return 1 + fi + + if [ -z "$(type -t ditto)" ]; then + return 1 + fi + + if [ -z "$(type -t xcrun)" ]; then + return 1 + fi + + if [ -z "$APPLE_DEVELOPER_ID" ]; then + return 1 + fi + + if [ -z "$APPLE_KEYCHAIN_PROFILE" ]; then + return 1 + fi + + + # report status + return 0 +} diff --git a/automataCI/services/crypto/microsoft.ps1 b/automataCI/services/crypto/microsoft.ps1 new file mode 100644 index 00000000..86a930ca --- /dev/null +++ b/automataCI/services/crypto/microsoft.ps1 @@ -0,0 +1,100 @@ +# Copyright 2023 (Holloway) Chew, Kean Ho +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at: +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +. "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PATH_AUTOMATA}\services\io\os.ps1" +. "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PATH_AUTOMATA}\services\io\fs.ps1" + + + + +function MICROSOFT-Sign { + param ( + [string]$__file, + [string]$__destination, + [string]$__name, + [string]$__website + ) + + + # validate input + $__process = MICROSOFT-Is-Available + if ($__process -ne 0) { + return 1 + } + + if ([string]::IsNullOrEmpty($__name) -or + [string]::IsNullOrEmpty($__website) -or + (-not (Test-Path -Path "${__file}"))) { + return 1 + } + + + # execute + switch (${env:MICROSOFT_CERT_TYPE}) { + PKCS12 { + $__arguments = "sign " ` + + "/f ${env:MICROSOFT_CERT} " ` + + "/fd ${env:MICROSOFT_CERT_HASH} " ` + + "/p ${env:MICROSOFT_CERT_PASSWORD} " ` + + "/n ${__name} " ` + + "/du ${__website} " ` + + "/t ${env:MICROSOFT_CERT_TIMESTAMP} " ` + + "${__file}" + } default { + return 1 + }} + + $__process = OS-Exec "signtool" "${__arguments}" + if ($__process -ne 0) { + return 1 + } + + $null = FS-Move "${__file}" "${__destination}" + + + # report status + return 0 +} + + + + +function MICROSOFT-Is-Available { + # execute + $__process = OS-Is-Command-Available "signtool" + if ($__process -ne 0) { + return 1 + } + + if (-not (Test-Path -Path "${env:MICROSOFT_CERT}")) { + return 1 + } + + if ([string]::IsNullOrEmpty(${env:MICROSOFT_CERT_TYPE})) { + return 1 + } + + if ([string]::IsNullOrEmpty(${env:MICROSOFT_CERT_TIMESTAMP})) { + return 1 + } + + if ([string]::IsNullOrEmpty(${env:MICROSOFT_CERT_HASH})) { + return 1 + } + + if ([string]::IsNullOrEmpty(${env:MICROSOFT_CERT_PASSWORD})) { + return 1 + } + + + # report status + return 0 +} diff --git a/automataCI/services/crypto/microsoft.sh b/automataCI/services/crypto/microsoft.sh new file mode 100644 index 00000000..e7002994 --- /dev/null +++ b/automataCI/services/crypto/microsoft.sh @@ -0,0 +1,138 @@ +#!/bin/sh +# Copyright 2023 (Holloway) Chew, Kean Ho +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at: +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +. "${PROJECT_PATH_ROOT}/${PROJECT_PATH_AUTOMATA}/services/io/fs.sh" + + + + +MICROSOFT::sign() { + __destination="$1" + __file="$2" + __name="$3" + __website="$4" + + + # validate input + MICROSOFT::is_available + if [ $? -ne 0 ]; then + return 1 + fi + + if [ -z "$__name" ] || + [ -z "$__website" ] || + [ ! -f "$__file" ] || + [ -z "$__destination" ]; then + return 1 + fi + + + # execute + case "$MICROSOFT_CERT_TYPE" in + CERT) + if [ ! -f "$MICROSOFT_CERT_KEYFILE" ]; then + return 1 + fi + + FS::remove_silently "$__destination" + osslsigncode sign \ + -certs "$MICROSOFT_CERT" \ + -h "$MICROSOFT_CERT_HASH" \ + -key "$MICROSOFT_CERT_KEYFILE" \ + -pass "$MICROSOFT_CERT_PASSWORD" \ + -n "$__name" \ + -i "$__website" \ + -t "$MICROSOFT_CERT_TIMESTAMP" \ + -in "$__file" \ + -out "$__destination" + if [ $? -ne 0 ]; then + return 1 + fi + ;; + SPC) + if [ ! -f "$MICROSOFT_CERT_KEYFILE" ]; then + return 1 + fi + + FS::remove_silently "$__destination" + osslsigncode sign \ + -spc "$MICROSOFT_CERT" \ + -h "$MICROSOFT_CERT_HASH" \ + -key "$MICROSOFT_CERT_KEYFILE" \ + -pass "$MICROSOFT_CERT_PASSWORD" \ + -n "$__name" \ + -i "$__website" \ + -t "$MICROSOFT_CERT_TIMESTAMP" \ + -in "$__file" \ + -out "$__destination" + if [ $? -ne 0 ]; then + return 1 + fi + ;; + PKCS12) + FS::remove_silently "$__destination" + osslsigncode sign \ + -pkcs12 "$MICROSOFT_CERT" \ + -h "$MICROSOFT_CERT_HASH" \ + -pass "$MICROSOFT_CERT_PASSWORD" \ + -n "$__name" \ + -i "$__website" \ + -t "$MICROSOFT_CERT_TIMESTAMP" \ + -in "$__file" \ + -out "$__destination" + if [ $? -ne 0 ]; then + return 1 + fi + ;; + *) + return 1 + ;; + esac + + + # report status + return 0 +} + + + + +MICROSOFT::is_available() { + # execute + if [ -z "$(type -t osslsigncode)" ]; then + return 1 + fi + + if [ ! -f "$MICROSOFT_CERT" ]; then + return 1 + fi + + if [ -z "$MICROSOFT_CERT_TYPE" ]; then + return 1 + fi + + if [ -z "$MICROSOFT_CERT_TIMESTAMP" ]; then + return 1 + fi + + if [ -z "$MICROSOFT_CERT_HASH" ]; then + return 1 + fi + + if [ -z "$MICROSOFT_CERT_PASSWORD" ]; then + return 1 + fi + + + # report status + return 0 +} diff --git a/src/.ci/notarize_unix-any.sh b/src/.ci/notarize_unix-any.sh new file mode 100644 index 00000000..a16c3bfd --- /dev/null +++ b/src/.ci/notarize_unix-any.sh @@ -0,0 +1,101 @@ +#!/bin/sh +# Copyright 2023 (Holloway) Chew, Kean Ho +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at: +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + + + + +# initialize +if [ "$PROJECT_PATH_ROOT" == "" ]; then + >&2 printf "[ ERROR ] - Please run from ci.cmd instead!\n" + return 1 +fi + +. "${PROJECT_PATH_ROOT}/${PROJECT_PATH_AUTOMATA}/services/io/os.sh" +. "${PROJECT_PATH_ROOT}/${PROJECT_PATH_AUTOMATA}/services/io/fs.sh" +. "${PROJECT_PATH_ROOT}/${PROJECT_PATH_AUTOMATA}/services/crypto/apple.sh" +. "${PROJECT_PATH_ROOT}/${PROJECT_PATH_AUTOMATA}/services/crypto/microsoft.sh" + + + + +NOTARY::certify() { + _target="$1" + _directory="$2" + _target_name="$3" + _target_os="$4" + _target_arch="$5" + + + # validate project + if [ $(FS::is_target_a_source "$_target") -eq 0 ]; then + return 10 # not applicable + elif [ $(FS::is_target_a_library "$_target") -eq 0 ]; then + return 10 # not applicable + elif [ $(FS::is_target_a_wasm_js "$_target") -eq 0 ]; then + return 10 # not applicable + elif [ $(FS::is_target_a_wasm "$_target") -eq 0 ]; then + return 10 # not applicable + elif [ $(FS::is_target_a_chocolatey "$_target") -eq 0 ]; then + return 10 # not applicable + elif [ $(FS::is_target_a_homebrew "$_target") -eq 0 ]; then + return 10 # not applicable + fi + + + # notarize + case "$_target_os" in + darwin) + if [ ! -z "$PROJECT_SIMULATE_RELEASE_REPO" ]; then + return 12 + fi + + APPLE::is_available + if [ $? -ne 0 ]; then + return 11 + fi + + _dest="${_target%/*}/${_target_name}-signed_${_target_os}-${_target_arch}" + APPLE::sign "$_dest" "$_target" + if [ $? -ne 0 ]; then + return 1 + fi + ;; + windows) + if [ ! -z "$PROJECT_SIMULATE_RELEASE_REPO" ]; then + return 12 + fi + + MICROSOFT::is_available + if [ $? -ne 0 ]; then + return 11 + fi + + _dest="${_target%/*}/${_target_name}-signed_${_target_os}-${_target_arch}.exe" + MICROSOFT::sign \ + "$_dest" \ + "$_target" \ + "$PROJECT_CONTACT_NAME" \ + "$PROJECT_CONTACT_WEBSITE" + if [ $? -ne 0 ]; then + return 1 + fi + ;; + *) + return 10 # not applicable + ;; + esac + + + # report status + return 0 +} diff --git a/src/.ci/notarize_windows-any.ps1 b/src/.ci/notarize_windows-any.ps1 new file mode 100644 index 00000000..aeef239b --- /dev/null +++ b/src/.ci/notarize_windows-any.ps1 @@ -0,0 +1,107 @@ +# Copyright 2023 (Holloway) Chew, Kean Ho +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy +# of the License at: +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + + + +# initialize +if (-not (Test-Path -Path $env:PROJECT_PATH_ROOT)) { + Write-Error "[ ERROR ] - Please run from ci.cmd instead!\n" + exit 1 +} + +. "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PATH_AUTOMATA}\services\io\os.ps1" +. "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PATH_AUTOMATA}\services\io\fs.ps1" +. "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PATH_AUTOMATA}\services\crypto\apple.ps1" +. "${env:PROJECT_PATH_ROOT}\${env:PROJECT_PATH_AUTOMATA}\services\crypto\microsoft.ps1" + + + + +function NOTARY-Certify { + param ( + [string]$_target, + [string]$_directory, + [string]$_target_name, + [string]$_target_os, + [string]$_target_arch + ) + + + # validate project + if ($(FS-Is-Target-A-Source "${_target}") -eq 0) { + return 10 # not applicable + } elseif ($(FS-Is-Target-A-Library "${_target}") -eq 0) { + return 10 # not applicable + } elseif ($(FS-Is-Target-A-WASM-JS "${_target}") -eq 0) { + return 10 # not applicable + } elseif ($(FS-Is-Target-A-WASM "${_target}") -eq 0) { + return 10 # not applicable + } elseif ($(FS-Is-Target-A-Chocolatey "${_target}") -eq 0) { + return 10 # not applicable + } elseif ($(FS-Is-Target-A-Homebrew "${_target}") -eq 0) { + return 10 # not applicable + } + + + # notarize + switch ($_target_os) { + darwin { + if (-not [string]::IsNullOrEmpty("${env:PROJECT_SIMULATE_RELEASE_REPO}")) { + return 12 + } + + $__process = APPLE-Is-Available + if ($__process -ne 0) { + return 11 + } + + $_dest = "$(Split-Path -Parent -Path "${_target}")" + $_dest = "${_dest}\${_target_name}-signed_${_target_os}-${_target_arch}" + $__process = APPLE-Sign "${_dest}" "${_target}" + if ($__process -ne 0) { + return 1 + } + } windows { + if (-not [string]::IsNullOrEmpty("${env:PROJECT_SIMULATE_RELEASE_REPO}")) { + return 12 + } + + $__process = MICROSOFT-Is-Available + if ($__process -ne 0) { + return 11 + } + + $_dest = "$(Split-Path -Parent -Path "${_target}")" + $_dest = "${_dest}\${_target_name}-signed_${_target_os}-${_target_arch}.exe" + $__process = MICROSOFT-Sign ` + "${_dest}" ` + "${_target}" ` + "${env:PROJECT_CONTACT_NAME}" ` + "${env:PROJECT_CONTACT_WEBSITE}" + if ($__process -ne 0) { + return 1 + } + } default { + return 10 # not applicable + }} + + + # report status + return 0 +} + + + + +# report status +return 0 diff --git a/src/changelog/data/latest b/src/changelog/data/latest index 3b570281..1d71cc75 100644 --- a/src/changelog/data/latest +++ b/src/changelog/data/latest @@ -1,3 +1,4 @@ +root: applied regressive changes to Python programming language root: applied regressive changes back to Go programming language root: applied regressive changes to C programming language root: added Nim Programming Language support \ No newline at end of file diff --git a/src/changelog/deb/latest b/src/changelog/deb/latest index 7a635687..538ac5a6 100644 --- a/src/changelog/deb/latest +++ b/src/changelog/deb/latest @@ -1,7 +1,8 @@ automataci (1.7.0) stable; urgency=low + * root: applied regressive changes to Python programming language * root: applied regressive changes back to Go programming language * root: applied regressive changes to C programming language * root: added Nim Programming Language support --- Your Legal Full Name Here Mon, 16 Oct 2023 15:45:41 +0800 +-- Your Legal Full Name Here Mon, 16 Oct 2023 16:40:51 +0800