Re-implement CI auto version increment for packaging (#7354)

* Only install Python deps with deps script

* Remove hard-coded Qt version in CI

* Add example .env

* Improve comments in .env file

* Simplify config reader and Choco CI config

* Actually return the config value

* Move deps before Qt version env call

* Remove `self.`

* Move venv ensure to main

* Fixed arg

* Move config import to function

* Move ensure_module to function

* Simplify over-complicated `Version.cmake`

* Move code to `github` module

* Use `symless/next-version-action`

* Make CMake version file even simpler

* Set version from tag

* Create release when master or release branch

* Don't run CI on master push, only release

* Fixed bac macro

* Use new version values

* Handle empty version env var

* Also strip version file value

* Remove quotes

* Add @master to action

* Read version from file

* Simplify version file read

* Fixed typo in env var

* Remove unused var

* Delete legacy build number action

* Fixed env var

* Version file read shouldn't be needed

* Remove weird and unnecessary include path

* Update ChangeLog

* Remove unused config value

* Better name for changelog check

* Delete broken Flatpak CI

* Run stale issue cron at midnight

* Update ChangeLog

* Add version input for manual run

* Print next version

* Fetch all tags

* Use more idiomatic approach

* Set to pre-release when master

* Remove unnecessary `commitish`

* Fixed wrong ID

* More specific IDs

* Reduce config needed for upload

* Only /release can be non-pre-release

* More discreet package path for gdrive

* Try without setting path

* Remove seemly unused step

* Better name for Qt version step

* Fixed bad var ref

* Better name for package dir

* Fixed bad input name

* Add missing shell

* Workflow to test upload action

* Remove fetch tags

* Use bash to cut version

* Remove name and make conditional

* Replace deprecated set-output

* Fixed env var name

* Missing dir sep char

* Add comment to test workflow

* Improve input descriptions

* Replace deprecated set-output
This commit is contained in:
Nick Bolton 2024-06-26 16:46:42 +01:00 committed by GitHub
parent 17c64e2f3a
commit 7103bbed6d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 277 additions and 5382 deletions

34
.env.example Normal file
View file

@ -0,0 +1,34 @@
#
# Usage: Copy this .env.example file to .env
#
#
# Build
#
# [Windows] The version of Qt to build against (overrides the value in the config.yml file)
# QT_VERSION=1.2.3
#
# Packaging (optional)
#
# [macOS] Apple ID used to notarize the app
# APPLE_NOTARY_USER="example@example.com"
# [macOS] App-specific password for the Apple ID
# https://support.apple.com/en-gb/102654
# APPLE_NOTARY_PASSWORD="super-secret-password"
# [macOS] Apple Team ID
# https://developer.apple.com/account/#/membership
# APPLE_TEAM_ID="ABC123XYZ9"
# [macOS] Certificate ID for the Developer ID Application code signing certificate
# APPLE_CODESIGN_ID="Developer ID Application: Acme Inc (ABC123XYZ9)"
# [macOS] Password for the P12 code signing certificate
# APPLE_P12_PASSWORD="super-secret-password"
# [macOS] Base64 encoded P12 code signing certificate
# APPLE_P12_CERTIFICATE="very-long-base64-encoded-string"

View file

@ -1 +0,0 @@
node_modules

View file

@ -1 +0,0 @@
v20

View file

@ -1,10 +0,0 @@
name: "Generate next build number"
description: "Generate next build number"
outputs:
build-number:
description: "Generated build number"
runs:
using: "node20"
main: "dist/index.js"

File diff suppressed because it is too large Load diff

View file

@ -1,222 +0,0 @@
const core = require('@actions/core');
const { Octokit } = require("@octokit/core");
const fs = require('fs');
function VersionPart(part) {
var self = this;
var m_prefix = '';
var m_suffix = '';
var m_number = 0;
self.setNumber = function(number) {
if (!isNaN(number)) {
m_number = number;
}
}
self.getNumber = function() {
return m_number;
}
self.getSuffix = function(){
return m_suffix;
}
self.toString = function() {
return m_prefix + m_number.toString() + m_suffix;
}
self.next = function() {
m_number += 1;
}
function parsePartPrefix(part) {
if (isNaN(part[0])) {
for (var i = 0; i < part.length; ++i) {
if (!isNaN(part[i])) {
break;
}
m_prefix += part[i];
}
}
}
function parsePartNumber(part) {
let number = 0;
if (m_prefix.length > 0){
number = parseInt(part.substring(m_prefix.length));
}
else{
number = parseInt(part);
}
self.setNumber(number);
}
function parsePartSuffix(part) {
let items = part.split('-');
if (items.length == 2) {
m_suffix = '-' + items[1];
}
}
self.setPart = function(part) {
if (part && part.length > 0){
parsePartPrefix(part);
parsePartNumber(part);
parsePartSuffix(part);
}
}
self.setPart(part);
}
function Version(version) {
const PARTS_DELIMITER = '.';
var m_major = new VersionPart();
var m_minor = new VersionPart();
var m_patch = new VersionPart();
var m_build = new VersionPart();
this.toString = function() {
return ( m_major.toString() + PARTS_DELIMITER +
m_minor.toString() + PARTS_DELIMITER +
m_patch.toString() + PARTS_DELIMITER +
m_build.toString());
}
this.isEmpty = function(){
return (!this.getMajor() && !this.getMinor() && !this.getPatch());
}
this.nextBuild = function() {
m_build.next();
}
function init() {
if (version)
{
let versionParts = version.split(PARTS_DELIMITER);
if (versionParts.length == 3) {
m_major.setPart(versionParts[0]);
m_minor.setPart(versionParts[1]);
m_build.setPart(versionParts[2]);
m_patch.setNumber(m_build.getNumber());
m_build.setNumber(0);
}
else if (versionParts.length == 4) {
m_major.setPart(versionParts[0]);
m_minor.setPart(versionParts[1]);
m_patch.setPart(versionParts[2]);
m_build.setPart(versionParts[3]);
}
else {
core.setFailed('ERROR: wrong version number <' + version + '>');
}
}
}
this.getMajor = function() {
return m_major.getNumber();
}
this.getMinor = function() {
return m_minor.getNumber();
}
this.getPatch = function() {
return m_patch.getNumber();
}
this.getStage = function(){
return m_build.getSuffix();
}
this.isSamePatch = function(version) {
return (this.getMajor() == version.getMajor() &&
this.getMinor() == version.getMinor() &&
this.getPatch() == version.getPatch());
}
init();
}
function getOptionValue(source, option) {
let start = source.indexOf(option);
if (start != -1) {
start += option.length + 1;
let end = source.indexOf(')', start);
return source.toString('utf8', start, end).replace(/\"/g, '').trim();
}
else{
core.setFailed("ERROR: Can't find option <" + option + ">");
}
}
async function getVersionApi()
{
const octokit = new Octokit({});
let response = await octokit.request('GET /repos/{owner}/{repo}/releases?per_page=100', {
owner: 'symless',
repo: 'synergy-core'
});
return response.data;
}
async function getVersionsFromGithub(cmakeVersion)
{
let gitVersion = new Version();
let versions = await getVersionApi();
for (let i = 0; i < versions.length; ++i) {
let version = new Version(versions[i].tag_name);
if (version.isSamePatch(cmakeVersion)) {
gitVersion = version;
break;
}
}
return gitVersion;
}
function getVersionFromFile(){
let options = fs.readFileSync('cmake/Version.cmake');
let major = getOptionValue(options, 'SYNERGY_VERSION_MAJOR');
let minor = getOptionValue(options, 'SYNERGY_VERSION_MINOR');
let patch = getOptionValue(options, 'SYNERGY_VERSION_PATCH');
let stage = getOptionValue(options, 'SYNERGY_VERSION_STAGE');
return new Version(major + '.' + minor + '.' + patch + '-' + stage);
}
async function main()
{
try {
let version = null;
let cmakeVersion = getVersionFromFile();
let gitVersion = await getVersionsFromGithub(cmakeVersion);
console.log('INFO: Version from Git: <' + gitVersion.toString() + '>');
console.log('INFO: Version from cmake: <' + cmakeVersion.toString() + '>');
if (gitVersion.isEmpty()) {
version = cmakeVersion;
}
else {
gitVersion.nextBuild();
version = gitVersion;
}
console.log('INFO: Generate build version: <' + version.toString() + '>');
core.setOutput('next-build', version.toString());
} catch (error) {
core.setFailed(error.message);
}
};
main();

View file

@ -1,190 +0,0 @@
{
"name": "build-number",
"version": "0.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "build-number",
"version": "0.0.0",
"license": "ISC",
"dependencies": {
"@actions/core": "^1.10.1",
"@octokit/core": "^5.0.0"
},
"devDependencies": {
"@vercel/ncc": "^0.38.0"
}
},
"node_modules/@actions/core": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz",
"integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==",
"dependencies": {
"@actions/http-client": "^2.0.1",
"uuid": "^8.3.2"
}
},
"node_modules/@actions/http-client": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.1.1.tgz",
"integrity": "sha512-qhrkRMB40bbbLo7gF+0vu+X+UawOvQQqNAA/5Unx774RS8poaOhThDOG6BGmxvAnxhQnDp2BG/ZUm65xZILTpw==",
"dependencies": {
"tunnel": "^0.0.6"
}
},
"node_modules/@octokit/auth-token": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
"integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==",
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/core": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.0.tgz",
"integrity": "sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==",
"dependencies": {
"@octokit/auth-token": "^4.0.0",
"@octokit/graphql": "^7.0.0",
"@octokit/request": "^8.0.2",
"@octokit/request-error": "^5.0.0",
"@octokit/types": "^11.0.0",
"before-after-hook": "^2.2.0",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/endpoint": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.0.tgz",
"integrity": "sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==",
"dependencies": {
"@octokit/types": "^11.0.0",
"is-plain-object": "^5.0.0",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/graphql": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.1.tgz",
"integrity": "sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==",
"dependencies": {
"@octokit/request": "^8.0.1",
"@octokit/types": "^11.0.0",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/openapi-types": {
"version": "18.0.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz",
"integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw=="
},
"node_modules/@octokit/request": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.1.tgz",
"integrity": "sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==",
"dependencies": {
"@octokit/endpoint": "^9.0.0",
"@octokit/request-error": "^5.0.0",
"@octokit/types": "^11.1.0",
"is-plain-object": "^5.0.0",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/request-error": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.0.tgz",
"integrity": "sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==",
"dependencies": {
"@octokit/types": "^11.0.0",
"deprecation": "^2.0.0",
"once": "^1.4.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/types": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.1.0.tgz",
"integrity": "sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==",
"dependencies": {
"@octokit/openapi-types": "^18.0.0"
}
},
"node_modules/@vercel/ncc": {
"version": "0.38.0",
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.0.tgz",
"integrity": "sha512-B4YKZMm/EqMptKSFyAq4q2SlgJe+VCmEH6Y8gf/E1pTlWbsUJpuH1ymik2Ex3aYO5mCWwV1kaSYHSQOT8+4vHA==",
"dev": true,
"bin": {
"ncc": "dist/ncc/cli.js"
}
},
"node_modules/before-after-hook": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
},
"node_modules/deprecation": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
},
"node_modules/is-plain-object": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/tunnel": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
"engines": {
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
}
},
"node_modules/universal-user-agent": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
},
"node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
}
}
}

View file

@ -1,19 +0,0 @@
{
"name": "build-number",
"version": "0.0.0",
"description": "Calculate the current version",
"main": "dist/index.js",
"private": true,
"scripts": {
"build": "ncc build main.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"@actions/core": "^1.10.1",
"@octokit/core": "^5.0.0"
},
"devDependencies": {
"@vercel/ncc": "^0.38.0"
}
}

View file

@ -1,28 +1,39 @@
name: "Distribute upload" name: "Distribute upload"
description: "Uploads the package from the dist dir to GitHub artifacts or Google Drive" description: "Uploads the package from the dist dir to GitHub artifacts or Google Drive"
inputs: inputs:
service: use_github:
description: "Where to upload the package (github or gdrive)" description: "Whether to upload to GitHub artifacts"
default: "github"
use_gdrive:
description: "Whether to upload to Google Drive"
github-target-filename: github-target-filename:
description: "The filename to upload (only used by GitHub artifacts)" description: "Filename to upload (GitHub artifacts)"
gdrive-target-dir: gdrive-target-base-dir:
description: "The directory to upload (only used by Google Drive)" description: "Base directory to upload (Google Drive)"
gdrive-secret-key: gdrive-secret-key:
description: "The Google Drive secret key" description: "Google Drive secret key"
gdrive-parent-folder-id: gdrive-parent-folder-id:
description: "The Google Drive parent folder ID" description: "Google Drive parent folder ID"
package-version:
description: "Package version appended to the Google Drive dir"
runs: runs:
using: "composite" using: "composite"
steps: steps:
- if: ${{ inputs.use_gdrive == 'true' }}
run: |
SHORT_VERSION=$(echo "${{ inputs.package-version }}" | cut -d'-' -f1)
echo "SHORT_VERSION=$SHORT_VERSION" >> $GITHUB_ENV
shell: bash
# Upload to GitHub # Upload to GitHub
- if: ${{ inputs.service == 'github' }} - if: ${{ inputs.use_github == 'true' }}
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: ${{ inputs.github-target-filename }} name: ${{ inputs.github-target-filename }}
@ -30,10 +41,10 @@ runs:
retention-days: 3 retention-days: 3
# Upload to Google Drive # Upload to Google Drive
- if: ${{ inputs.service == 'gdrive' }} - if: ${{ inputs.use_gdrive }}
uses: symless/gdrive-upload@target-glob uses: symless/gdrive-upload@target-glob
with: with:
credentials: ${{ inputs.gdrive-secret-key }} credentials: ${{ inputs.gdrive-secret-key }}
target: "./dist/*" target: "./dist/*"
parent_folder_id: ${{ inputs.gdrive-parent-folder-id }} parent_folder_id: ${{ inputs.gdrive-parent-folder-id }}
child_folder: Snapshots/${{ inputs.gdrive-target-dir }} child_folder: Packages/${{ inputs.gdrive-target-base-dir }}/${{ env.SHORT_VERSION }}/${{ inputs.package-version }}

View file

@ -2,19 +2,22 @@ name: CI
on: on:
workflow_dispatch: workflow_dispatch:
inputs:
version:
description: Synergy version number
pull_request: pull_request:
types: types:
- opened - opened
- reopened - reopened
- synchronize - synchronize
- ready_for_review - ready_for_review
push: release:
branches: types: [published]
- master*
- release*
env: env:
GIT_COMMIT: ${{ github.sha }} SYNERGY_VERSION: ${{ github.event.inputs.version || github.event.release.tag_name }}
UPLOAD_TO_GITHUB: ${{ github.event_name == 'pull_request' && !github.event.pull_request.draft }}
UPLOAD_TO_GDRIVE: ${{ github.event_name != 'pull_request' }}
jobs: jobs:
windows: windows:
@ -24,7 +27,6 @@ jobs:
env: env:
QT_BASE_DIR: ${{ github.workspace }}\deps\Qt QT_BASE_DIR: ${{ github.workspace }}\deps\Qt
QT_VERSION: 5.15.2
steps: steps:
- name: Checkout - name: Checkout
@ -32,6 +34,12 @@ jobs:
with: with:
submodules: "recursive" submodules: "recursive"
- name: Install dependencies
run: python ./scripts/install_deps.py
- name: Set QT_VERSION env var
run: python ./scripts/github_env.py --set-qt-version
- name: Cache Qt - name: Cache Qt
id: cache-qt id: cache-qt
uses: actions/cache@v1 uses: actions/cache@v1
@ -43,9 +51,6 @@ jobs:
if: steps.cache-qt.outputs.cache-hit != 'true' if: steps.cache-qt.outputs.cache-hit != 'true'
run: python ./scripts/install_deps.py --only qt run: python ./scripts/install_deps.py --only qt
- name: Install dependencies
run: python ./scripts/install_deps.py
- name: Setup VC++ environment - name: Setup VC++ environment
uses: ilammy/msvc-dev-cmd@v1 uses: ilammy/msvc-dev-cmd@v1
@ -54,9 +59,6 @@ jobs:
CMAKE_PREFIX_PATH: "${{ env.QT_BASE_DIR }}\\${{ env.QT_VERSION }}\\msvc2019_64\\" CMAKE_PREFIX_PATH: "${{ env.QT_BASE_DIR }}\\${{ env.QT_VERSION }}\\msvc2019_64\\"
run: cmake -B build --preset=windows-release run: cmake -B build --preset=windows-release
- name: Set env vars
run: python ./scripts/github_env.py
- name: Build - name: Build
run: cmake --build build run: cmake --build build
@ -94,16 +96,6 @@ jobs:
shell: "/usr/bin/arch -arch arm64e /bin/bash --noprofile --norc -eo pipefail {0}" shell: "/usr/bin/arch -arch arm64e /bin/bash --noprofile --norc -eo pipefail {0}"
steps: steps:
- name: Setup PATH
run: |
case "$ARCH" in
"arm64")
echo "/opt/homebrew/bin" >> $GITHUB_PATH
;;
esac
env:
ARCH: ${{ matrix.runtime.arch }}
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
@ -117,9 +109,6 @@ jobs:
CMAKE_OSX_DEPLOYMENT_TARGET: ${{ matrix.runtime.target }} CMAKE_OSX_DEPLOYMENT_TARGET: ${{ matrix.runtime.target }}
run: cmake -B build --preset=macos-release -DCMAKE_PREFIX_PATH=$(brew --prefix qt@5) run: cmake -B build --preset=macos-release -DCMAKE_PREFIX_PATH=$(brew --prefix qt@5)
- name: Set env vars
run: ./scripts/github_env.py
- name: Build - name: Build
run: cmake --build build run: cmake --build build
@ -137,21 +126,17 @@ jobs:
APPLE_NOTARY_PASSWORD: ${{ secrets.APPLE_NOTARY_PASSWORD }} APPLE_NOTARY_PASSWORD: ${{ secrets.APPLE_NOTARY_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
- name: Upload to GitHub - name: Upload
if: ${{ github.event_name == 'pull_request' && !github.event.pull_request.draft }} if:
uses: ./.github/actions/dist-upload uses: ./.github/actions/dist-upload
with: with:
service: "github" use_github: ${{ env.UPLOAD_TO_GITHUB }}
use_gdrive: ${{ env.UPLOAD_TO_GDRIVE }}
github-target-filename: "synergy-macos-${{ matrix.runtime.target }}" github-target-filename: "synergy-macos-${{ matrix.runtime.target }}"
gdrive-target-base-dir: "synergy1/personal"
- name: Upload to Google Drive
if: github.event_name != 'pull_request'
uses: ./.github/actions/dist-upload
with:
service: "gdrive"
gdrive-target-dir: "synergy1/v1-core-standard/${{ env.SYNERGY_VERSION }}"
gdrive-secret-key: ${{ secrets.GOOGLE_DRIVE_KEY }} gdrive-secret-key: ${{ secrets.GOOGLE_DRIVE_KEY }}
gdrive-parent-folder-id: ${{ secrets.GOOGLE_DRIVE_TECH_DRIVE }} gdrive-parent-folder-id: ${{ secrets.GOOGLE_DRIVE_TECH_DRIVE }}
package-version: ${{ env.SYNERGY_VERSION }}
linux: linux:
runs-on: ${{ matrix.distro.runs-on }} runs-on: ${{ matrix.distro.runs-on }}
@ -206,9 +191,7 @@ jobs:
submodules: "recursive" submodules: "recursive"
- name: Install dependencies - name: Install dependencies
run: | run: ./scripts/install_deps.py
${{ matrix.distro.python-deps }}
./scripts/install_deps.py
- name: Configure (modern) - name: Configure (modern)
if: ${{ !matrix.distro.legacy-cmake }} if: ${{ !matrix.distro.legacy-cmake }}
@ -219,9 +202,6 @@ jobs:
if: ${{ matrix.distro.legacy-cmake }} if: ${{ matrix.distro.legacy-cmake }}
run: cmake -B build -DCMAKE_BUILD_TYPE=Release run: cmake -B build -DCMAKE_BUILD_TYPE=Release
- name: Set env vars
run: ./scripts/github_env.py
- name: Build - name: Build
run: cmake --build build run: cmake --build build

View file

@ -1,9 +1,11 @@
name: Create Release name: Create release
on: on:
workflow_dispatch: workflow_dispatch:
push: push:
branches: [master] branches:
- master*
- release*
jobs: jobs:
create-release: create-release:
@ -11,23 +13,31 @@ jobs:
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- name: Checkout git repo - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
# Fetch all tags
fetch-depth: 0 fetch-depth: 0
- name: "Generate next build number" - name: Read version file
id: build run: echo "CURRENT_VERSION=$(cat VERSION)" >> $GITHUB_ENV
uses: "./.github/actions/build-number"
- name: Create Release - name: Get next version
id: next-version
uses: symless/next-version-action@master
with:
current-version: ${{ env.CURRENT_VERSION }}
- name: Print next version
run: echo ${{ steps.next-version.outputs.next-version }}
- name: Create release
id: create_release id: create_release
uses: actions/create-release@v1 uses: actions/create-release@v1
with:
tag_name: ${{ steps.build.outputs.next-build }}
release_name: ${{ steps.build.outputs.next-build }}
commitish: master
draft: false
prerelease: true
env: env:
GITHUB_TOKEN: ${{ secrets.RELEASE_EVENT_PROPAGATION_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.next-version.outputs.next-version }}
release_name: ${{ steps.next-version.outputs.next-version }}
draft: false
prerelease: ${{ !startsWith(github.ref, 'refs/heads/release') }}

View file

@ -1,106 +0,0 @@
name: "Build Linux Flatpak"
on:
release:
types: [created]
jobs:
build-linux-flatpak:
name: ubuntu-flatpak
runs-on: ubuntu-latest
timeout-minutes: 10
container:
image: symless/synergy-core:ubuntu20.04
options: --privileged
strategy:
matrix:
runtime:
- name: synergy
remote_folder: v1-core-standard
enterprise: ""
business: ""
- name: synergy-enterprise
remote_folder: v1-core-enterprise
enterprise: "1"
business: ""
- name: synergy-business
remote_folder: v1-core-business
enterprise: ""
business: "1"
env:
GIT_COMMIT: ${{ github.sha }}
SYNERGY_ENTERPRISE: ${{ matrix.runtime.enterprise }}
SYNERGY_BUSINESS: ${{ matrix.runtime.business }}
steps:
- name: Checkout git repo
uses: actions/checkout@v3
with:
submodules: "recursive"
fetch-depth: "0"
- name: Install Dependencies
run: |
apt-get update
apt-get install -y \
cmake python3 g++ \
libssl-dev libx11-dev xorg-dev qtbase5-dev \
libglib2.0-dev libgdk-pixbuf2.0-dev libnotify-dev \
flatpak flatpak-builder
- name: Work around https://github.com/actions/checkout/issues/766
run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: Version Info
id: version
run: |
python3 scripts/build_version.py
mkdir -p version-info && cd version-info && cmake .. && cd ..
. ./version-info/version
rm -rf version-info
SYNERGY_VERSION="$SYNERGY_VERSION_MAJOR.$SYNERGY_VERSION_MINOR.$SYNERGY_VERSION_PATCH"
SYNERGY_REVISION=$(git rev-parse --short=8 HEAD)
SYNERGY_FLATPAK_NAME="${{ matrix.runtime.name }}_${SYNERGY_VERSION}-${SYNERGY_VERSION_STAGE}.${SYNERGY_REVISION}"
echo "::set-output name=SYNERGY_VERSION_MAJOR::${SYNERGY_VERSION_MAJOR}"
echo "::set-output name=SYNERGY_VERSION_MINOR::${SYNERGY_VERSION_MINOR}"
echo "::set-output name=SYNERGY_VERSION_PATCH::${SYNERGY_VERSION_PATCH}"
echo "::set-output name=SYNERGY_VERSION_STAGE::${SYNERGY_VERSION_STAGE}"
echo "::set-output name=SYNERGY_VERSION_BUILD::${SYNERGY_VERSION_BUILD}"
echo "::set-output name=SYNERGY_VERSION::${SYNERGY_VERSION}"
echo "::set-output name=SYNERGY_REVISION::${SYNERGY_REVISION}"
echo "::set-output name=SYNERGY_FLATPAK_NAME::${SYNERGY_FLATPAK_NAME}"
echo "::set-output name=SYNERGY_REMOTE_FOLDER::${{ matrix.runtime.remote_folder }}/${SYNERGY_VERSION}/${SYNERGY_VERSION_STAGE}/b${SYNERGY_VERSION_BUILD}-${SYNERGY_REVISION}"
- name: Install flatpak
run: |
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak install -y org.kde.Platform//5.15-21.08
flatpak install -y org.kde.Sdk//5.15-21.08
- name: Build
run: |
cd flatpak
flatpak-builder build ${{ matrix.runtime.name }}.yml --disable-cache --force-clean
flatpak build-export export build
flatpak build-bundle export ${{ steps.version.outputs.SYNERGY_FLATPAK_NAME }}.flatpak com.symless.Synergy master --runtime-repo=https://flathub.org/repo/flathub.flatpakrepo
- name: Upload Artifact
if: "github.event_name == 'pull_request'"
uses: actions/upload-artifact@v2
with:
name: ${{ steps.version.outputs.SYNERGY_FLATPAK_NAME }}
path: flatpak/${{ steps.version.outputs.SYNERGY_FLATPAK_NAME }}.flatpak
retention-days: 1
- name: Send package to Binary Storage
if: "github.event_name == 'release'"
uses: garygrossgarten/github-action-scp@v0.7.3
with:
local: flatpak/${{ steps.version.outputs.SYNERGY_FLATPAK_NAME }}.flatpak
remote: ${{ secrets.BINARIES_SSH_DIR }}/${{ steps.version.outputs.SYNERGY_REMOTE_FOLDER }}/${{ steps.version.outputs.SYNERGY_FLATPAK_NAME }}.flatpak
host: ${{ secrets.BINARIES_SSH_HOST }}
username: ${{ secrets.BINARIES_SSH_USER }}
privateKey: ${{ secrets.BINARIES_SSH_KEY }}

View file

@ -1,7 +1,7 @@
name: "Close stale issues and PRs" name: "Close stale issues and PRs"
on: on:
schedule: schedule:
- cron: "30 1 * * *" - cron: "0 0 * * *"
jobs: jobs:
stale-issues: stale-issues:

View file

@ -1,3 +1,6 @@
# Used only for testing the `dist-upload` action.
# Triggered using 'Run workflow' in the Actions tab.
name: Test dist upload name: Test dist upload
on: on:
@ -11,11 +14,25 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
# Fetch all tags
fetch-depth: 0
- name: Make test dist - name: Make test dist
run: | run: |
mkdir dist mkdir dist
echo "test" > dist/test echo "test" > dist/test
- name: Upload to GitHub
if:
uses: ./.github/actions/dist-upload
with:
use_github: true
github-target-filename: "test"
- name: Upload to Google Drive
if:
uses: ./.github/actions/dist-upload
with:
use_gdrive: true
gdrive-target-base-dir: "test"
gdrive-secret-key: ${{ secrets.GOOGLE_DRIVE_KEY }}
gdrive-parent-folder-id: ${{ secrets.GOOGLE_DRIVE_TECH_DRIVE }}
package-version: 1.0.0-test

View file

@ -34,6 +34,7 @@ Enhancements:
- #7351 Use deps script to make life easier for contribs - #7351 Use deps script to make life easier for contribs
- #7352 Combine GitHub workflows to reduce config duplication - #7352 Combine GitHub workflows to reduce config duplication
- #7353 Re-implement packaging for GitHub workflows (macOS) - #7353 Re-implement packaging for GitHub workflows (macOS)
- #7354 Re-implement CI auto version increment for packaging
# 1.14.6 # 1.14.6

1
VERSION Normal file
View file

@ -0,0 +1 @@
1.15.0-beta

View file

@ -1,78 +1,14 @@
# #
# Synergy Version # Gets the version number either from an env var or from the VERSION file.
# #
set (SYNERGY_VERSION_MAJOR 1) set (VERSION $ENV{SYNERGY_VERSION})
set (SYNERGY_VERSION_MINOR 15) string(STRIP "${VERSION}" VERSION)
set (SYNERGY_VERSION_PATCH 0)
set (SYNERGY_VERSION_STAGE "snapshot")
# CI changes this to the current tag, but doesn't commit if (NOT VERSION)
set (SYNERGY_VERSION_BUILD 1) file(READ "${CMAKE_SOURCE_DIR}/VERSION" VERSION)
string(STRIP "${VERSION}" VERSION)
#
# Version from CI
#
if (DEFINED ENV{SYNERGY_VERSION_MAJOR})
set (SYNERGY_VERSION_MAJOR $ENV{SYNERGY_VERSION_MAJOR})
endif() endif()
if (DEFINED ENV{SYNERGY_VERSION_MINOR}) message (STATUS "Version number: " ${VERSION})
set (SYNERGY_VERSION_MINOR $ENV{SYNERGY_VERSION_MINOR}) add_definitions (-DSYNERGY_VERSION="${VERSION}")
endif()
if (DEFINED ENV{SYNERGY_VERSION_PATCH})
set (SYNERGY_VERSION_PATCH $ENV{SYNERGY_VERSION_PATCH})
endif()
if (DEFINED ENV{SYNERGY_VERSION_STAGE})
set (SYNERGY_VERSION_STAGE $ENV{SYNERGY_VERSION_STAGE})
endif()
if (NOT DEFINED SYNERGY_REVISION)
if (DEFINED ENV{GIT_COMMIT})
string (SUBSTRING $ENV{GIT_COMMIT} 0 8 SYNERGY_REVISION)
elseif (SYNERGY_VERSION_STAGE STREQUAL "snapshot")
execute_process (
COMMAND git rev-parse --short=8 HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE SYNERGY_REVISION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif()
endif()
if (DEFINED SYNERGY_REVISION)
string(LENGTH ${SYNERGY_REVISION} SYNERGY_REVISION_LENGTH)
if (NOT ((SYNERGY_REVISION MATCHES "^[a-f0-9]+") AND (SYNERGY_REVISION_LENGTH EQUAL "8")))
message (FATAL_ERROR "SYNERGY_REVISION ('${SYNERGY_REVISION}') should be a short commit hash")
endif()
unset (SYNERGY_REVISION_LENGTH)
else()
set (SYNERGY_REVISION "0badc0de")
endif()
if (DEFINED ENV{BUILD_NUMBER})
set (SYNERGY_VERSION_BUILD $ENV{BUILD_NUMBER})
endif()
string (TIMESTAMP SYNERGY_BUILD_DATE "%Y%m%d" UTC)
set (SYNERGY_SNAPSHOT_INFO "${SYNERGY_VERSION_STAGE}.${SYNERGY_REVISION}")
set (SYNERGY_VERSION_TAG "${SYNERGY_VERSION_STAGE}+build-${SYNERGY_VERSION_BUILD}+${SYNERGY_REVISION}")
set (SYNERGY_VERSION "${SYNERGY_VERSION_MAJOR}.${SYNERGY_VERSION_MINOR}.${SYNERGY_VERSION_PATCH}")
set (SYNERGY_VERSION_LONG "${SYNERGY_VERSION}-${SYNERGY_VERSION_TAG}")
message (STATUS "Long version number: " ${SYNERGY_VERSION_LONG})
add_definitions (-DSYNERGY_VERSION="${SYNERGY_VERSION}")
add_definitions (-DSYNERGY_VERSION_LONG="${SYNERGY_VERSION_LONG}")
add_definitions (-DSYNERGY_REVISION="${SYNERGY_REVISION}")
add_definitions (-DSYNERGY_BUILD_DATE="${SYNERGY_BUILD_DATE}")
add_definitions (-DSYNERGY_VERSION_BUILD=${SYNERGY_VERSION_BUILD})
file(WRITE ${CMAKE_BINARY_DIR}/.env.version
"SYNERGY_VERSION_MAJOR=${SYNERGY_VERSION_MAJOR}\n"
"SYNERGY_VERSION_MINOR=${SYNERGY_VERSION_MINOR}\n"
"SYNERGY_VERSION_PATCH=${SYNERGY_VERSION_PATCH}\n"
"SYNERGY_VERSION_BUILD=${SYNERGY_VERSION_BUILD}\n"
"SYNERGY_VERSION_STAGE=${SYNERGY_VERSION_STAGE}\n")

View file

@ -6,12 +6,11 @@ config:
version: 5.15.2 version: 5.15.2
mirror: https://qt.mirror.constant.com/ mirror: https://qt.mirror.constant.com/
install-dir: C:\Qt install-dir: C:\Qt
ci: choco-ci:
skip: edit-config: Chocolatey.config
edit-config: Chocolatey.config skip-packages:
packages: - cmake
- cmake - visualstudio2022buildtools
- visualstudio2022buildtools
mac: mac:
qt-prefix-command: brew --prefix qt@5 qt-prefix-command: brew --prefix qt@5
@ -62,4 +61,3 @@ config:
centos: centos:
<<: *fedora <<: *fedora
command: sudo yum install -y

View file

@ -10,7 +10,7 @@ Vendor: Symless
Packager: Symless <engineering@symless.com> Packager: Symless <engineering@symless.com>
License: GPLv2 License: GPLv2
Epoch: 1 Epoch: 1
Release: @SYNERGY_SNAPSHOT_INFO@%{?dist} Release: @SYNERGY_VERSION@%{?dist}
Requires: openssl Requires: openssl
%description %description

View file

@ -10,7 +10,7 @@ Vendor: Symless
Packager: Symless <engineering@symless.com> Packager: Symless <engineering@symless.com>
License: GPLv2 License: GPLv2
Epoch: 1 Epoch: 1
Release: @SYNERGY_SNAPSHOT_INFO@%{?dist} Release: @SYNERGY_VERSION@%{?dist}
Requires: openssl Requires: openssl
%description %description

View file

@ -10,7 +10,7 @@ Vendor: Symless
Packager: Symless <engineering@symless.com> Packager: Symless <engineering@symless.com>
License: GPLv2 License: GPLv2
Epoch: 1 Epoch: 1
Release: @SYNERGY_SNAPSHOT_INFO@%{?dist} Release: @SYNERGY_VERSION@%{?dist}
Requires: openssl Requires: openssl
%description %description

View file

@ -1,29 +1,30 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import argparse
from lib import env from lib import env, github
from lib.config import Config
# important: load venv before loading modules that install deps. qt_version_key = "QT_VERSION"
env.ensure_in_venv(__file__)
github_key = "GITHUB_ENV"
version_key = "SYNERGY_VERSION"
def main(): def main():
env_file = os.getenv(github_key) parser = argparse.ArgumentParser()
if not env_file: parser.add_argument(
raise RuntimeError(f"Env var {github_key} not set") "--set-qt-version",
action="store_true",
help=f"Set {qt_version_key} env var",
)
args = parser.parse_args()
if not os.path.exists(env_file): # important: load venv before loading modules that install deps.
raise RuntimeError(f"File not found: {env_file}") env.ensure_in_venv(__file__)
major, minor, patch, stage, _build = env.get_version_info() if args.set_qt_version:
version_value = f"{major}.{minor}.{patch}-{stage}" config = Config()
_qt_mirror, qt_version, _qt_install_dir = config.get_qt_config()
print(f"Setting env var: {version_key}={version_value}") github.set_env(qt_version_key, qt_version)
with open(env_file, "a") as env_file: else:
env_file.write(f"{version_key}={version_value}\n") raise RuntimeError("No option selected")
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -3,9 +3,6 @@
import os, sys, argparse, traceback import os, sys, argparse, traceback
from lib import env, cmd_utils from lib import env, cmd_utils
# important: load venv before loading modules that install deps.
env.ensure_in_venv(__file__)
def main(): def main():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
@ -17,6 +14,12 @@ def main():
) )
args = parser.parse_args() args = parser.parse_args()
# ensures that pip and venv are available for `ensure_module` function.
env.ensure_dependencies()
# important: load venv before loading modules that install deps.
env.ensure_in_venv(__file__)
error = False error = False
try: try:
deps = Dependencies(args.only) deps = Dependencies(args.only)
@ -84,8 +87,8 @@ class Dependencies:
choco = windows.WindowsChoco() choco = windows.WindowsChoco()
if self.ci_env: if self.ci_env:
choco.config_ci_cache() choco.config_ci_cache()
choco_config_file, remove_packages = self.config.get_choco_config() edit_config, skip_packages = self.config.get_choco_ci_config()
choco.remove_from_config(choco_config_file, remove_packages) choco.remove_from_config(edit_config, skip_packages)
command = self.config.get_deps_command() command = self.config.get_deps_command()
choco.install(command, self.ci_env) choco.install(command, self.ci_env)

View file

@ -1,107 +1,78 @@
from lib import env, cmd_utils from lib import env, cmd_utils
env.ensure_module("yaml", "pyyaml")
import yaml
config_file = "config.yml" config_file = "config.yml"
root_key = "config"
deps_key = "dependencies" deps_key = "dependencies"
class ConfigError(RuntimeError): class ConfigKeyError(RuntimeError):
pass def __init__(self, config_file, key):
self.config_file = config_file
self.key = key
def __str__(self):
return f"Not found in {self.config_file}: {self.key}"
def _get(dict, key, key_parent=None):
value = dict.get(key)
if not value:
key_path = f"{root_key}:{key_parent}:{key}" if key_parent else key
raise ConfigKeyError(f"Missing key in {config_file}: {key_path}")
return value
class Config: class Config:
"""Reads the project configuration YAML file.""" """Reads the project configuration YAML file."""
def __init__(self): def __init__(self):
env.ensure_module("yaml", "pyyaml")
import yaml
with open(config_file, "r") as f: with open(config_file, "r") as f:
data = yaml.safe_load(f) data = yaml.safe_load(f)
self.os_name = env.get_os() self.os_name = env.get_os()
root_key = "config" root = _get(data, root_key)
try: self.os = _get(root, self.os_name)
root = data[root_key]
except KeyError:
raise ConfigError(f"Nothing found in {config_file} for: {root_key}")
try:
self.os = root[self.os_name]
except KeyError:
raise ConfigError(f"Nothing found in {config_file} for: {self.os_name}")
def get_os_value(self, key): def get_os_value(self, key):
try: return _get(self.os, key, f"{self.os_name}:{key}")
return self.os[key]
except KeyError:
raise ConfigError(
f"Nothing found in {config_file} for: {self.os_name}:{key}"
)
def get_qt_config(self): def get_qt_config(self):
qt = self.get_os_deps_value("qt") qt_key = "qt"
qt = self.get_os_deps_value(qt_key)
try: parent_key = f"{self.os_name}:{deps_key}"
mirror_url = qt["mirror"] mirror_url = _get(qt, "mirror", parent_key)
except KeyError: version = _get(qt, "version", parent_key)
raise ConfigError(f"Qt mirror not set in {self.config_file}") base_dir = _get(qt, "install-dir", parent_key)
try: return mirror_url, version, base_dir
default_version = qt["version"]
except KeyError:
raise ConfigError(f"Qt version not set in {self.config_file}")
try:
default_base_dir = qt["install-dir"]
except KeyError:
raise ConfigError(f"Qt install-dir not set in {self.config_file}")
return mirror_url, default_version, default_base_dir
def get_os_deps_value(self, key): def get_os_deps_value(self, key):
deps = self.get_os_value(deps_key) deps = self.get_os_value(deps_key)
try: return _get(deps, key, f"{self.os_name}:{deps_key}")
return deps[key]
except KeyError:
raise ConfigError(
f"Nothing found in {config_file} for: {self.os_name}:{deps_key}:{key}"
)
def get_deps_command(self): def get_deps_command(self):
dependencies = self.get_os_value(deps_key) deps = self.get_os_value(deps_key)
try: command = _get(deps, "command", f"{self.os_name}:{deps_key}")
command = dependencies["command"]
except KeyError:
raise ConfigError(
f"No dependencies command found in {config_file} for: {self.os_name}"
)
return cmd_utils.strip_continuation_sequences(command) return cmd_utils.strip_continuation_sequences(command)
def get_linux_deps_command(self, distro): def get_linux_deps_command(self, distro):
distro_data = self.get_os_value(distro) distro_data = self.get_os_value(distro)
deps = _get(distro_data, deps_key, f"{self.os_name}:{distro}")
command = _get(deps, "command", f"{self.os_name}:{distro}:{deps_key}")
return cmd_utils.strip_continuation_sequences(command)
try: def get_choco_ci_config(self):
deps = distro_data[deps_key] choco_ci_key = "choco-ci"
except KeyError: choco_ci = self.get_os_deps_value(choco_ci_key)
raise ConfigError(
f"No dependencies config found in {config_file} for: {distro}"
)
try: choco_ci_path = f"{self.os_name}:{deps_key}:{choco_ci_key}"
command = deps["command"] edit_config = _get(choco_ci, "edit-config", choco_ci_path)
return cmd_utils.strip_continuation_sequences(command) skip_packages = _get(choco_ci, "skip-packages", choco_ci_path)
except KeyError:
raise ConfigError( return edit_config, skip_packages
f"No dependencies command found in {config_file} for: {self.os_name}:{distro}"
)
def get_choco_config(self):
ci = self.get_os_deps_value("ci")
try:
ci_skip = ci["skip"]
choco_config_file = ci_skip["edit-config"]
remove_packages = ci_skip["packages"]
except KeyError:
raise ConfigError(f"Bad structure in {config_file} under: ci")
return choco_config_file, remove_packages

View file

@ -2,7 +2,8 @@ import os, sys, subprocess, platform
from lib import env, cmd_utils from lib import env, cmd_utils
venv_path = "build/python" venv_path = "build/python"
version_env = "build/.env.version" version_file = "VERSION"
version_env_var = "SYNERGY_VERSION"
def check_module(module): def check_module(module):
@ -80,7 +81,7 @@ def ensure_in_venv(script):
If the script is not running in a venv, it will create one and re-run the script in the venv. If the script is not running in a venv, it will create one and re-run the script in the venv.
""" """
ensure_dependencies() assert_dependencies()
import venv import venv
if not in_venv(): if not in_venv():
@ -96,13 +97,13 @@ def ensure_in_venv(script):
sys.exit(result.returncode) sys.exit(result.returncode)
# TODO: Use pyproject.toml to specify dependencies # TODO: Use requirements.txt or pyproject.toml to specify dependencies
def ensure_module(module, package): def ensure_module(module, package):
""" """
Ensures that a Python module is available, and installs the package if it is not. Ensures that a Python module is available, and installs the package if it is not.
""" """
ensure_dependencies() assert_dependencies()
try: try:
__import__(module) __import__(module)
@ -111,16 +112,30 @@ def ensure_module(module, package):
cmd_utils.run([sys.executable, "-m", "pip", "install", package], shell=False) cmd_utils.run([sys.executable, "-m", "pip", "install", package], shell=False)
def ensure_dependencies(): def assert_dependencies(raise_error=True):
""" """
Ensures that pip and venv are available, and installs them if they are not. Returns True if pip and venv are available.
This is normally only required on Linux.
""" """
has_pip = check_module("pip") has_pip = check_module("pip")
has_venv = check_module("venv") has_venv = check_module("venv")
if has_pip and has_venv: if raise_error:
if not has_pip:
raise RuntimeError("Python is missing pip")
if not has_venv:
raise RuntimeError("Python is missing venv")
else:
return has_pip and has_venv
def ensure_dependencies():
"""
Ensures that pip and venv are available, and installs them if they are not.
This is normally only installs on Linux, as Windows and Mac usually come with pip and venv.
"""
if assert_dependencies(raise_error=False):
return return
print("Installing Python dependencies...") print("Installing Python dependencies...")
@ -145,19 +160,12 @@ def ensure_dependencies():
raise RuntimeError(f"Unable to install Python dependencies on {distro}") raise RuntimeError(f"Unable to install Python dependencies on {distro}")
def get_version_info(): def get_app_version():
env.ensure_module("dotenv", "python-dotenv") """
from dotenv import load_dotenv # type: ignore Returns the version either from the env var, or from the version file.
"""
if version_env_var in os.environ:
return os.environ[version_env_var]
if not os.path.isfile(version_env): with open(version_file, "r") as f:
raise RuntimeError(f"Version file not found: {version_env}") return f.read().strip()
load_dotenv(dotenv_path=version_env)
major = os.getenv("SYNERGY_VERSION_MAJOR")
minor = os.getenv("SYNERGY_VERSION_MINOR")
patch = os.getenv("SYNERGY_VERSION_PATCH")
stage = os.getenv("SYNERGY_VERSION_STAGE")
build = os.getenv("SYNERGY_VERSION_BUILD")
return major, minor, patch, stage, build

19
scripts/lib/github.py Normal file
View file

@ -0,0 +1,19 @@
import os
github_key = "GITHUB_ENV"
def set_env(key, value):
"""
Appends the key=value pair to the GitHub environment file.
"""
env_file = os.getenv(github_key)
if not env_file:
raise RuntimeError(f"Env var {github_key} not set")
if not os.path.exists(env_file):
raise RuntimeError(f"File not found: {env_file}")
print(f"Setting GitHub env var: {key}={value}")
with open(env_file, "a") as env_file:
env_file.write(f"{key}={value}\n")

View file

@ -5,6 +5,8 @@ import xml.etree.ElementTree as ET
from lib import cmd_utils from lib import cmd_utils
cmake_env_var = "CMAKE_PREFIX_PATH" cmake_env_var = "CMAKE_PREFIX_PATH"
runner_temp_env_var = "RUNNER_TEMP"
qt_base_dir_env_var = "QT_BASE_DIR"
def relaunch_as_admin(script): def relaunch_as_admin(script):
@ -55,15 +57,14 @@ class WindowsChoco:
def config_ci_cache(self): def config_ci_cache(self):
"""Configures Chocolatey cache for CI.""" """Configures Chocolatey cache for CI."""
runner_temp_key = "RUNNER_TEMP" runner_temp = os.environ.get(runner_temp_env_var)
runner_temp = os.environ.get(runner_temp_key)
if runner_temp: if runner_temp:
# sets the choco cache dir, which should match the dir in the ci cache action. # sets the choco cache dir, which should match the dir in the ci cache action.
key_arg = '--name="cacheLocation"' key_arg = '--name="cacheLocation"'
value_arg = f'--value="{runner_temp}/choco"' value_arg = f'--value="{runner_temp}/choco"'
cmd_utils.run(["choco", "config", "set", key_arg, value_arg]) cmd_utils.run(["choco", "config", "set", key_arg, value_arg])
else: else:
print(f"Warning: CI environment variable {runner_temp_key} not set") print(f"Warning: CI environment variable {runner_temp_env_var} not set")
def remove_from_config(self, choco_config_file, remove_packages): def remove_from_config(self, choco_config_file, remove_packages):
"""Removes a package from the Chocolatey configuration.""" """Removes a package from the Chocolatey configuration."""
@ -82,18 +83,15 @@ class WindowsChoco:
class WindowsQt: class WindowsQt:
"""Qt for Windows.""" """Qt for Windows."""
def __init__(self, mirror_url, default_version, default_base_dir): def __init__(self, mirror_url, version, base_dir):
self.mirror_url = mirror_url self.mirror_url = mirror_url
self.version = version
self.version = os.environ.get("QT_VERSION") # allows ci to override the qt base dir path
if not self.version: self.base_dir = os.environ.get(qt_base_dir_env_var)
print(f"QT_VERSION not set, using: {default_version}")
self.version = default_version
self.base_dir = os.environ.get("QT_BASE_DIR")
if not self.base_dir: if not self.base_dir:
print(f"QT_BASE_DIR not set, using: {default_base_dir}") print(f"QT_BASE_DIR not set, using: {base_dir}")
self.base_dir = default_base_dir self.base_dir = base_dir
self.install_dir = f"{self.base_dir}\\{self.version}" self.install_dir = f"{self.base_dir}\\{self.version}"

View file

@ -3,21 +3,20 @@
import platform import platform
from lib import env from lib import env
# important: load venv before loading modules that install deps.
env.ensure_in_venv(__file__)
env_file = ".env" env_file = ".env"
package_filename_product = "synergy" package_filename_product = "synergy"
def main(): def main():
# important: load venv before loading modules that install deps.
env.ensure_in_venv(__file__)
env.ensure_module("dotenv", "python-dotenv") env.ensure_module("dotenv", "python-dotenv")
from dotenv import load_dotenv # type: ignore from dotenv import load_dotenv # type: ignore
load_dotenv(dotenv_path=env_file) load_dotenv(dotenv_path=env_file)
major, minor, patch, stage, _build = env.get_version_info() version = env.get_app_version()
version = f"{major}.{minor}.{patch}-{stage}"
filename_base = get_filename_base(version) filename_base = get_filename_base(version)
print(f"Package filename base: {filename_base}") print(f"Package filename base: {filename_base}")

View file

@ -27,10 +27,6 @@ AboutDialog::AboutDialog(MainWindow* parent, const AppConfig& config) :
m_versionChecker.setApp(parent->appPath(config.synergycName())); m_versionChecker.setApp(parent->appPath(config.synergycName()));
QString version = m_versionChecker.getVersion(); QString version = m_versionChecker.getVersion();
#ifdef SYNERGY_REVISION
version += '-';
version += SYNERGY_REVISION;
#endif
m_pLabelSynergyVersion->setText(version); m_pLabelSynergyVersion->setText(version);
QString buildDateString = QString::fromLocal8Bit(__DATE__).simplified(); QString buildDateString = QString::fromLocal8Bit(__DATE__).simplified();

View file

@ -25,5 +25,5 @@ const char* kCopyright = "Copyright (C) 2012-%s Symless Ltd.\n"
"Copyright (C) 2002-2014 Chris Schoeneman"; "Copyright (C) 2002-2014 Chris Schoeneman";
const char* kContact = "Email: engineering@symless.com"; const char* kContact = "Email: engineering@symless.com";
const char* kWebsite = "https://symless.com/"; const char* kWebsite = "https://symless.com/";
const char* kVersion = SYNERGY_VERSION_LONG; const char* kVersion = SYNERGY_VERSION;
const char* kAppVersion = "Synergy " SYNERGY_VERSION; const char* kAppVersion = "Synergy " SYNERGY_VERSION;

View file

@ -60,12 +60,6 @@ include_directories(
../../../ext/googletest/googlemock/include ../../../ext/googletest/googlemock/include
) )
if (UNIX)
include_directories(
../../..
)
endif()
add_executable(integtests ${sources}) add_executable(integtests ${sources})
target_link_libraries(integtests target_link_libraries(integtests
arch base client common io ipc mt net platform server synlib gtest gmock ${libs}) arch base client common io ipc mt net platform server synlib gtest gmock ${libs})

View file

@ -56,12 +56,6 @@ include_directories(
../../../ext ../../../ext
) )
if (UNIX)
include_directories(
../../..
)
endif()
if (SYNERGY_ADD_HEADERS) if (SYNERGY_ADD_HEADERS)
list(APPEND sources ${headers}) list(APPEND sources ${headers})
endif() endif()