From 45fb8df97d296d1fc07915a38f5837a4fd21d361 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Fri, 25 Apr 2025 13:13:48 +0700 Subject: [PATCH 01/57] docs(web): add a Web engine keystroke lifecycle internal doc Fixes: #12732 --- web/docs/internal/keystroke-lifecycle.md | 90 +++++++++++++++++++++++ web/docs/internal/keystroke-processing.md | 2 +- 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 web/docs/internal/keystroke-lifecycle.md diff --git a/web/docs/internal/keystroke-lifecycle.md b/web/docs/internal/keystroke-lifecycle.md new file mode 100644 index 0000000000..18582459a8 --- /dev/null +++ b/web/docs/internal/keystroke-lifecycle.md @@ -0,0 +1,90 @@ +# The Keyman Engine for Web keystroke lifecycle + +Depending on the variant of Keyman Engine for Web in play, the engine integrates either with a host app or with the current browser page to interpret and/or intercept keystroke events and produce the desired context manipulations corresponding to them. While some details diverge between `app/browser` and `app/webview` builds, the general structure and pattern for this process holds. + +This document will break down the full keystroke lifecycle into four distinct phases, as follows: + +1. Keystroke pre-processing: event interception + interpretation (pre-processing) +2. Keystroke processing: keystroke main-group rule evaluation +3. Keystroke post-processing: keystroke post-keystroke evaluation + side-effects +4. Keystroke resolution: UI state updating + +## Keystroke pre-processing + +Both the `app/browser` and `app/webview` products are capable of handling simulated keystrokes from the on-screen keyboard as well as hardware keystrokes. For hardware keystrokes, this varies between the two, while the majority of on-screen keyboard keystrokes are handled identically. + +### `app/browser` + +The `app/browser` version of the engine is designed to integrate with the active page of the user's browser, giving it far more direct access to the user's true context in addition to direct access to handling DOM events resulting from hardware keystrokes. Its `HardwareEventKeyboard` class is the primary module for establishing the needed engine event hooks and for interpreting the corresponding DOM events as they arise. + +The bulk of DOM key events trigger keystroke processing on key-down, though modifier keys also receive key-up handling. Key-press events are handled selectively for held backspaces and possibly certain keystrokes for mnemonic keyboards. In all cases, DOM keyboard event objects are preprocessed by the centralized `preprocessKeyboardEvent` method, which converts the DOM event format into Web's `KeyEvent` format, which is the form required by the keyboard rules within compiled JS keyboards. This includes mnemonic keystroke preprocessing and remapping. + +### `app/webview` + +The `app/webview` version of the engine, which is designed to be used while embedded in a platform-specific host app, does not have direct access to standard hardware keystroke events. It's run in a WebView that does not take input - a WebView owned by the host app. It is the responsibility of the host app to handle hardware keystroke events and preprocess them on behalf of the Web engine, then forward them to the Web engine via a carefully-constructed JS call from the host upon the WebView. The `PassthroughKeyboard` class within `app/webview` space provides the method `raiseKeyEvent` as an internal API for this purpose, which converts the mobile-app format for hardware keystroke into the internal `KeyEvent` format. This includes mnemonic keystroke processing and remapping. + +### On-screen keyboard + +For both `app/browser` and `app/webview`, the on-screen keyboard delegates mouse and touch processing to [our internal gesture engine](./gestures/index.md) for most keyboards. (Keyboards that instead display "help pages", such as `sil_euro_latin` on desktop, have specialized handling.) The gesture engine is responsible for interpreting all DOM mouse and touch events for OSKs based on the touch-layout format, which are managed by the `VisualKeyboard` class. The gesture engine will raise events about the gesture lifecycle that, when appropriate, will emit `KeyElement` instances - elements of the constructed OSK corresponding to elements of the OSK directly representing keyboard keys. + +OSK keystroke preprocessing operates a little differently from hardware keystrokes. The `ActiveLayout` object for the current form-factor of the `Keyboard` maintains a "base" `KeyEvent` object, per key, that is lazy-constructed (by the `.baseKeyEvent` property) when first needed - the meat of which is performed by the `ActiveKeyBase.constructBaseKeyEvent` method. This is only evaluated up to once per key per activation of the keyboard. As keystrokes are received during OSK use, `VisualKeyboard.keyEventFromSpec` calls the `Keyboard.constructKeyEvent` method to clone that base `KeyEvent` object for the incoming keystroke and then adjust it to match current modifier and state-key settings. + +### Final steps + +Regardless of the path taken to generate the `KeyEvent` object, _all_ keystroke handling modules of Keyman Engine for Web then raise that `KeyEvent` object via their `keyevent` event as specified by the `KeyEventSourceInterface` type. This event also permits a callback that is used by the final phase of the lifecycle - keystroke resolution - as needed. The main `KeymanEngine` base class listens for these events and forwards them for next phase of the lifecycle - keystroke processing - to the `InputProcessor` module, which passes control to whichever `KeystrokeProcessor` type is active for the keyboard when appropriate. + +## Keystroke processing + +Once the `KeyEvent` object for a keystroke has been passed into the `InputProcessor` module and its `processKeyEvent` method, the keystroke-processing stage has been reached. There are a number of subprocesses that trigger here in sequence - keystrokes don't go _straight_ to evaluation against keyboard rules. + +### Pre-keystroke state management + +First, the engine checks the keyboard associated with the `KeyEvent`, ensuring that it is still in place. (See #7543 for more details.) With that assertion in place, it then performs a check needed to support multitaps - it checks to see if the key event has an associated "base context" and reverts the current context to match it if so. Once those checks are fulfilled, the engine then checks to see if the key event corresponds to a pure layer-switching or modifier/state-key interaction. If those are detected, rule-evaluation is bypassed. + +On a similar note, backspace and spacebar keystrokes receive special handling next in associated with predictive-text functionality. When autocorrect is enabled, the spacebar in particular can be used to accept the current suggestion instead of acting as whitespace; if this is triggered, its `KeyEvent` will be swallowed - no rule processing will occur for the it. The backspace may trigger display of a "reversion" suggestion when applicable but will not be swallowed. + +Once this phase is reached, the engine will then snapshot the current state of the context, then trigger standard rule processing against the original context by calling the current `KeyboardProcessor`'s `processKeystroke` method. Any operations against the context will be persisted and take full effect; DOM input elements (for `app/browser`) are updated during rule evaluation. + +### Determining direct keystroke effects + +The `KeyboardProcessor` classes are responsible for determining the effects that should arise when evaluating the incoming keystroke with the current context state. While the exact mechanisms of this may vary depending upon the type of keyboard, the role is the same - interpreting the keystroke in context. + +### JS keyboards + +Before proceeding further, `KeyboardProcessor` does a context check to see whether or not the context contains anything considered deletable - in the case of a BKSP, we need to ensure that the keystroke passes through to the engine's host cleanly, as it may have special implications for the site or host app. + +With that out of the way, the JS keyboard's main group is then provided with the `KeyEvent` object in order to evaluate the keyboard's rules against the keystroke. This involves constructing a `RuleBehavior` object to track any and all needed side-effects for the keystroke. Such changes are generally not applied to the engine at large at this time in order to prevent unwanted side effects that may arise to and from predictive text operations that follow shortly afterward. + +The `KeyboardInterface` class defines the internal API used by keyboards for their evaluation of keyboard rules. + +Once the keyboard's script returns control to the main engine, the engine then determines the net effects to the context that resulted from applying the keyboard rule and preserves that as a `Transcription`, part of includes a `Transform` that most directly represents the changes to text surrounding the text insertion point. + +For JS keyboards, if no keyboard rule is defined for a non-frame key on the `default` or `shift` layer, there is an additional set of implied "default" keyboard rules that is applied. (A keyboard's source must _explicitly_ specify to not emit anything for such keys if such an outcome is desired.) This occurs regardless of the keystroke's source, as such effects are necessary to incorporate for predictive-text operations. If no such rule exists, the processor will add a note to the `RuleBehavior` object that default processing could not be provided and is thus needed from the engine's host. + +### KMX keyboards & KMX+ (LDML) keyboards + +For KMX and KMX+ keyboards, keystrokes are evaluated by using the embedded WASM version of Keyman Core. + +TODO: add link to specific mechanisms here once available. + +### "Alternate" processing (predictive-text) + +Once the incoming `KeyEvent` has been processed, if predictive-text is active and the `KeyEvent` includes fat-finger oriented data, the engine will then build a set of "alternates" - of "phantom" keystrokes - and process _them_ against headless clones of the original context in the same manner as the original keystroke. + +Once all relevant "alternates" have been evaluated, the engine will then signal the predictive-text engine with all relevant data, including the original, snapshotted state of the context. It does not actually trigger predictive-text at this time; processing of alternates is done before keystroke post-processing in order to avoid cross-effects from JS-keyboard variable store manipulations and similar mechanisms. Fat-finger "alternate" `KeyEvent`s are evaluated as if they occurred under the exact same conditions as the keystroke that was actually detected. + +### Keystroke post-processing + +At this stage, the side-effects desired for the original keystroke, as saved to its `RuleBehavior`, are then applied. Note that this includes changes to the `&layer` store - this update will also trigger an event that updates the state of the OSK to match the desired layer. + +Once that is done, the engine will then save data relevant to the original context state, the `KeyEvent`, and the `RuleBehavior` to the "context cache" supporting multitap context reversion. These effects include layer-change effects that result from JS keyboard rules, which modify the KMN-style keyboard stores `&oldlayer` and `&newlayer` in preparation for `begin PostKeystroke` group processing, which is then executed (and which can trigger another `&layer` & OSK-layer update). + +Once post-keystroke effects have been determined, the engine then signals predictive-text to generate new predictions associated with the keystroke. For `app/browser` variants of the engine, changes to the context will then also trigger the DOM `input` event on the context's element in case third parties wish to leverage such events for their website's pages. + +### Keystroke resolution + +At this stage, `InputProcessor` passes control back to the main `KeymanEngine` module, which then triggers the "on rule finalization" setting if configured. This setting is mostly used for page-integration within `app/browser`, supporting DOM element `change` event emulation whenever focus shifts away from the active context element. + +For OSK keystrokes, an identifier associated with the `KeyEvent`'s context snapshot will be made accessible through the `keyevent` event's callback parameter - a feature utilized by multitap gesture support. + +For hardware-keyboard keystrokes, the `keyevent` callback is used to determine whether or not native handling for the keystroke should be triggered - such as for TAB and ENTER keys, which may have semantic command-like functionality depending on the state of the Web engine's host - be that a web page or an Android/iOS app utilizing the keyboard. ENTER keys are often used to submit forms, and this helps ensure we trigger such functionality when appropriate. \ No newline at end of file diff --git a/web/docs/internal/keystroke-processing.md b/web/docs/internal/keystroke-processing.md index 4406b1dcab..8606d18cba 100644 --- a/web/docs/internal/keystroke-processing.md +++ b/web/docs/internal/keystroke-processing.md @@ -1,6 +1,6 @@ # Keystroke Processing -In addition to handling keystroke events produced from hardware keyboards, Keyman Engine for Web manages an on-screen keyboard that can also be used to generate such events. This document will enumerate the various components of data management and control flow used to handle and process keystrokes. +In addition to handling keystroke events produced from hardware keyboards, Keyman Engine for Web manages an on-screen keyboard that can also be used to generate such events. This document will enumerate the various components of data management and control flow used to handle and process keystrokes. For a more thorough examination of the keystroke lifecycle, see the [keystroke-lifecycle](./keystroke-lifecycle.md) page. ## Input: KeyEvent - the pre-processed keystroke From dcc9638198d2e6707e9ab5f123c27f9344dcebf9 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Fri, 25 Apr 2025 13:16:31 +0700 Subject: [PATCH 02/57] docs(web): minor nit regarding AltGr emulation --- web/docs/internal/keystroke-lifecycle.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/docs/internal/keystroke-lifecycle.md b/web/docs/internal/keystroke-lifecycle.md index 18582459a8..ff3dca47df 100644 --- a/web/docs/internal/keystroke-lifecycle.md +++ b/web/docs/internal/keystroke-lifecycle.md @@ -17,7 +17,7 @@ Both the `app/browser` and `app/webview` products are capable of handling simula The `app/browser` version of the engine is designed to integrate with the active page of the user's browser, giving it far more direct access to the user's true context in addition to direct access to handling DOM events resulting from hardware keystrokes. Its `HardwareEventKeyboard` class is the primary module for establishing the needed engine event hooks and for interpreting the corresponding DOM events as they arise. -The bulk of DOM key events trigger keystroke processing on key-down, though modifier keys also receive key-up handling. Key-press events are handled selectively for held backspaces and possibly certain keystrokes for mnemonic keyboards. In all cases, DOM keyboard event objects are preprocessed by the centralized `preprocessKeyboardEvent` method, which converts the DOM event format into Web's `KeyEvent` format, which is the form required by the keyboard rules within compiled JS keyboards. This includes mnemonic keystroke preprocessing and remapping. +The bulk of DOM key events trigger keystroke processing on key-down, though modifier keys also receive key-up handling. Key-press events are handled selectively for held backspaces and possibly certain keystrokes for mnemonic keyboards. In all cases, DOM keyboard event objects are preprocessed by the centralized `preprocessKeyboardEvent` method, which converts the DOM event format into Web's `KeyEvent` format, which is the form required by the keyboard rules within compiled JS keyboards. This includes mnemonic keystroke preprocessing and remapping in addition to AltGr emulation. ### `app/webview` From a701b97888dedab84b7981dd894c00d16bd19d0f Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Mon, 28 Apr 2025 13:05:02 +0700 Subject: [PATCH 03/57] fix(web): add robustness for bad touch-layout fontsize specs Fixes: #13766 Fixes: KEYMAN-WEB-QX It seems that at some point, Developer has been compiling raw "12" values in the touch-layout JSON as a numeric 12 for the fontsize field. This clearly happened for the inuktitut_pirurvik keyboard; we should also inspect urdu_phonetic, which has the same raw "12". This change ensures that Web can handle this case without spewing tons of warning/error messages. It also adds error-logging to help with diagnosis for any related issue in the future. --- web/src/engine/osk/src/lengthStyle.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/web/src/engine/osk/src/lengthStyle.ts b/web/src/engine/osk/src/lengthStyle.ts index b5fa17bb41..b0161d63bb 100644 --- a/web/src/engine/osk/src/lengthStyle.ts +++ b/web/src/engine/osk/src/lengthStyle.ts @@ -12,6 +12,24 @@ export class ParsedLengthStyle implements LengthStyle { public constructor(style: LengthStyle | string) { let parsed: LengthStyle = (typeof style == 'string') ? ParsedLengthStyle.parseLengthStyle(style) : style; + const fallback: LengthStyle = { + val: 1, + absolute: false + }; + + if(typeof style == 'number') { + // Addresses #13766 for compiled layouts with numbers in the touch-layout `fontsize` field + + // Do not actually emit console warning; we handle those as "errors" in the mobile apps, and + // this is more an issue with the compiled keyboard. + parsed = fallback; + } + + if(isNaN(parsed.val)) { + console.error("NaN appeared while trying to calculate style scaling effects"); + parsed = fallback + } + // While Object.assign would be nice (and previously, was used), it will break // on old but still supported versions of Android if their Chrome isn't updated. // Requires mobile Chrome 45+, but API 21 (5.0) launches with an older browser. @@ -38,6 +56,11 @@ export class ParsedLengthStyle implements LengthStyle { } public scaledBy(scalar: number): ParsedLengthStyle { + if(isNaN(scalar)) { + console.error("NaN appeared while trying to calculate style scaling effects"); + return this; + } + return new ParsedLengthStyle({ val: scalar * this.val, absolute: this.absolute From e601d59b598529d45d8a3bbd21279dfc7e2142c5 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Tue, 29 Apr 2025 10:46:33 +0700 Subject: [PATCH 04/57] change(web): replace USVString with string in predictive-text engine Fixes: #12046 It was only ever an alias (for `string`!) for its intended use, with actual `USVString` typing being unavailable in the browser. --- common/web/types/src/lexical-model-types.ts | 26 ++++--------- .../types/tests/lexical-model-types.tests.ts | 2 +- .../templates/src/tokenization.ts | 2 +- .../templates/src/trie-model.ts | 9 ++--- .../engine/predictive-text/types/message.d.ts | 3 +- .../worker-main/src/lmlayer.ts | 5 +-- .../src/main/correction/context-tracker.ts | 39 +++++++++---------- .../src/main/correction/distance-modeler.ts | 11 +++--- .../src/main/model-compositor.ts | 3 +- 9 files changed, 41 insertions(+), 59 deletions(-) diff --git a/common/web/types/src/lexical-model-types.ts b/common/web/types/src/lexical-model-types.ts index 7c5cfdf643..e2670d2e21 100644 --- a/common/web/types/src/lexical-model-types.ts +++ b/common/web/types/src/lexical-model-types.ts @@ -5,18 +5,6 @@ /****************************** Lexical Models ******************************/ -/** - * A JavaScript string with the restriction that it must only - * contain Unicode scalar values. - * - * This means that any lone high surrogate must be paired with - * a low surrogate, if it exists. Lone surrogate code units are - * forbidden. - * - * See also: https://developer.mozilla.org/en-US/docs/Web/API/USVString - */ -export type USVString = string; - export type CasingForm = 'lower' | 'initial' | 'upper'; /** @@ -67,7 +55,7 @@ export interface LexiconTraversal { * - If `char` = 'e', the child represents a prefix of 'the'. * - Then `traversal` allows traversing the part of the lexicon prefixed by 'the'. */ - children(): Generator<{char: USVString, traversal: () => LexiconTraversal}>; + children(): Generator<{char: string, traversal: () => LexiconTraversal}>; /** * Allows direct access to the traversal state that results when appending one @@ -81,7 +69,7 @@ export interface LexiconTraversal { * That is, if a model "keys" `è` to `e`, there will be no `è` child. * @param char */ - child(char: USVString): LexiconTraversal | undefined; + child(char: string): LexiconTraversal | undefined; /** * Any entries directly keyed by the currently-represented lookup prefix. Entries and @@ -178,7 +166,7 @@ export interface LexicalModel { * @param text The original input text. * @returns The 'keyed' form of that text. */ - toKey?(text: USVString): USVString; + toKey?(text: string): string; /** * Generates predictive suggestions corresponding to the state of context after the proposed @@ -248,7 +236,7 @@ export interface LexicalModel { * @param context * @deprecated */ - wordbreak?(context: Context): USVString; + wordbreak?(context: Context): string; /** * Lexical models _may_ provide a LexiconTraversal object usable to enhance @@ -279,7 +267,7 @@ export interface Transform { * * Corresponds to `s` in com.keyman.KeyboardInterface.output. */ - insert: USVString; + insert: string; /** * The number of code units to delete to the left of the cursor. @@ -380,7 +368,7 @@ export interface Context { * buffer. If there is nothing to the left of the buffer, this is * an empty string. */ - readonly left: USVString; + readonly left: string; /** * Up to maxRightContextCodeUnits code units of Unicode scalar value @@ -390,7 +378,7 @@ export interface Context { * * This property may be missing entirely. */ - readonly right?: USVString; + readonly right?: string; /** * Whether the insertion point is at the start of the buffer. diff --git a/common/web/types/tests/lexical-model-types.tests.ts b/common/web/types/tests/lexical-model-types.tests.ts index ef8bed28a5..3075582a39 100644 --- a/common/web/types/tests/lexical-model-types.tests.ts +++ b/common/web/types/tests/lexical-model-types.tests.ts @@ -7,7 +7,7 @@ import { KMXPlus, LdmlKeyboardTypes, LexicalModelTypes } from "@keymanapp/common-types"; -export let u: LexicalModelTypes.USVString; +export let u: string; export let l: LexicalModelTypes.Transform; export let s: LexicalModelTypes.Suggestion; export let st: LexicalModelTypes.SuggestionTag; diff --git a/web/src/engine/predictive-text/templates/src/tokenization.ts b/web/src/engine/predictive-text/templates/src/tokenization.ts index a9bd03c5d3..fd8ed28d5c 100644 --- a/web/src/engine/predictive-text/templates/src/tokenization.ts +++ b/web/src/engine/predictive-text/templates/src/tokenization.ts @@ -214,6 +214,6 @@ export function getLastPreCaretToken(wordBreaker: LexicalModelTypes.WordBreaking // While it is currently identical to getLastWord, this may change in the future. // It's best not to write ourselves into a corner on this one, as disambiguating later // would likely be pretty painful. -export function wordbreak(wordBreaker: LexicalModelTypes.WordBreakingFunction, context: LexicalModelTypes.Context): LexicalModelTypes.USVString { +export function wordbreak(wordBreaker: LexicalModelTypes.WordBreakingFunction, context: LexicalModelTypes.Context): string { return getLastPreCaretToken(wordBreaker, context); } diff --git a/web/src/engine/predictive-text/templates/src/trie-model.ts b/web/src/engine/predictive-text/templates/src/trie-model.ts index 2c5e6a194e..f83b304cb3 100644 --- a/web/src/engine/predictive-text/templates/src/trie-model.ts +++ b/web/src/engine/predictive-text/templates/src/trie-model.ts @@ -43,7 +43,6 @@ import LexiconTraversal = LexicalModelTypes.LexiconTraversal; import Suggestion = LexicalModelTypes.Suggestion; import TextWithProbability = LexicalModelTypes.TextWithProbability; import Transform = LexicalModelTypes.Transform; -import USVString = LexicalModelTypes.USVString; import WithOutcome = LexicalModelTypes.WithOutcome; import WordBreakingFunction = LexicalModelTypes.WordBreakingFunction; @@ -112,7 +111,7 @@ class Traversal implements LexiconTraversal { this.totalWeight = totalWeight; } - child(char: USVString): LexiconTraversal | undefined { + child(char: string): LexiconTraversal | undefined { // May result for blank tokens resulting immediately after whitespace. if(char == '') { return this; @@ -131,7 +130,7 @@ class Traversal implements LexiconTraversal { } // Handles one code unit at a time. - private _child(char: USVString): Traversal | undefined { + private _child(char: string): Traversal | undefined { const root = this.root; const totalWeight = this.totalWeight; const nextPrefix = this.prefix + char; @@ -157,7 +156,7 @@ class Traversal implements LexiconTraversal { } } - *children(): Generator<{char: USVString, traversal: () => LexiconTraversal}> { + *children(): Generator<{char: string, traversal: () => LexiconTraversal}> { let root = this.root; // We refer to the field multiple times in this method, and it doesn't change. @@ -302,7 +301,7 @@ export default class TrieModel implements LexicalModel { }; } - toKey(text: USVString): USVString { + toKey(text: string): string { return this._trie.toKey(text); } diff --git a/web/src/engine/predictive-text/types/message.d.ts b/web/src/engine/predictive-text/types/message.d.ts index a0ca7c9cb7..39ff92d6ae 100644 --- a/web/src/engine/predictive-text/types/message.d.ts +++ b/web/src/engine/predictive-text/types/message.d.ts @@ -24,7 +24,6 @@ import { LexicalModelTypes } from '@keymanapp/common-types'; import Configuration = LexicalModelTypes.Configuration; import Reversion = LexicalModelTypes.Reversion; import Suggestion = LexicalModelTypes.Suggestion; -import USVString = LexicalModelTypes.USVString; /** * Tokens are signed 31-bit integers! @@ -87,7 +86,7 @@ interface CurrentWordMessage { * Contains the 'current word' left of the caret given the Context * of its source message - the 'wordbreak' message with matching Token value. */ - word: USVString; + word: string; } /** diff --git a/web/src/engine/predictive-text/worker-main/src/lmlayer.ts b/web/src/engine/predictive-text/worker-main/src/lmlayer.ts index 2f59917d0e..5727dabd94 100644 --- a/web/src/engine/predictive-text/worker-main/src/lmlayer.ts +++ b/web/src/engine/predictive-text/worker-main/src/lmlayer.ts @@ -28,7 +28,6 @@ import Distribution = LexicalModelTypes.Distribution; import Reversion = LexicalModelTypes.Reversion; import Suggestion = LexicalModelTypes.Suggestion; import Transform = LexicalModelTypes.Transform; -import USVString = LexicalModelTypes.USVString; import PromiseStore from "./promise-store.js"; import { OutgoingMessage } from '@keymanapp/lm-message-types'; @@ -62,7 +61,7 @@ export default class LMLayer { /** Call this when the LMLayer has sent us the 'ready' message! */ private _declareLMLayerReady: (conf: Configuration) => void; private _predictPromises: PromiseStore; - private _wordbreakPromises: PromiseStore; + private _wordbreakPromises: PromiseStore; private _acceptPromises: PromiseStore; private _revertPromises: PromiseStore; private _nextToken: number; @@ -152,7 +151,7 @@ export default class LMLayer { }); } - wordbreak(context: Context): Promise { + wordbreak(context: Context): Promise { let token = this._nextToken++; return new Promise((resolve, reject) => { this._wordbreakPromises.make(token, resolve, reject); diff --git a/web/src/engine/predictive-text/worker-thread/src/main/correction/context-tracker.ts b/web/src/engine/predictive-text/worker-thread/src/main/correction/context-tracker.ts index 9bbc7f19c2..4c589ec358 100644 --- a/web/src/engine/predictive-text/worker-thread/src/main/correction/context-tracker.ts +++ b/web/src/engine/predictive-text/worker-thread/src/main/correction/context-tracker.ts @@ -11,7 +11,6 @@ import Distribution = LexicalModelTypes.Distribution; import LexicalModel = LexicalModelTypes.LexicalModel; import Suggestion = LexicalModelTypes.Suggestion; import Transform = LexicalModelTypes.Transform; -import USVString = LexicalModelTypes.USVString; function textToCharTransforms(text: string, transformId?: number) { let perCharTransforms: Transform[] = []; @@ -40,7 +39,7 @@ export function getEditPathLastMatch(editPath: EditOperation[]) { return editPath.lastIndexOf('match', editLength - 2); } else { return editPath.lastIndexOf('match'); - } + } } export class TrackedContextSuggestion { @@ -62,7 +61,7 @@ export class TrackedContextToken { constructor(instance?: TrackedContextToken) { if(instance) { Object.assign(this, instance); - // We don't alter the values in replacements, but we do wish to prevent aliasing + // We don't alter the values in replacements, but we do wish to prevent aliasing // of the array containing them. this.replacements = instance.replacements.slice(); } @@ -94,7 +93,7 @@ export class TrackedContextToken { * @param tokenText * @param transformId */ - updateWithBackspace(tokenText: USVString, transformId: number) { + updateWithBackspace(tokenText: string, transformId: number) { // It's a backspace transform; time for special handling! // // For now, with 14.0, we simply compress all remaining Transforms for the token into @@ -109,11 +108,11 @@ export class TrackedContextToken { }); this.raw = tokenText; - this.transformDistributions = backspacedTokenContext; + this.transformDistributions = backspacedTokenContext; this.clearReplacements(); } - update(transformDistribution: Distribution, tokenText?: USVString) { + update(transformDistribution: Distribution, tokenText?: string) { // Preserve existing text if new text isn't specified. tokenText = tokenText || (tokenText === '' ? '' : this.raw); @@ -210,7 +209,7 @@ export class TrackedContextState { } toRawTokenization() { - let sequence: USVString[] = []; + let sequence: string[] = []; for(let token of this.tokens) { // Hide any tokens representing wordbreaks. (Thinking ahead to phrase-level possibilities) @@ -329,14 +328,14 @@ interface ContextMatchResult { /** * Indicates the portion of the incoming keystroke data, if any, that applies to * tokens before the last pre-caret token and thus should not be replaced by predictions - * based upon `state`. If the provided context state + the incoming transform do not + * based upon `state`. If the provided context state + the incoming transform do not * adequately match the current context, the match attempt will fail with a `null` result. * * Should generally be non-null if the token before the caret did not previously exist. - * - * The result may be null if it does not match the prior context state or if bookkeeping - * based upon it is problematic - say, if wordbreaking effects shift due to new input, - * causing a mismatch with the prior state's tokenization. + * + * The result may be null if it does not match the prior context state or if bookkeeping + * based upon it is problematic - say, if wordbreaking effects shift due to new input, + * causing a mismatch with the prior state's tokenization. * (Refer to #12494 for an example case.) */ preservationTransform?: Transform; @@ -352,7 +351,7 @@ export class ContextTracker extends CircularArray { transformSequenceDistribution?: Distribution ): ContextMatchResult { // Map the previous tokenized state to an edit-distance friendly version. - let matchContext: USVString[] = matchState.toRawTokenization(); + let matchContext: string[] = matchState.toRawTokenization(); // Inverted order, since 'match' existed before our new context. let mapping = ClassicalDistanceCalculation.computeDistance( @@ -591,7 +590,7 @@ export class ContextTracker extends CircularArray { // multitaps makes it tricky to reliably use in all situations. // It's best to handle `delete` cases directly for this reason. for(let j = i + 1; j < editPath.length; j++) { - // If something _other_ than delete follows a 'delete' on the edit path, + // If something _other_ than delete follows a 'delete' on the edit path, // we probably have a context mismatch. // // It's possible to construct cases where this isn't true, but it's likely not @@ -620,12 +619,12 @@ export class ContextTracker extends CircularArray { priorEdit = editPath[i]; } - return { - state, - baseState: matchState, - preservationTransform, - headTokensRemoved: poppedTokenCount, - tailTokensAdded: pushedTokenCount + return { + state, + baseState: matchState, + preservationTransform, + headTokensRemoved: poppedTokenCount, + tailTokensAdded: pushedTokenCount }; } diff --git a/web/src/engine/predictive-text/worker-thread/src/main/correction/distance-modeler.ts b/web/src/engine/predictive-text/worker-thread/src/main/correction/distance-modeler.ts index 555e896c39..316d3bc3e4 100644 --- a/web/src/engine/predictive-text/worker-thread/src/main/correction/distance-modeler.ts +++ b/web/src/engine/predictive-text/worker-thread/src/main/correction/distance-modeler.ts @@ -9,7 +9,6 @@ import LexicalModel = LexicalModelTypes.LexicalModel; import LexiconTraversal = LexicalModelTypes.LexiconTraversal; import ProbabilityMass = LexicalModelTypes.ProbabilityMass; import Transform = LexicalModelTypes.Transform; -import USVString = LexicalModelTypes.USVString; type RealizedInput = ProbabilityMass[]; // NOT Distribution - they're masses from separate distributions. @@ -48,15 +47,15 @@ export class SearchNode { calculation: ClassicalDistanceCalculation, TraversableToken>; currentTraversal: LexiconTraversal; - toKey: (wordform: USVString) => USVString = str => str; + toKey: (wordform: string) => string = str => str; priorInput: RealizedInput; // Internal lazy-cache for .inputSamplingCost, as it's a bit expensive to re-compute. private _inputCost?: number; - constructor(rootTraversal: LexiconTraversal, toKey?: (arg0: USVString) => USVString); + constructor(rootTraversal: LexiconTraversal, toKey?: (arg0: string) => string); constructor(node: SearchNode); - constructor(rootTraversal: LexiconTraversal | SearchNode, toKey?: (arg0: USVString) => USVString) { + constructor(rootTraversal: LexiconTraversal | SearchNode, toKey?: (arg0: string) => string) { toKey = toKey || (x => x); if(rootTraversal instanceof SearchNode) { @@ -294,11 +293,11 @@ export class SearchResult { return this.resultNode.priorInput; } - get matchSequence(): TraversableToken[] { + get matchSequence(): TraversableToken[] { return this.resultNode.calculation.matchSequence; }; - get matchString(): USVString { + get matchString(): string { return this.resultNode.resultKey; } diff --git a/web/src/engine/predictive-text/worker-thread/src/main/model-compositor.ts b/web/src/engine/predictive-text/worker-thread/src/main/model-compositor.ts index d0b4658b13..7b04c7a0ad 100644 --- a/web/src/engine/predictive-text/worker-thread/src/main/model-compositor.ts +++ b/web/src/engine/predictive-text/worker-thread/src/main/model-compositor.ts @@ -13,7 +13,6 @@ import LexicalModelPunctuation = LexicalModelTypes.LexicalModelPunctuation; import Reversion = LexicalModelTypes.Reversion; import Suggestion = LexicalModelTypes.Suggestion; import Transform = LexicalModelTypes.Transform; -import USVString = LexicalModelTypes.USVString; export class ModelCompositor { private lexicalModel: LexicalModel; @@ -192,7 +191,7 @@ export class ModelCompositor { } // Responsible for applying casing rules to suggestions. - private applySuggestionCasing(suggestion: Suggestion, baseWord: USVString, casingForm: CasingForm) { + private applySuggestionCasing(suggestion: Suggestion, baseWord: string, casingForm: CasingForm) { // Step 1: does the suggestion replace the whole word? If not, we should extend the suggestion to do so. let unchangedLength = baseWord.kmwLength() - suggestion.transform.deleteLeft; From b7649defd03b17891fc166c1a9de083d6b16ce30 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Mon, 28 Apr 2025 18:17:15 +0200 Subject: [PATCH 05/57] chore(common): override check when running on TC This change overrides a check added in Ubuntu 24.04+ that prevents mixing Python packages installed through apt and through pip. This allows to install the necessary Python package for TC which isn't available as Debian package. This change allows builds on Ubuntu 24.04 based TC agents. --- linux/keyman-config/run-tests.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/linux/keyman-config/run-tests.sh b/linux/keyman-config/run-tests.sh index 41904e4cf3..337ebe8bbc 100755 --- a/linux/keyman-config/run-tests.sh +++ b/linux/keyman-config/run-tests.sh @@ -14,7 +14,15 @@ fi if [[ -n "${TEAMCITY_VERSION}" ]]; then if ! pip3 list --format=columns | grep -q teamcity-messages; then - pip3 install teamcity-messages + if [[ -n "${TEAMCITY_PLATFORM}" ]] || [[ -n "${DOCKER_RUNNING}" ]]; then + # Ubuntu 24.04+ prevents mixing pip and system packages and wants us + # to use a virtualenv. However, that causes other problems, so we + # override this check only if we're running in a TC agent or docker + # so that we don't accidentally break the local system. + PIP_ARGS="--break-system-packages" + fi + # shellcheck disable=SC2086 + pip3 install --user ${PIP_ARGS:-} teamcity-messages fi test_module=teamcity.unittestpy else From 0f8999a736bcdc99fb34d0686d62714d7d003b71 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 29 Apr 2025 11:48:03 +0200 Subject: [PATCH 06/57] fix(common): fix configure step in check-markdown The check-markdown tool gets called as part of a TC build. The configure action in `build.sh` will select the correct node version and set the necessary environment variables. However, previously this failed because `${KEYMAN_ROOT}/node_modules` might already exist even though we didn't configure check-markdown before. This change checks a local directory as output of the configure action and thus allows to build on a Noble based TC agent. --- resources/tools/check-markdown/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/tools/check-markdown/build.sh b/resources/tools/check-markdown/build.sh index 607be1dea6..c288b9a6be 100755 --- a/resources/tools/check-markdown/build.sh +++ b/resources/tools/check-markdown/build.sh @@ -15,7 +15,7 @@ builder_describe "Check markdown internal links" \ "build" builder_describe_outputs \ - configure /node_modules \ + configure "${THIS_SCRIPT_PATH}/node_modules" \ build build/index.js builder_parse "$@" From de0eaa411b32da5d374b816c1f5ca2e020d6193f Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Wed, 30 Apr 2025 09:01:47 +0700 Subject: [PATCH 07/57] change(web): lint kmwstring web-utility This removes the exception in #13797 for KMWString, properly including the newly-refactored code in linting as well. --- web/src/engine/common/web-utils/.eslintrc.cjs | 4 ---- web/src/engine/common/web-utils/src/kmwstring.ts | 6 +++--- 2 files changed, 3 insertions(+), 7 deletions(-) delete mode 100644 web/src/engine/common/web-utils/.eslintrc.cjs diff --git a/web/src/engine/common/web-utils/.eslintrc.cjs b/web/src/engine/common/web-utils/.eslintrc.cjs deleted file mode 100644 index 30334ae3dc..0000000000 --- a/web/src/engine/common/web-utils/.eslintrc.cjs +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - // Temporarily ignored due to noise it would cause within the refactor - ignorePatterns: ["**/kmwstring.ts"] -}; diff --git a/web/src/engine/common/web-utils/src/kmwstring.ts b/web/src/engine/common/web-utils/src/kmwstring.ts index d901f4adf8..8d45e4ee11 100644 --- a/web/src/engine/common/web-utils/src/kmwstring.ts +++ b/web/src/engine/common/web-utils/src/kmwstring.ts @@ -55,9 +55,9 @@ export function charCodeAt(s: string, index: number) { } } - let first = str.charCodeAt(codeUnitIndex); + const first = str.charCodeAt(codeUnitIndex); if(first >= 0xD800 && first <= 0xDBFF && str.length > codeUnitIndex + 1) { - let second = str.charCodeAt(codeUnitIndex + 1); + const second = str.charCodeAt(codeUnitIndex + 1); if(second >= 0xDC00 && second <= 0xDFFF) { return ((first - 0xD800) << 10) + (second - 0xDC00) + 0x10000; } @@ -248,7 +248,7 @@ export function substring(s: string, indexA: number, indexB?: number) { indexBCodeUnit = str.length; } else { if(indexA > indexB) { - let c = indexA; + const c = indexA; indexA = indexB; indexB = c; } From dbbb6fd8bcea9be5f17cd01f53bff5a33e0656a1 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Wed, 30 Apr 2025 12:20:35 +0700 Subject: [PATCH 08/57] fix(web): fix extraction of gesture-engine fixture used in DOM-based unit tests Test-bot: skip --- .../gesture-processor/src/tools/host-fixture/host-fixture.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/src/engine/osk/gesture-processor/src/tools/host-fixture/host-fixture.html b/web/src/engine/osk/gesture-processor/src/tools/host-fixture/host-fixture.html index 2565ac5c4b..83cf84ef33 100644 --- a/web/src/engine/osk/gesture-processor/src/tools/host-fixture/host-fixture.html +++ b/web/src/engine/osk/gesture-processor/src/tools/host-fixture/host-fixture.html @@ -23,6 +23,7 @@ --> +
@@ -40,7 +41,7 @@

- + \ No newline at end of file From e5b9118356b5366cc93490aea5987e75ec2c12ab Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Wed, 30 Apr 2025 12:22:31 +0700 Subject: [PATCH 09/57] chore(web): ensure gesture-recognizer unit tests run --- web/src/engine/osk/build.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/web/src/engine/osk/build.sh b/web/src/engine/osk/build.sh index e54a75bad1..33677a0a3d 100755 --- a/web/src/engine/osk/build.sh +++ b/web/src/engine/osk/build.sh @@ -51,7 +51,12 @@ do_build() { node validate-gesture-specs.js } +do_test() { + test-headless-typescript "${SUBPROJECT_NAME}" + ./gesture-processor/build.sh test +} + builder_run_action configure do_configure builder_run_action clean rm -rf "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}" builder_run_action build do_build -builder_run_action test test-headless-typescript "${SUBPROJECT_NAME}" \ No newline at end of file +builder_run_action test do_test \ No newline at end of file From 92a903ddd8485b974faa627cb8b542bd83dd1a7a Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Wed, 30 Apr 2025 19:46:00 +0200 Subject: [PATCH 10/57] maint(common): add support for TC blocks This change adds support for TC blocks of service messages (https://www.jetbrains.com/help/teamcity/service-messages.html#Blocks+of+Service+Messages) and starts/ends a block in the `builder_start_action`/`builder_finish_action` functions. We output the TC block service messages only if we're running on TC, i.e. if the `TEAMCITY_GIT_PATH` environment variable is set. Part-of: #13399 Test-bot: skip --- resources/build/test/test.sh | 91 +++++++++++++++++++++++++++ resources/builder.inc.sh | 116 ++++++++++++++++++++++------------- 2 files changed, 166 insertions(+), 41 deletions(-) diff --git a/resources/build/test/test.sh b/resources/build/test/test.sh index 1cbaa25476..fcce015ff5 100755 --- a/resources/build/test/test.sh +++ b/resources/build/test/test.sh @@ -188,6 +188,97 @@ if [[ "${parse_output[*]}" != "${expected}" ]]; then builder_die "FAIL: Wrong output for '--feature xyzzy --bar abc --baz def test':\n Actual : ${parse_output[*]}\n Expected: ${expected}" fi +#---------------------------------------------------------------------- +function builder_echo_tests() { + echo -e "${COLOR_BLUE}## Testing builder_echo${COLOR_RESET}" + _old_builder_debug_internal=${_builder_debug_internal} + _OLD_TEAMICITY_GIT_PATH=${TEAMCITY_GIT_PATH} + + # regular build, no internal debug + TEAMCITY_GIT_PATH="" + _builder_debug_internal=false + expected="" + result=$(builder_echo start "foo" "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo start foo description' (no debug):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + expected="" + result=$(builder_echo end "foo" success "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo end foo success description' (no debug):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + expected="$(builder_echo error "description")" + result=$(builder_echo end "foo" error "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo end foo error description' (no debug):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + + # regular build, with internal debug + _builder_debug_internal=true + expected="$(builder_echo heading "description")" + result=$(builder_echo start "foo" "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo start foo description' (debug):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + expected="$(builder_echo success "description")" + result=$(builder_echo end "foo" success "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo end foo success description' (debug):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + expected="$(builder_echo error "description")" + result=$(builder_echo end "foo" error "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo end foo error description' (debug):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + + # simulate running on TeamCity + TEAMCITY_GIT_PATH="foo" + # TC build, no internal debug + _builder_debug_internal=false + expected="##teamcity[blockOpened name='foo'] +$(builder_echo heading "description")" + result=$(builder_echo start "foo" "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo start foo description' on TC (no debug):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + expected="$(builder_echo success "description") +##teamcity[blockClosed name='foo']" + result=$(builder_echo end "foo" success "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo end foo success description' on TC (no debug):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + expected="$(builder_echo error "description") +##teamcity[blockClosed name='foo']" + result=$(builder_echo end "foo" error "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo end foo error description' on TC (no debug):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + + # TC build, with internal debug + _builder_debug_internal=true + expected="##teamcity[blockOpened name='foo'] +$(builder_echo heading "description")" + result=$(builder_echo start "foo" "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo start foo description' on TC (debug):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + expected="$(builder_echo success "description") +##teamcity[blockClosed name='foo']" + result=$(builder_echo end "foo" success "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo end foo success description' on TC (debug):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + expected="$(builder_echo error "description") +##teamcity[blockClosed name='foo']" + result=$(builder_echo end "foo" error "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo end foo error description' on TC (debug):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + TEAMCITY_GIT_PATH="${_OLD_TEAMICITY_GIT_PATH}" + _builder_debug_internal=${_old_builder_debug_internal} +} +builder_echo_tests + # Run tests based in separate scripts to facilitate their operation #---------------------------------------------------------------------- diff --git a/resources/builder.inc.sh b/resources/builder.inc.sh index 6e06313935..7d1f973e14 100755 --- a/resources/builder.inc.sh +++ b/resources/builder.inc.sh @@ -169,35 +169,73 @@ function builder_heading() { builder_echo() { - local color=white message= mark= - if [[ $# -gt 1 && $1 =~ ^(white|grey|green|success|blue|heading|yellow|warning|red|error|purple|brightwhite|teal|debug|setmark)$ ]]; then - color="$1" - shift + local color=white message= mark= block= action= do_output=true is_running_on_teamcity=false + if [[ -n "${TEAMCITY_GIT_PATH:-}" ]]; then + is_running_on_teamcity=true + fi + + if [[ $# -gt 1 ]]; then + if [[ $1 =~ ^(white|grey|green|success|blue|heading|yellow|warning|red|error|purple|brightwhite|teal|debug|setmark)$ ]]; then + color="$1" + shift + elif [[ $1 == "start" ]]; then + # builder_echo start block message + action="$1" + block="$2" + shift 2 + color="heading" + if ${is_running_on_teamcity}; then + do_output=true + else + do_output=${_builder_debug_internal:-false} + fi + elif [[ $1 == "end" ]]; then + # builder_echo end block status message + action="$1" + block="$2" + color="$3" + shift 3 + if [[ "${color}" == "error" ]] || ${is_running_on_teamcity}; then + do_output=true + else + do_output=${_builder_debug_internal:-false} + fi + fi fi message="$*" - if [[ ! -z ${COLOR_RED+x} ]]; then - case $color in - white) color="$COLOR_WHITE" ;; - grey) color="$COLOR_GREY" ;; - green|success) color="$COLOR_GREEN" ;; - blue|heading) color="$COLOR_BLUE" ;; - yellow|warning) color="$COLOR_YELLOW" ;; - red|error) color="$COLOR_RED" ;; - purple) color="$COLOR_PURPLE" ;; - brightwhite) color="$COLOR_BRIGHTWHITE" ;; - teal|debug) color="$COLOR_TEAL" ;; - setmark) mark="$HEADING_SETMARK" color="$COLOR_PURPLE" ;; - esac + if [[ "${action}" == "start" ]] && ${is_running_on_teamcity}; then + echo -e "##teamcity[blockOpened name='${block}']" + fi - if builder_is_dep_build; then - echo -e "$mark$COLOR_GREY[$THIS_SCRIPT_IDENTIFIER]$COLOR_RESET $color$message$COLOR_RESET" + if ${do_output}; then + if [[ ! -z ${COLOR_RED+x} ]]; then + case $color in + white) color="$COLOR_WHITE" ;; + grey) color="$COLOR_GREY" ;; + green|success) color="$COLOR_GREEN" ;; + blue|heading) color="$COLOR_BLUE" ;; + yellow|warning) color="$COLOR_YELLOW" ;; + red|error) color="$COLOR_RED" ;; + purple) color="$COLOR_PURPLE" ;; + brightwhite) color="$COLOR_BRIGHTWHITE" ;; + teal|debug) color="$COLOR_TEAL" ;; + setmark) mark="$HEADING_SETMARK" color="$COLOR_PURPLE" ;; + esac + + if builder_is_dep_build; then + echo -e "$mark$COLOR_GREY[$THIS_SCRIPT_IDENTIFIER]$COLOR_RESET $color$message$COLOR_RESET" + else + echo -e "$mark$BUILDER_BOLD$COLOR_BRIGHT_WHITE[$THIS_SCRIPT_IDENTIFIER]$COLOR_RESET $color$message$COLOR_RESET" + fi else - echo -e "$mark$BUILDER_BOLD$COLOR_BRIGHT_WHITE[$THIS_SCRIPT_IDENTIFIER]$COLOR_RESET $color$message$COLOR_RESET" + # Cope with the case of pre-init message and just emit plain text + echo -e "$message" fi - else - # Cope with the case of pre-init message and just emit plain text - echo -e "$message" + fi + + if [[ "${action}" == "end" ]] && ${is_running_on_teamcity}; then + echo -e "##teamcity[blockClosed name='${block}']" fi } @@ -393,9 +431,7 @@ _builder_execute_child() { local script="$THIS_SCRIPT_PATH/${_builder_target_paths[$target]}/build.sh" - if $_builder_debug_internal; then - builder_echo heading "## $action$target starting..." - fi + builder_echo start "$action$target" "## $action$target starting..." # Build array of specified inheritable options local child_options=() @@ -424,12 +460,10 @@ _builder_execute_child() { $builder_debug \ $_builder_offline \ && ( - if $_builder_debug_internal; then - builder_echo success "## $action$target completed successfully" - fi + builder_echo end "$action$target" success "## $action$target completed successfully" ) || ( result=$? - builder_echo error "## $action$target failed with exit code $result" + builder_echo end "$action$target" error "## $action$target failed with exit code $result" exit $result ) || exit $? # Required due to above subshell masking exit } @@ -619,19 +653,19 @@ builder_start_action() { # verify whether a target output is present. if builder_is_dep_build && ! builder_is_full_dep_build && - _builder_dep_output_exists $_builder_matched_action; then - builder_echo "skipping $_builder_matched_action_name, up-to-date" + _builder_dep_output_exists "${_builder_matched_action}"; then + builder_echo "skipping ${_builder_matched_action_name}, up-to-date" return 1 fi - builder_echo blue "## $_builder_matched_action_name starting..." - if [ -n "${_builder_current_action}" ]; then + builder_echo start "${_builder_matched_action_name}" "## ${_builder_matched_action_name} starting..." + if [[ -n "${_builder_current_action}" ]]; then _builder_warn_if_incomplete fi - _builder_current_action="$_builder_matched_action" + _builder_current_action="${_builder_matched_action}" # Build dependencies as required - _builder_do_build_deps "$_builder_matched_action" + _builder_do_build_deps "${_builder_matched_action}" return 0 else return 1 @@ -1659,15 +1693,15 @@ builder_finish_action() { # Sanity check: if there is a described output for this action, does the corresponding # file or directory exist now? if _builder_dep_output_defined $matched_action && ! _builder_dep_output_exists "$matched_action"; then - builder_echo warning "Expected output: '${_builder_dep_path[$matched_action]}'." - builder_echo warning "## $action_name completed successfully, but output does not exist" + builder_echo end "$action_name" warning "Expected output: '${_builder_dep_path[$matched_action]}'." + builder_echo end "$action_name" warning "## $action_name completed successfully, but output does not exist" else - builder_echo success "## $action_name completed successfully" + builder_echo end "$action_name" success "## $action_name completed successfully" fi elif [[ $result == failure ]]; then - builder_echo error "## $action_name failed" + builder_echo end "$action_name" error "## $action_name failed" else - builder_echo error "## $action_name failed with message: $result" + builder_echo end "$action_name" error "## $action_name failed with message: $result" fi # Remove $action$target from the array; it is no longer a current action From cb5e3035a71391f7328949c2480c690350bd4236 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Fri, 2 May 2025 09:33:33 +0700 Subject: [PATCH 11/57] chore(web): replace --ci flag with builder_is_ci_build Fixes: #12640 --- web/build.sh | 14 +++---------- web/ci.sh | 17 ++-------------- web/common.inc.sh | 5 ++++- web/src/app/browser/build.sh | 3 +-- web/src/app/ui/build.sh | 3 +-- web/src/app/webview/build.sh | 3 +-- web/src/engine/attachment/build.sh | 3 +-- web/src/engine/common/web-utils/build.sh | 5 ++--- web/src/engine/dom-utils/build.sh | 3 +-- web/src/engine/element-wrappers/build.sh | 3 +-- web/src/engine/events/build.sh | 3 +-- web/src/engine/interfaces/build.sh | 3 +-- web/src/engine/js-processor/build.sh | 3 +-- web/src/engine/keyboard-storage/build.sh | 3 +-- web/src/engine/keyboard/build.sh | 3 +-- web/src/engine/main/build.sh | 3 +-- web/src/engine/osk/build.sh | 3 +-- web/src/engine/osk/gesture-processor/build.sh | 3 +-- web/src/engine/predictive-text/build.sh | 5 ++--- .../engine/predictive-text/templates/build.sh | 6 +++--- .../predictive-text/wordbreakers/build.sh | 6 +++--- .../predictive-text/worker-main/build.sh | 10 +++------- .../worker-main/unit_tests/test.sh | 20 ++++++------------- .../predictive-text/worker-thread/build.sh | 10 +++------- web/src/samples/build.sh | 3 +-- web/src/test/manual/build.sh | 3 +-- web/src/tools/build.sh | 1 - web/test.sh | 5 ++--- 28 files changed, 49 insertions(+), 103 deletions(-) diff --git a/web/build.sh b/web/build.sh index 49160de690..3ebc47f631 100755 --- a/web/build.sh +++ b/web/build.sh @@ -9,6 +9,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" ## END STANDARD BUILD SCRIPT INCLUDE . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" +. "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh" # ################################ Main script ################################ @@ -41,8 +42,7 @@ builder_describe "Builds engine modules for Keyman Engine for Web (KMW)." \ ":samples Builds all needed resources for the KMW sample-page set" \ ":tools Builds engine-related development resources" \ ":test-pages=src/test/manual Builds resources needed for the KMW manual testing pages" \ - ":_all (Meta build target used when targets are not specified)" \ - "--ci+ Set to utilize CI-based test configurations & reporting." + ":_all (Meta build target used when targets are not specified)" # Possible TODO? # "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ @@ -133,14 +133,6 @@ build_action() { "${KEYMAN_ROOT}/web/build/test/dom/cases/attachment/" } -test_action() { - TEST_OPTS= - if builder_has_option --ci; then - TEST_OPTS=--ci - fi - ./test.sh "${TEST_OPTS}" -} - coverage_action() { builder_echo "Creating coverage report..." @@ -211,7 +203,7 @@ builder_run_action build:_all build_action # Run tests builder_run_child_actions test -builder_run_action test:_all test_action +builder_run_action test:_all ./test.sh function do_test_help() { check-markdown "$KEYMAN_ROOT/web/docs/engine" diff --git a/web/ci.sh b/web/ci.sh index 70cb24b965..e083b41455 100755 --- a/web/ci.sh +++ b/web/ci.sh @@ -63,8 +63,7 @@ function build_action() { # - also useful when validating this script on a local dev machine! # - build: then do the ACTUAL build. # one option: - # - --ci: For app/browser, outputs 'release' config filesize profiling logs - ./build.sh configure clean build --ci + ./build.sh configure clean build # Upload the sentry-configuration engine used by the mobile apps to sentry # Also, clean 'em first. @@ -79,19 +78,7 @@ function build_action() { } function test_action() { - # Testing step: run ALL unit tests, including those of the submodules. - - OPTIONS= - if ! builder_is_debug_build; then - OPTIONS=--ci - fi - - # No --reporter option exists yet for the headless modules. - - "${KEYMAN_ROOT}/web/src/engine/keyboard/build.sh" test ${OPTIONS} - "${KEYMAN_ROOT}/web/src/engine/osk/gesture-processor/build.sh" test ${OPTIONS} - - ./build.sh test ${OPTIONS} + ./build.sh test } function post_test_action() { diff --git a/web/common.inc.sh b/web/common.inc.sh index 56d0e7b5b3..4b24730d5d 100644 --- a/web/common.inc.sh +++ b/web/common.inc.sh @@ -1,6 +1,9 @@ #!/usr/bin/env bash # +# Needed for builder_is_ci_build check. +. "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh" + BUNDLE_CMD="node $KEYMAN_ROOT/web/src/tools/es-bundling/build/common-bundle.mjs" # Compiles all build products corresponding to the specified target. @@ -101,7 +104,7 @@ function test-headless() { fi TEST_OPTS= - if builder_has_option --ci; then + if builder_is_ci_build; then TEST_OPTS="--reporter mocha-teamcity-reporter" fi if [[ -n "$TEST_EXTENSIONS" ]]; then diff --git a/web/src/app/browser/build.sh b/web/src/app/browser/build.sh index d4c1023314..85c696ba4a 100755 --- a/web/src/app/browser/build.sh +++ b/web/src/app/browser/build.sh @@ -19,8 +19,7 @@ builder_describe "Builds the Keyman Engine for Web's website-integrating version "clean" \ "configure" \ "build" \ - "test" \ - "--ci+ Set to utilize CI-based test configurations & reporting." + "test" # Possible TODO?s # "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ diff --git a/web/src/app/ui/build.sh b/web/src/app/ui/build.sh index a0ac5c4007..3a431f9a0a 100755 --- a/web/src/app/ui/build.sh +++ b/web/src/app/ui/build.sh @@ -18,8 +18,7 @@ builder_describe "Builds the Keyman Engine for Web's desktop form-factor keyboar "clean" \ "configure" \ "build" \ - "test" \ - "--ci+ Set to utilize CI-based test configurations & reporting." + "test" # Possible TODO?s # "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ diff --git a/web/src/app/webview/build.sh b/web/src/app/webview/build.sh index 371c9325f2..1c2b2fe7dd 100755 --- a/web/src/app/webview/build.sh +++ b/web/src/app/webview/build.sh @@ -18,8 +18,7 @@ builder_describe "Builds the Keyman Engine for Web's puppetable version designed "clean" \ "configure" \ "build" \ - "test" \ - "--ci+ Set to utilize CI-based test configurations & reporting." + "test" # Possible TODO?s # "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ diff --git a/web/src/engine/attachment/build.sh b/web/src/engine/attachment/build.sh index 32d781a5b0..497e65e9a1 100755 --- a/web/src/engine/attachment/build.sh +++ b/web/src/engine/attachment/build.sh @@ -19,8 +19,7 @@ builder_describe "Builds the Keyman Engine for Web (KMW) attachment engine." \ "clean" \ "configure" \ "build" \ - "test" \ - "--ci+ Set to utilize CI-based test configurations & reporting." + "test" # Possible TODO? # "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ diff --git a/web/src/engine/common/web-utils/build.sh b/web/src/engine/common/web-utils/build.sh index ac18e2984c..0123919100 100755 --- a/web/src/engine/common/web-utils/build.sh +++ b/web/src/engine/common/web-utils/build.sh @@ -22,8 +22,7 @@ builder_describe \ "Compiles the web-oriented utility function module." \ "@/common/web/keyman-version" \ "@/web/src/tools/es-bundling" \ - clean configure build test \ - "--ci For use with action ${BUILDER_TERM_START}test${BUILDER_TERM_END} - emits CI-friendly test reports" + clean configure build test builder_describe_outputs \ configure "/node_modules" \ @@ -49,7 +48,7 @@ function do_test() { builder_heading "Running web-utils test suite" local FLAGS= - if builder_has_option --ci; then + if builder_is_ci_build; then echo "Replacing user-friendly test reports with CI-friendly versions." FLAGS="$FLAGS --reporter mocha-teamcity-reporter" fi diff --git a/web/src/engine/dom-utils/build.sh b/web/src/engine/dom-utils/build.sh index f842655c45..10cf2b660c 100755 --- a/web/src/engine/dom-utils/build.sh +++ b/web/src/engine/dom-utils/build.sh @@ -20,8 +20,7 @@ builder_describe "Builds DOM-utility modules used by the Keyman Engine for Web ( "clean" \ "configure" \ "build" \ - "test" \ - "--ci+ Set to utilize CI-based test configurations & reporting." + "test" # Possible TODO? # "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ diff --git a/web/src/engine/element-wrappers/build.sh b/web/src/engine/element-wrappers/build.sh index e188c7dd41..aeee72241a 100755 --- a/web/src/engine/element-wrappers/build.sh +++ b/web/src/engine/element-wrappers/build.sh @@ -17,8 +17,7 @@ builder_describe "Builds DOM-based OutputTarget subclasses used by the Keyman En "clean" \ "configure" \ "build" \ - "test" \ - "--ci+ Set to utilize CI-based test configurations & reporting." + "test" # Possible TODO? # "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ diff --git a/web/src/engine/events/build.sh b/web/src/engine/events/build.sh index 600ca8dc0c..e1f804908f 100755 --- a/web/src/engine/events/build.sh +++ b/web/src/engine/events/build.sh @@ -18,8 +18,7 @@ builder_describe "Builds specialized event-related modules utilized by Keyman En "clean" \ "configure" \ "build" \ - "test" \ - "--ci+ Set to utilize CI-based test configurations & reporting." + "test" # Possible TODO? # "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ diff --git a/web/src/engine/interfaces/build.sh b/web/src/engine/interfaces/build.sh index 94bb267cbc..502e1f7172 100755 --- a/web/src/engine/interfaces/build.sh +++ b/web/src/engine/interfaces/build.sh @@ -19,8 +19,7 @@ builder_describe "Builds configuration subclasses used by the Keyman Engine for "clean" \ "configure" \ "build" \ - "test" \ - "--ci+ Set to utilize CI-based test configurations & reporting." + "test" # Possible TODO?s # "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ diff --git a/web/src/engine/js-processor/build.sh b/web/src/engine/js-processor/build.sh index db00593166..620670276b 100755 --- a/web/src/engine/js-processor/build.sh +++ b/web/src/engine/js-processor/build.sh @@ -17,8 +17,7 @@ builder_describe "Builds configuration subclasses used by the Keyman Engine for "clean" \ "configure" \ "build" \ - "test" \ - "--ci+ Set to utilize CI-based test configurations & reporting." + "test" builder_describe_outputs \ configure "/node_modules" \ diff --git a/web/src/engine/keyboard-storage/build.sh b/web/src/engine/keyboard-storage/build.sh index b7ffc4d6b3..86755c613a 100755 --- a/web/src/engine/keyboard-storage/build.sh +++ b/web/src/engine/keyboard-storage/build.sh @@ -17,8 +17,7 @@ builder_describe "Builds Keyman Engine modules for keyboard cloud-querying & cac "clean" \ "configure" \ "build" \ - "test" \ - "--ci+ Set to utilize CI-based test configurations & reporting." + "test" # Possible TODO?s # "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ diff --git a/web/src/engine/keyboard/build.sh b/web/src/engine/keyboard/build.sh index fd15e59bc1..dc1283a7f2 100755 --- a/web/src/engine/keyboard/build.sh +++ b/web/src/engine/keyboard/build.sh @@ -25,8 +25,7 @@ builder_describe \ configure \ clean \ build \ - test \ - "--ci For use with action $(builder_term test) - emits CI-friendly test reports" + test builder_describe_outputs \ configure /node_modules \ diff --git a/web/src/engine/main/build.sh b/web/src/engine/main/build.sh index 8d6e39e0d2..a90e9f7660 100755 --- a/web/src/engine/main/build.sh +++ b/web/src/engine/main/build.sh @@ -24,8 +24,7 @@ builder_describe "Builds the Keyman Engine for Web's common top-level base class "clean" \ "configure" \ "build" \ - "test" \ - "--ci+ Set to utilize CI-based test configurations & reporting." + "test" # Possible TODO?s # "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ diff --git a/web/src/engine/osk/build.sh b/web/src/engine/osk/build.sh index e54a75bad1..44e0f4b481 100755 --- a/web/src/engine/osk/build.sh +++ b/web/src/engine/osk/build.sh @@ -21,8 +21,7 @@ builder_describe "Builds the Keyman Engine for Web's On-Screen Keyboard package "clean" \ "configure" \ "build" \ - "test" \ - "--ci+ Set to utilize CI-based test configurations & reporting." + "test" # Possible TODO?s # "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ diff --git a/web/src/engine/osk/gesture-processor/build.sh b/web/src/engine/osk/gesture-processor/build.sh index 70080b1a7f..8c6a4efb28 100755 --- a/web/src/engine/osk/gesture-processor/build.sh +++ b/web/src/engine/osk/gesture-processor/build.sh @@ -25,8 +25,7 @@ builder_describe "Builds the gesture-recognition model for Web-based on-screen k "build" \ "test" \ ":module" \ - ":tools tools for testing & developing test resources for this module" \ - "--ci sets the --ci option for child scripts (i.e, the $(builder_term test) action)" + ":tools tools for testing & developing test resources for this module" builder_describe_outputs \ configure /node_modules \ diff --git a/web/src/engine/predictive-text/build.sh b/web/src/engine/predictive-text/build.sh index 2209b4b014..ff0029ec40 100755 --- a/web/src/engine/predictive-text/build.sh +++ b/web/src/engine/predictive-text/build.sh @@ -21,8 +21,7 @@ builder_describe "Builds predictive-text components used within Keyman Engine fo ":wordbreakers Builds the wordbreakers provided for lexical model use" \ ":worker-main Builds the predictive-text worker interface module" \ ":worker-thread Builds the predictive-text worker" \ - ":_all (Meta build target used when targets are not specified)" \ - "--ci+ Set to utilize CI-based test configurations & reporting." + ":_all (Meta build target used when targets are not specified)" # Possible TODO? # "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ @@ -57,4 +56,4 @@ builder_run_child_actions build:templates builder_run_child_actions build:worker-thread builder_run_child_actions build:worker-main -builder_run_child_actions test \ No newline at end of file +builder_run_child_actions test diff --git a/web/src/engine/predictive-text/templates/build.sh b/web/src/engine/predictive-text/templates/build.sh index bf23622998..2dda929d27 100755 --- a/web/src/engine/predictive-text/templates/build.sh +++ b/web/src/engine/predictive-text/templates/build.sh @@ -9,6 +9,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" ## END STANDARD BUILD SCRIPT INCLUDE . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" +. "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh" ################################ Main script ################################ @@ -19,8 +20,7 @@ builder_describe "Builds the predictive-text model template implementation modul "clean" \ "configure" \ "build" \ - "test" \ - "--ci" + "test" builder_describe_outputs \ configure /node_modules \ @@ -38,7 +38,7 @@ function do_build() { function do_test() { local FLAGS= - if builder_has_option --ci; then + if builder_is_ci_build; then FLAGS="-reporter mocha-teamcity-reporter" fi diff --git a/web/src/engine/predictive-text/wordbreakers/build.sh b/web/src/engine/predictive-text/wordbreakers/build.sh index 6505dfdd4f..9e449030d8 100755 --- a/web/src/engine/predictive-text/wordbreakers/build.sh +++ b/web/src/engine/predictive-text/wordbreakers/build.sh @@ -9,6 +9,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" ## END STANDARD BUILD SCRIPT INCLUDE . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" +. "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh" ################################ Main script ################################ @@ -18,8 +19,7 @@ builder_describe "Builds the predictive-text wordbreaker implementation module" "clean" \ "configure" \ "build" \ - "test" \ - "--ci" + "test" builder_describe_outputs \ configure src/main/default/data.inc.ts \ @@ -47,7 +47,7 @@ function do_build() { function do_test() { local FLAGS= - if builder_has_option --ci; then + if builder_is_ci_build; then FLAGS="-reporter mocha-teamcity-reporter" fi diff --git a/web/src/engine/predictive-text/worker-main/build.sh b/web/src/engine/predictive-text/worker-main/build.sh index fd37a65a9b..6642e18b86 100755 --- a/web/src/engine/predictive-text/worker-main/build.sh +++ b/web/src/engine/predictive-text/worker-main/build.sh @@ -12,6 +12,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" ## END STANDARD BUILD SCRIPT INCLUDE . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" +. "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh" BUNDLE_CMD="node $KEYMAN_ROOT/web/src/tools/es-bundling/build/common-bundle.mjs" @@ -25,8 +26,7 @@ builder_describe "Builds the lm-layer module" \ "clean" \ "configure" \ "build" \ - "test" \ - "--ci Sets $(builder_term test) action to use CI-based test configurations & reporting" + "test" builder_describe_outputs \ configure /node_modules \ @@ -55,11 +55,7 @@ function do_build() { # Note - the actual test setup is done in a separate test script, but it's easy # enough to route the calls through. function do_test() { - local TEST_OPTIONS= - if builder_has_option --ci; then - TEST_OPTIONS=--ci - fi - ./unit_tests/test.sh test:headless test:browser ${TEST_OPTIONS} + ./unit_tests/test.sh test:headless test:browser } builder_run_action configure do_configure diff --git a/web/src/engine/predictive-text/worker-main/unit_tests/test.sh b/web/src/engine/predictive-text/worker-main/unit_tests/test.sh index 2ade97b599..e4ae5a50fd 100755 --- a/web/src/engine/predictive-text/worker-main/unit_tests/test.sh +++ b/web/src/engine/predictive-text/worker-main/unit_tests/test.sh @@ -22,20 +22,12 @@ builder_describe "Runs all tests for the language-modeling / predictive-text lay "test+" \ ":libraries Runs unit tests for in-repo libraries used by this module"\ ":headless Runs this module's headless user tests" \ - ":browser Runs this module's browser-based user tests" \ - "--ci Uses CI-based test configurations & emits CI-friendly test reports" + ":browser Runs this module's browser-based user tests" # TODO: consider dependencies? ideally this will be test.inc.sh? builder_parse "$@" -TEST_OPTS= -if builder_has_option --ci && builder_is_debug_build; then - builder_die "Options --ci and --debug are incompatible." -elif builder_has_option --ci; then - TEST_OPTS=--ci -fi - if builder_start_action configure; then verify_npm_setup builder_finish_action success configure @@ -49,18 +41,18 @@ if builder_start_action test:libraries; then # addition to fair bit of `pushd` and `popd`. echo echo "### Running $(builder_term web/src/engine/predictive-text/wordbreakers) tests" - "$KEYMAN_ROOT/web/src/engine/predictive-text/wordbreakers/build.sh" test $TEST_OPTS + "$KEYMAN_ROOT/web/src/engine/predictive-text/wordbreakers/build.sh" test pushd "$KEYMAN_ROOT/web/src/engine/predictive-text/templates/" echo echo "### Running $(builder_term web/src/engine/predictive-text/templates/) tests" - "$KEYMAN_ROOT/web/src/engine/predictive-text/templates/build.sh" test $TEST_OPTS + "$KEYMAN_ROOT/web/src/engine/predictive-text/templates/build.sh" test popd pushd "$KEYMAN_ROOT/web/src/engine/predictive-text/worker-thread" echo echo "### Running ${BUILDER_TERM_START}web/src/engine/predictive-text/worker-thread${BUILDER_TERM_END} tests" - ./build.sh test $TEST_OPTS + ./build.sh test popd builder_finish_action success test:libraries @@ -69,7 +61,7 @@ fi if builder_start_action test:headless; then MOCHA_FLAGS=$FLAGS - if builder_has_option --ci; then + if builder_is_ci_build; then MOCHA_FLAGS="$MOCHA_FLAGS --reporter mocha-teamcity-reporter" fi @@ -109,7 +101,7 @@ if builder_start_action test:browser; then WTR_CONFIG= WTR_DEBUG= - if builder_has_option --ci; then + if builder_is_ci_build; then WTR_CONFIG=.CI fi diff --git a/web/src/engine/predictive-text/worker-thread/build.sh b/web/src/engine/predictive-text/worker-thread/build.sh index ddf332e90d..78bd10d2d7 100755 --- a/web/src/engine/predictive-text/worker-thread/build.sh +++ b/web/src/engine/predictive-text/worker-thread/build.sh @@ -10,6 +10,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" ## END STANDARD BUILD SCRIPT INCLUDE . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" +. "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh" WORKER_OUTPUT=build/obj WORKER_OUTPUT_FILENAME=build/lib/worker-main.js @@ -30,7 +31,7 @@ builder_describe \ "@/web/src/tools/es-bundling" \ "@../wordbreakers" \ "@../templates" \ - configure clean build test --ci + configure clean build test builder_describe_outputs \ configure /node_modules \ @@ -47,11 +48,6 @@ function do_configure() { } function do_build() { - EXT_FLAGS= - if builder_has_option --ci; then - EXT_FLAGS=--ci - fi - # Declaration bundling. tsc --emitDeclarationOnly --outFile $INTERMEDIATE/worker-main.d.ts @@ -98,7 +94,7 @@ function do_test() { local WTR_CONFIG= local WTR_DEBUG= - if builder_has_option --ci; then + if builder_is_ci_build; then MOCHA_FLAGS="$MOCHA_FLAGS --reporter mocha-teamcity-reporter" WTR_CONFIG=.CI fi diff --git a/web/src/samples/build.sh b/web/src/samples/build.sh index b67df8565b..fe5817e6e5 100755 --- a/web/src/samples/build.sh +++ b/web/src/samples/build.sh @@ -19,8 +19,7 @@ builder_describe "Builds the Keyman Engine for Web's sample page setups." \ "configure Does nothing for this project" \ "clean" \ "build" \ - "test Does nothing for this project" \ - "--ci Does nothing for this project" + "test Does nothing for this project" # Possible TODO?s # "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ diff --git a/web/src/test/manual/build.sh b/web/src/test/manual/build.sh index ee75c87710..44ff6c3bad 100755 --- a/web/src/test/manual/build.sh +++ b/web/src/test/manual/build.sh @@ -18,8 +18,7 @@ builder_describe "Builds the Keyman Engine for Web's sample page setups." \ "configure Does nothing for this project" \ "clean" \ "build" \ - "test Does nothing for this project" \ - "--ci Does nothing for this project" + "test Does nothing for this project" # Possible TODO?s # "upload-symbols Uploads build product to Sentry for error report symbolification. Only defined for $DOC_BUILD_EMBED_WEB" \ diff --git a/web/src/tools/build.sh b/web/src/tools/build.sh index b7670418ab..8732527b41 100755 --- a/web/src/tools/build.sh +++ b/web/src/tools/build.sh @@ -19,7 +19,6 @@ builder_describe "Builds the Keyman Engine for Web's development & unit-testing "clean" \ "build" \ "test" \ - "--ci Does nothing for this script" \ ":bulk_rendering=testing/bulk_rendering Builds the bulk-rendering tool used to validate changes to OSK display code" \ ":recorder=testing/recorder Builds the KMW recorder tool used for development of unit-test resources" \ ":sourcemap-root=building/sourcemap-root Builds the sourcemap-cleaning tool used during minification of app/ builds" diff --git a/web/test.sh b/web/test.sh index 12216512c9..3497ed5322 100755 --- a/web/test.sh +++ b/web/test.sh @@ -20,8 +20,7 @@ builder_describe "Runs the Keyman Engine for Web unit-testing suites" \ "@./src/tools/testing/recorder test:integrated" \ "test+" \ ":dom Runs DOM-oriented unit tests (reduced footprint, nothing browser-specific)" \ - ":integrated Runs KMW's integration test suite" \ - "--ci Set to utilize CI-based test configurations & reporting. May not be set with $(builder_term --debug)." + ":integrated Runs KMW's integration test suite" builder_parse "$@" @@ -29,7 +28,7 @@ builder_parse "$@" # Select the right CONFIG file. WTR_CONFIG= -if builder_has_option --ci; then +if builder_is_ci_build; then WTR_CONFIG=.CI fi From b6fbf165dd3e4b252543ea1524a7c7af8b86c95d Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Fri, 2 May 2025 09:52:43 +0700 Subject: [PATCH 12/57] maint(web): simplify worker-main test.sh --- .../worker-main/unit_tests/test.sh | 53 ------------------- 1 file changed, 53 deletions(-) diff --git a/web/src/engine/predictive-text/worker-main/unit_tests/test.sh b/web/src/engine/predictive-text/worker-main/unit_tests/test.sh index e4ae5a50fd..de915488de 100755 --- a/web/src/engine/predictive-text/worker-main/unit_tests/test.sh +++ b/web/src/engine/predictive-text/worker-main/unit_tests/test.sh @@ -20,7 +20,6 @@ FLAGS="" builder_describe "Runs all tests for the language-modeling / predictive-text layer module" \ "configure" \ "test+" \ - ":libraries Runs unit tests for in-repo libraries used by this module"\ ":headless Runs this module's headless user tests" \ ":browser Runs this module's browser-based user tests" @@ -33,31 +32,6 @@ if builder_start_action configure; then builder_finish_action success configure fi -if builder_start_action test:libraries; then - - # Note: these do not yet provide TeamCity-friendly-formatted test reports. - # They do not have builder-based scripts, being run directly via npm package script. - # So, for now, we add a text header to clarify what is running at each stage, in - # addition to fair bit of `pushd` and `popd`. - echo - echo "### Running $(builder_term web/src/engine/predictive-text/wordbreakers) tests" - "$KEYMAN_ROOT/web/src/engine/predictive-text/wordbreakers/build.sh" test - - pushd "$KEYMAN_ROOT/web/src/engine/predictive-text/templates/" - echo - echo "### Running $(builder_term web/src/engine/predictive-text/templates/) tests" - "$KEYMAN_ROOT/web/src/engine/predictive-text/templates/build.sh" test - popd - - pushd "$KEYMAN_ROOT/web/src/engine/predictive-text/worker-thread" - echo - echo "### Running ${BUILDER_TERM_START}web/src/engine/predictive-text/worker-thread${BUILDER_TERM_END} tests" - ./build.sh test - popd - - builder_finish_action success test:libraries -fi - if builder_start_action test:headless; then MOCHA_FLAGS=$FLAGS @@ -70,33 +44,6 @@ if builder_start_action test:headless; then builder_finish_action success test:headless fi -# If we are running a TeamCity test build, for now, only run BrowserStack -# tests when on a PR branch with a title including "(web)" or with the label -# test-browserstack. This is because the BrowserStack tests are currently -# unreliable, and the false positive failures are masking actual failures. -# -# We do not run BrowserStack tests on master, beta, or stable-x.y test -# builds. -if [[ $VERSION_ENVIRONMENT == test ]] && builder_has_action test:browser; then - if builder_pull_get_details; then - if ! ([[ $builder_pull_title =~ \(web\) ]] || builder_pull_has_label test-browserstack); then - - echo "Auto-skipping $(builder_term test:browser) for unrelated CI test build" - exit 0 - fi - fi -fi - -get_browser_set_for_OS ( ) { - if [[ $BUILDER_OS == mac ]]; then - BROWSERS="--browsers Firefox,Chrome,Safari" - elif [[ $BUILDER_OS == win ]]; then - BROWSERS="--browsers Chrome" - else - BROWSERS="--browsers Firefox,Chrome" - fi -} - if builder_start_action test:browser; then WTR_CONFIG= WTR_DEBUG= From a0ce7d293463989a5bfed4dbb65230755f709ec9 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Fri, 2 May 2025 11:58:33 +0700 Subject: [PATCH 13/57] change(web): apply suggestion from PR review Co-authored-by: Eberhard Beilharz --- web/src/engine/osk/src/lengthStyle.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/engine/osk/src/lengthStyle.ts b/web/src/engine/osk/src/lengthStyle.ts index b0161d63bb..f0f9830fdb 100644 --- a/web/src/engine/osk/src/lengthStyle.ts +++ b/web/src/engine/osk/src/lengthStyle.ts @@ -13,7 +13,7 @@ export class ParsedLengthStyle implements LengthStyle { let parsed: LengthStyle = (typeof style == 'string') ? ParsedLengthStyle.parseLengthStyle(style) : style; const fallback: LengthStyle = { - val: 1, + val: 1, // 100% absolute: false }; From b32c236103d91bbbcb35f00a5cca89590bc390d9 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 2 May 2025 12:45:52 +0700 Subject: [PATCH 14/57] maint(common): rename gosh.sh to gosh and use /usr/bin/env bash Fixes: #13822 --- resources/gosh/{gosh.sh => gosh} | 0 resources/gosh/gosh.js | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename resources/gosh/{gosh.sh => gosh} (100%) diff --git a/resources/gosh/gosh.sh b/resources/gosh/gosh similarity index 100% rename from resources/gosh/gosh.sh rename to resources/gosh/gosh diff --git a/resources/gosh/gosh.js b/resources/gosh/gosh.js index 47a6900c16..de3c8cfc30 100755 --- a/resources/gosh/gosh.js +++ b/resources/gosh/gosh.js @@ -108,6 +108,6 @@ function launchWin32Bash() { } function launchNixBash() { - const child_args = args.slice(1); - return child_process.spawnSync(args[0], child_args, {shell: '/bin/bash', stdio:'inherit'}); + const child_args = ['bash', ...args.slice(1)]; + return child_process.spawnSync(args[0], child_args, {shell: '/usr/bin/env', stdio:'inherit'}); } From cf0b83081b5b2b598a6380a6b7bc3aaf6a748367 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Fri, 2 May 2025 12:20:32 +0700 Subject: [PATCH 15/57] change(web): use pt-style sizing for unitless touch-layout fontsizes --- web/src/engine/osk/src/views/oskView.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/web/src/engine/osk/src/views/oskView.ts b/web/src/engine/osk/src/views/oskView.ts index 41989dd72f..961a246d08 100644 --- a/web/src/engine/osk/src/views/oskView.ts +++ b/web/src/engine/osk/src/views/oskView.ts @@ -521,7 +521,13 @@ export default abstract class OSKView // Set default OSK font size (Build 344, KMEW-90) // If the layer group specifies a fontsize value, we need // to apply that to the banner as well. - const layerFontSize = this.vkbd?.layerGroup?.spec.fontsize; + const layerFontSizeRaw = this.vkbd?.layerGroup?.spec.fontsize; + // Addresses issue with touch-layouts specifying a unitless fontsize; this + // coerces them to `pt` style sizing, like how word-processors present font-size. + // + // Returns NaN if not 100% a number. "12px", "12pt", "12%" all return NaN. + const fsRaw = Number(layerFontSizeRaw); + const layerFontSize = isNaN(fsRaw) ? layerFontSizeRaw : (fsRaw + 'pt'); if(layerFontSize) { const parsedSize = new ParsedLengthStyle(layerFontSize); From 17ff99a18b2f4edf0a822b233939080132ffdf2c Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 2 May 2025 12:50:14 +0700 Subject: [PATCH 16/57] chore(common): /bin/bash to launch the shell --- resources/gosh/gosh.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/gosh/gosh.js b/resources/gosh/gosh.js index de3c8cfc30..fd37968b14 100755 --- a/resources/gosh/gosh.js +++ b/resources/gosh/gosh.js @@ -109,5 +109,5 @@ function launchWin32Bash() { function launchNixBash() { const child_args = ['bash', ...args.slice(1)]; - return child_process.spawnSync(args[0], child_args, {shell: '/usr/bin/env', stdio:'inherit'}); + return child_process.spawnSync(args[0], child_args, {shell: '/bin/bash', stdio:'inherit'}); } From 76e9a789b0db7d86b7f5763ad8d65cb09af9e34f Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 2 May 2025 13:04:39 +0700 Subject: [PATCH 17/57] chore(common): restore gosh.js --- resources/gosh/gosh.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/gosh/gosh.js b/resources/gosh/gosh.js index fd37968b14..47a6900c16 100755 --- a/resources/gosh/gosh.js +++ b/resources/gosh/gosh.js @@ -108,6 +108,6 @@ function launchWin32Bash() { } function launchNixBash() { - const child_args = ['bash', ...args.slice(1)]; + const child_args = args.slice(1); return child_process.spawnSync(args[0], child_args, {shell: '/bin/bash', stdio:'inherit'}); } From ccc186c9a58be46c4a99213e7e7d60208745c0a2 Mon Sep 17 00:00:00 2001 From: rc-swag <58423624+rc-swag@users.noreply.github.com> Date: Fri, 2 May 2025 17:11:42 +1000 Subject: [PATCH 18/57] fix(windows): add breadcrumb to download failures Also add checks to see if it the system is online before attempting downloads. Adding this to the breadcrumb also. --- .../desktop/kmshell/main/Keyman.System.DownloadUpdate.pas | 8 ++++++++ .../kmshell/main/Keyman.System.UpdateStateMachine.pas | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/windows/src/desktop/kmshell/main/Keyman.System.DownloadUpdate.pas b/windows/src/desktop/kmshell/main/Keyman.System.DownloadUpdate.pas index 76724f95c3..dab746f31c 100644 --- a/windows/src/desktop/kmshell/main/Keyman.System.DownloadUpdate.pas +++ b/windows/src/desktop/kmshell/main/Keyman.System.DownloadUpdate.pas @@ -59,6 +59,7 @@ uses OnlineUpdateCheckMessages, RegistryKeys, Upload_Settings, + UtilCheckOnline, utilkmshell; procedure ErrorLogMessage(ErrorLogMessage: string); @@ -143,6 +144,7 @@ begin else begin Params.Packages[i].Install := False; // Download failed but install other files + TKeymanSentryClient.Breadcrumb('error', 'Download failded for keyboard: '+ Params.Packages[i].DownloadURL, 'cli.download'); end; end; @@ -157,6 +159,7 @@ begin else begin ErrorLogMessage('DoDownloadUpdates Failed to download' + Params.InstallURL); + TKeymanSentryClient.Breadcrumb('error', 'Download failded for keyboard: '+ Params.InstallURL, 'cli.download'); end; end; // If there is at least one keyboard package or version of keyman downloaded then @@ -172,6 +175,11 @@ var DownloadBackGroundSavePath : String; ucr: TUpdateCheckResponse; begin + if not IsOnline then + begin + TKeymanSentryClient.Breadcrumb('default', 'TDownloadUpdate: Not Online, cant execute download process.', 'cli.download'); + Exit; + end; DownloadBackGroundSavePath := IncludeTrailingPathDelimiter(TKeymanPaths.KeymanUpdateCachePath); if TUpdateCheckStorage.LoadUpdateCacheData(ucr) then begin diff --git a/windows/src/desktop/kmshell/main/Keyman.System.UpdateStateMachine.pas b/windows/src/desktop/kmshell/main/Keyman.System.UpdateStateMachine.pas index a6cf9bd2e5..e8f4a30bcc 100644 --- a/windows/src/desktop/kmshell/main/Keyman.System.UpdateStateMachine.pas +++ b/windows/src/desktop/kmshell/main/Keyman.System.UpdateStateMachine.pas @@ -126,6 +126,7 @@ uses KLog, RegistryKeys, utilexecute, + UtilCheckOnline, utiluac; const @@ -685,6 +686,12 @@ var FResult: Boolean; RootPath: string; begin + // check if online + if not IsOnline then + begin + TKeymanSentryClient.Breadcrumb('default', 'Not Online, cant execute download process.', 'update'); + Exit; + end; // call separate process RootPath := ExtractFilePath(ParamStr(0)); FResult := TUtilExecute.ShellCurrentUser(0, ParamStr(0), From 5af26297d93fdcf374e4f48b1f774399609bfe95 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Fri, 2 May 2025 15:02:04 +0700 Subject: [PATCH 19/57] maint(common): automatically set --debug option in local-environment builder scripts Fixes: #11106 --- resources/builder.inc.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/resources/builder.inc.sh b/resources/builder.inc.sh index 6e06313935..d94db7423b 100755 --- a/resources/builder.inc.sh +++ b/resources/builder.inc.sh @@ -1461,6 +1461,16 @@ _builder_parse_expanded_parameters() { done fi + # Per #11106, local builds are now automatically forced into the --debug configuration. + # Set now so that the automatic --debug shows up in the parameter list reported from + # the final 'else' block in the following if-else chain. + if [[ $VERSION_ENVIRONMENT == "local" ]] && [[ $builder_debug != --debug ]]; then + builder_echo grey "Local build environment detected: setting --debug" + _params+=(--debug) + _builder_chosen_options+=(--debug) + builder_debug=--debug + fi + if builder_is_dep_build; then if [[ -z ${_builder_deps_built+x} ]]; then builder_die "FATAL ERROR: Expected '_builder_deps_built' variable to be set" From 85046ceb6dd3fbd6cb3f59fbf3cb0488db22003a Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Fri, 2 May 2025 15:37:39 +0700 Subject: [PATCH 20/57] fix(common): builder.inc.sh test script patchup for automatic local --debug --- resources/build/test/test.sh | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/resources/build/test/test.sh b/resources/build/test/test.sh index 1cbaa25476..699b18d064 100755 --- a/resources/build/test/test.sh +++ b/resources/build/test/test.sh @@ -89,6 +89,12 @@ fi builder_parse_test() { local expected="$1" local expected_options="$2" + + # Minor override for local testing of builder-script mechanics: --debug will always be added. + if [[ $VERSION_ENVIRONMENT == "local" ]]; then + expected_options="${expected_options} --debug" + fi + shift shift local parameters="$@" @@ -97,8 +103,10 @@ builder_parse_test() { if [[ "$expected" != "${_builder_chosen_action_targets[@]}" ]]; then builder_die " Test: builder_parse $parameters action:target != \"$expected\"" fi - if [[ "$expected_options" != "${_builder_chosen_options[@]}" ]]; then - builder_die " Test: builder_parse $parameters, options != \"$expected\"" + if [[ "${expected_options}" != "${_builder_chosen_options[@]}" ]]; then + echo "${_builder_chosen_options[@]}" + echo "${_builder_chosen_options[@]}" + builder_die " Test: builder_parse $parameters, options != \"${expected_options}\"" fi } @@ -184,6 +192,14 @@ fi echo -e "${COLOR_BLUE}## Testing output of: builder_parse --feature xyzzy --bar abc --baz def test${COLOR_RESET}" parse_output=$(builder_parse --feature xyzzy --bar abc --baz def test) expected="$(builder_echo setmark "test.sh parameters: <--feature xyzzy --bar abc --baz def test>")" + +if [[ $VERSION_ENVIRONMENT == "local" ]]; then + expected="$(builder_echo setmark "test.sh parameters: <--feature xyzzy --bar abc --baz def test --debug>")" + # Yay, the fun of getting the second line... that newline before the closing brace is intentional. :( + parse_output=${parse_output#* +} + +fi if [[ "${parse_output[*]}" != "${expected}" ]]; then builder_die "FAIL: Wrong output for '--feature xyzzy --bar abc --baz def test':\n Actual : ${parse_output[*]}\n Expected: ${expected}" fi From 519a5b79e92f751a3f06baf38b41b65255388a36 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Mon, 5 May 2025 12:36:01 +0700 Subject: [PATCH 21/57] maint(common): address builder.sh test script review comments Co-authored-by: Marc Durdin --- resources/build/test/test.sh | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/resources/build/test/test.sh b/resources/build/test/test.sh index 699b18d064..78a320a26c 100755 --- a/resources/build/test/test.sh +++ b/resources/build/test/test.sh @@ -90,7 +90,7 @@ builder_parse_test() { local expected="$1" local expected_options="$2" - # Minor override for local testing of builder-script mechanics: --debug will always be added. + # When testing in a local environment, --debug will be added by default (see #11106) if [[ $VERSION_ENVIRONMENT == "local" ]]; then expected_options="${expected_options} --debug" fi @@ -104,8 +104,6 @@ builder_parse_test() { builder_die " Test: builder_parse $parameters action:target != \"$expected\"" fi if [[ "${expected_options}" != "${_builder_chosen_options[@]}" ]]; then - echo "${_builder_chosen_options[@]}" - echo "${_builder_chosen_options[@]}" builder_die " Test: builder_parse $parameters, options != \"${expected_options}\"" fi } @@ -194,11 +192,8 @@ parse_output=$(builder_parse --feature xyzzy --bar abc --baz def test) expected="$(builder_echo setmark "test.sh parameters: <--feature xyzzy --bar abc --baz def test>")" if [[ $VERSION_ENVIRONMENT == "local" ]]; then - expected="$(builder_echo setmark "test.sh parameters: <--feature xyzzy --bar abc --baz def test --debug>")" - # Yay, the fun of getting the second line... that newline before the closing brace is intentional. :( - parse_output=${parse_output#* -} - + # When run in a local-dev environment, an extra line appears about the automatic --debug option. + expected="$(builder_echo grey "Local build environment detected: setting --debug")"$'\n'"$(builder_echo setmark "test.sh parameters: <--feature xyzzy --bar abc --baz def test --debug>")" fi if [[ "${parse_output[*]}" != "${expected}" ]]; then builder_die "FAIL: Wrong output for '--feature xyzzy --bar abc --baz def test':\n Actual : ${parse_output[*]}\n Expected: ${expected}" From ab9ed717aaacf4778889811dc3eb889e6d661429 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Mon, 5 May 2025 12:48:55 +0700 Subject: [PATCH 22/57] maint(common): add --release option to force release builds in local environment Co-authored-by: Marc Durdin --- resources/builder.inc.sh | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/resources/builder.inc.sh b/resources/builder.inc.sh index d94db7423b..6eee6be02d 100755 --- a/resources/builder.inc.sh +++ b/resources/builder.inc.sh @@ -1048,6 +1048,7 @@ _builder_get_default_description() { :module) description="this module" ;; :tools) description="build tools for this project" ;; --debug) description="debug build" ;; + --release) description="release build" ;; esac echo "$description" } @@ -1269,6 +1270,7 @@ _builder_parse_expanded_parameters() { _builder_build_deps=--deps builder_verbose= builder_debug= + builder_release= local _params=($@) _builder_chosen_action_targets=() _builder_chosen_options=() @@ -1389,6 +1391,12 @@ _builder_parse_expanded_parameters() { _builder_chosen_options+=(--debug) builder_debug=--debug ;; + --release|-r) + _builder_chosen_options+=(--release) + # As of #13827, this is only checked when detecting if --debug should be auto-applied. + # There is no `builder_is_release_build` function yet. + builder_release=--release + ;; --deps|--no-deps|--force-deps) _builder_build_deps=$key ;; @@ -1461,16 +1469,6 @@ _builder_parse_expanded_parameters() { done fi - # Per #11106, local builds are now automatically forced into the --debug configuration. - # Set now so that the automatic --debug shows up in the parameter list reported from - # the final 'else' block in the following if-else chain. - if [[ $VERSION_ENVIRONMENT == "local" ]] && [[ $builder_debug != --debug ]]; then - builder_echo grey "Local build environment detected: setting --debug" - _params+=(--debug) - _builder_chosen_options+=(--debug) - builder_debug=--debug - fi - if builder_is_dep_build; then if [[ -z ${_builder_deps_built+x} ]]; then builder_die "FATAL ERROR: Expected '_builder_deps_built' variable to be set" @@ -1482,11 +1480,21 @@ _builder_parse_expanded_parameters() { else # This is a top-level invocation, so we want to track which dependencies # have been built, so they don't get built multiple times. + export _builder_deps_built=`mktemp` + + # Per #11106, local builds use --debug by default. + # Second condition prevents the block (and message) from executing when --debug is already specified explicitly. + if [[ $VERSION_ENVIRONMENT == "local" ]] && [[ $builder_debug != --debug ]] && [[ $builder_release != --release ]]; then + builder_echo grey "Local build environment detected: setting --debug" + _params+=(--debug) + _builder_chosen_options+=(--debug) + builder_debug=--debug + fi + builder_echo setmark "$(basename "$0") parameters: <${_params[@]}>" if [[ ${#builder_extra_params[@]} -gt 0 ]]; then builder_echo grey "$(basename "$0") extra parameters: <${builder_extra_params[@]}>" fi - export _builder_deps_built=`mktemp` fi if builder_is_debug_build; then From 51649bb8d3203a66e612eb56dd8f6390cec279c7 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Mon, 5 May 2025 12:50:05 +0700 Subject: [PATCH 23/57] maint(common): builder_release var should be local --- resources/builder.inc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/builder.inc.sh b/resources/builder.inc.sh index 6eee6be02d..f72206e9b9 100755 --- a/resources/builder.inc.sh +++ b/resources/builder.inc.sh @@ -1270,7 +1270,7 @@ _builder_parse_expanded_parameters() { _builder_build_deps=--deps builder_verbose= builder_debug= - builder_release= + local builder_release= local _params=($@) _builder_chosen_action_targets=() _builder_chosen_options=() From 80951c247acfa0b19f58f1d1e7dd72c42f5184d7 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Mon, 5 May 2025 13:31:31 +0700 Subject: [PATCH 24/57] docs(web): revised areas noted in code review Does not include the requested flowchart, which'll be its own commit once I work out the needed details and relationships. --- web/docs/internal/keystroke-lifecycle.md | 36 ++++++++++++++++-------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/web/docs/internal/keystroke-lifecycle.md b/web/docs/internal/keystroke-lifecycle.md index ff3dca47df..9f520be3e4 100644 --- a/web/docs/internal/keystroke-lifecycle.md +++ b/web/docs/internal/keystroke-lifecycle.md @@ -1,27 +1,41 @@ # The Keyman Engine for Web keystroke lifecycle -Depending on the variant of Keyman Engine for Web in play, the engine integrates either with a host app or with the current browser page to interpret and/or intercept keystroke events and produce the desired context manipulations corresponding to them. While some details diverge between `app/browser` and `app/webview` builds, the general structure and pattern for this process holds. - -This document will break down the full keystroke lifecycle into four distinct phases, as follows: +The phases of Keyman Engine for Web keystroke processings are as follows: 1. Keystroke pre-processing: event interception + interpretation (pre-processing) 2. Keystroke processing: keystroke main-group rule evaluation 3. Keystroke post-processing: keystroke post-keystroke evaluation + side-effects 4. Keystroke resolution: UI state updating +Keyman Engine for Web currently has two different builds, each used in specific contexts: + +* app/browser - for direct use on a page or site within a web browser +* app/webview - for integration with a host app, such as Keyman itself + +The overall phases for the keystroke lifecycle are the same for both; the implementation is merely a bit different for each within specific phases. These differences are documented after the common structure and patterns for each phase. + +Also note that Keyman Engine for Web supports keystroke processing for different keyboard specification formats: +- JS +- KMX (via web-core) +- KMX+ / LDML (via web-core) + +The `KeyboardProcessor` classes each handle keystroke processing for one specification format while adhering to a common interface exposed and accessible to the other layers of the keystroke lifecycle. + ## Keystroke pre-processing -Both the `app/browser` and `app/webview` products are capable of handling simulated keystrokes from the on-screen keyboard as well as hardware keystrokes. For hardware keystrokes, this varies between the two, while the majority of on-screen keyboard keystrokes are handled identically. +Both the `app/browser` and `app/webview` products are capable of handling keystrokes from the on-screen keyboard as well as hardware keystrokes. For hardware keystrokes, this varies between the two, while the majority of on-screen keyboard keystrokes are handled identically. -### `app/browser` +### `app/browser` - hardware keystrokes -The `app/browser` version of the engine is designed to integrate with the active page of the user's browser, giving it far more direct access to the user's true context in addition to direct access to handling DOM events resulting from hardware keystrokes. Its `HardwareEventKeyboard` class is the primary module for establishing the needed engine event hooks and for interpreting the corresponding DOM events as they arise. +The `app/browser` version of the engine is designed to integrate with the active page of the user's browser. As a result of this, contexts for text manipulation are directly implemented within Web elements that the engine has direct access to. It can thus attach DOM event handlers (for [`keydown`](https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event), [`keyup`](https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event), and [`keypress`](https://developer.mozilla.org/en-US/docs/Web/API/Element/keypress_event)) in order to process hardware keystrokes. Its `HardwareEventKeyboard` class is the primary module for handling hardware keystrokes - it establishes the needed engine event hooks and methods used to fully handle and preprocess their keystroke data for further use later in the keystroke lifecycle. -The bulk of DOM key events trigger keystroke processing on key-down, though modifier keys also receive key-up handling. Key-press events are handled selectively for held backspaces and possibly certain keystrokes for mnemonic keyboards. In all cases, DOM keyboard event objects are preprocessed by the centralized `preprocessKeyboardEvent` method, which converts the DOM event format into Web's `KeyEvent` format, which is the form required by the keyboard rules within compiled JS keyboards. This includes mnemonic keystroke preprocessing and remapping in addition to AltGr emulation. +The bulk of DOM key events trigger keystroke processing on key-down, though modifier keys also receive key-up handling. Key-press events are handled selectively for held backspaces and possibly certain keystrokes for mnemonic keyboards. In all cases, DOM keyboard event objects are preprocessed by the centralized `preprocessKeyboardEvent` method, which converts the DOM event [`KeyboardEvent`](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent) format into the Web engine's `KeyEvent` format, which is the form required by the keyboard rules within compiled JS keyboards. This includes mnemonic keystroke preprocessing and remapping in addition to AltGr emulation. -### `app/webview` +### `app/webview` - hardware keystrokes -The `app/webview` version of the engine, which is designed to be used while embedded in a platform-specific host app, does not have direct access to standard hardware keystroke events. It's run in a WebView that does not take input - a WebView owned by the host app. It is the responsibility of the host app to handle hardware keystroke events and preprocess them on behalf of the Web engine, then forward them to the Web engine via a carefully-constructed JS call from the host upon the WebView. The `PassthroughKeyboard` class within `app/webview` space provides the method `raiseKeyEvent` as an internal API for this purpose, which converts the mobile-app format for hardware keystroke into the internal `KeyEvent` format. This includes mnemonic keystroke processing and remapping. +The `app/webview` version of the engine, which is designed to be used while embedded in a platform-specific host app, does not have direct access to standard hardware keystroke events, as those are handled by the host app's OS and by native code handlers run outside the host app's WebView containing the app/webview Web engine. It is the responsibility of the host app to handle hardware keystroke events and preprocess them on behalf of the Web engine, then forward them to the Web engine via JS call into the WebView. The `PassthroughKeyboard` class within `app/webview` space provides the method `raiseKeyEvent` as an internal API for this purpose, which converts the mobile-app format for hardware keystroke into the internal `KeyEvent` format. `raiseKeyEvent` also handles mnemonic keystroke processing and remapping. + +Also note that this variant does not model the user's text context with Web elements - it is entirely managed through the `Mock` type. ### On-screen keyboard @@ -29,7 +43,7 @@ For both `app/browser` and `app/webview`, the on-screen keyboard delegates mouse OSK keystroke preprocessing operates a little differently from hardware keystrokes. The `ActiveLayout` object for the current form-factor of the `Keyboard` maintains a "base" `KeyEvent` object, per key, that is lazy-constructed (by the `.baseKeyEvent` property) when first needed - the meat of which is performed by the `ActiveKeyBase.constructBaseKeyEvent` method. This is only evaluated up to once per key per activation of the keyboard. As keystrokes are received during OSK use, `VisualKeyboard.keyEventFromSpec` calls the `Keyboard.constructKeyEvent` method to clone that base `KeyEvent` object for the incoming keystroke and then adjust it to match current modifier and state-key settings. -### Final steps +### Passing `KeyEvent` on for processing Regardless of the path taken to generate the `KeyEvent` object, _all_ keystroke handling modules of Keyman Engine for Web then raise that `KeyEvent` object via their `keyevent` event as specified by the `KeyEventSourceInterface` type. This event also permits a callback that is used by the final phase of the lifecycle - keystroke resolution - as needed. The main `KeymanEngine` base class listens for these events and forwards them for next phase of the lifecycle - keystroke processing - to the `InputProcessor` module, which passes control to whichever `KeystrokeProcessor` type is active for the keyboard when appropriate. @@ -47,7 +61,7 @@ Once this phase is reached, the engine will then snapshot the current state of t ### Determining direct keystroke effects -The `KeyboardProcessor` classes are responsible for determining the effects that should arise when evaluating the incoming keystroke with the current context state. While the exact mechanisms of this may vary depending upon the type of keyboard, the role is the same - interpreting the keystroke in context. +The `KeyboardProcessor` classes, which each embody how one keyboard specification pattern interprets keystrokes, are responsible for determining the effects that should arise when evaluating the incoming keystroke with the current context state. While the exact mechanisms of this may vary depending upon the type of keyboard - be it JS, KMX, or KMX+ (LDML), the role is the same - interpreting the keystroke in context. ### JS keyboards From 62240c8b4650df8413c4f88e80865b1d4ecbb274 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Mon, 5 May 2025 13:45:47 +0700 Subject: [PATCH 25/57] docs(web): applies 80-char line wrap --- web/docs/internal/keystroke-lifecycle.md | 183 +++++++++++++++++++---- 1 file changed, 155 insertions(+), 28 deletions(-) diff --git a/web/docs/internal/keystroke-lifecycle.md b/web/docs/internal/keystroke-lifecycle.md index 9f520be3e4..2e0b37818d 100644 --- a/web/docs/internal/keystroke-lifecycle.md +++ b/web/docs/internal/keystroke-lifecycle.md @@ -7,27 +7,48 @@ The phases of Keyman Engine for Web keystroke processings are as follows: 3. Keystroke post-processing: keystroke post-keystroke evaluation + side-effects 4. Keystroke resolution: UI state updating -Keyman Engine for Web currently has two different builds, each used in specific contexts: +Keyman Engine for Web currently has two different builds, each used in specific +contexts: * app/browser - for direct use on a page or site within a web browser * app/webview - for integration with a host app, such as Keyman itself -The overall phases for the keystroke lifecycle are the same for both; the implementation is merely a bit different for each within specific phases. These differences are documented after the common structure and patterns for each phase. +The overall phases for the keystroke lifecycle are the same for both; the +implementation is merely a bit different for each within specific phases. These +differences are documented after the common structure and patterns for each +phase. -Also note that Keyman Engine for Web supports keystroke processing for different keyboard specification formats: +Also note that Keyman Engine for Web supports keystroke processing for different +keyboard specification formats: - JS - KMX (via web-core) - KMX+ / LDML (via web-core) -The `KeyboardProcessor` classes each handle keystroke processing for one specification format while adhering to a common interface exposed and accessible to the other layers of the keystroke lifecycle. +The `KeyboardProcessor` classes each handle keystroke processing for one +specification format while adhering to a common interface exposed and accessible +to the other layers of the keystroke lifecycle. ## Keystroke pre-processing -Both the `app/browser` and `app/webview` products are capable of handling keystrokes from the on-screen keyboard as well as hardware keystrokes. For hardware keystrokes, this varies between the two, while the majority of on-screen keyboard keystrokes are handled identically. +Both the `app/browser` and `app/webview` products are capable of handling +keystrokes from the on-screen keyboard as well as hardware keystrokes. For +hardware keystrokes, this varies between the two, while the majority of +on-screen keyboard keystrokes are handled identically. ### `app/browser` - hardware keystrokes -The `app/browser` version of the engine is designed to integrate with the active page of the user's browser. As a result of this, contexts for text manipulation are directly implemented within Web elements that the engine has direct access to. It can thus attach DOM event handlers (for [`keydown`](https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event), [`keyup`](https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event), and [`keypress`](https://developer.mozilla.org/en-US/docs/Web/API/Element/keypress_event)) in order to process hardware keystrokes. Its `HardwareEventKeyboard` class is the primary module for handling hardware keystrokes - it establishes the needed engine event hooks and methods used to fully handle and preprocess their keystroke data for further use later in the keystroke lifecycle. +The `app/browser` version of the engine is designed to integrate with the active +page of the user's browser. As a result of this, contexts for text manipulation +are directly implemented within Web elements that the engine has direct access +to. It can thus attach DOM event handlers (for +[`keydown`](https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event), +[`keyup`](https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event), +and +[`keypress`](https://developer.mozilla.org/en-US/docs/Web/API/Element/keypress_event)) +in order to process hardware keystrokes. Its `HardwareEventKeyboard` class is +the primary module for handling hardware keystrokes - it establishes the needed +engine event hooks and methods used to fully handle and preprocess their +keystroke data for further use later in the keystroke lifecycle. The bulk of DOM key events trigger keystroke processing on key-down, though modifier keys also receive key-up handling. Key-press events are handled selectively for held backspaces and possibly certain keystrokes for mnemonic keyboards. In all cases, DOM keyboard event objects are preprocessed by the centralized `preprocessKeyboardEvent` method, which converts the DOM event [`KeyboardEvent`](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent) format into the Web engine's `KeyEvent` format, which is the form required by the keyboard rules within compiled JS keyboards. This includes mnemonic keystroke preprocessing and remapping in addition to AltGr emulation. @@ -39,66 +60,172 @@ Also note that this variant does not model the user's text context with Web elem ### On-screen keyboard -For both `app/browser` and `app/webview`, the on-screen keyboard delegates mouse and touch processing to [our internal gesture engine](./gestures/index.md) for most keyboards. (Keyboards that instead display "help pages", such as `sil_euro_latin` on desktop, have specialized handling.) The gesture engine is responsible for interpreting all DOM mouse and touch events for OSKs based on the touch-layout format, which are managed by the `VisualKeyboard` class. The gesture engine will raise events about the gesture lifecycle that, when appropriate, will emit `KeyElement` instances - elements of the constructed OSK corresponding to elements of the OSK directly representing keyboard keys. +For both `app/browser` and `app/webview`, the on-screen keyboard delegates mouse +and touch processing to [our internal gesture engine](./gestures/index.md) for +most keyboards. (Keyboards that instead display "help pages", such as +`sil_euro_latin` on desktop, have specialized handling.) The gesture engine is +responsible for interpreting all DOM mouse and touch events for OSKs based on +the touch-layout format, which are managed by the `VisualKeyboard` class. The +gesture engine will raise events about the gesture lifecycle that, when +appropriate, will emit `KeyElement` instances - elements of the constructed OSK +corresponding to elements of the OSK directly representing keyboard keys. -OSK keystroke preprocessing operates a little differently from hardware keystrokes. The `ActiveLayout` object for the current form-factor of the `Keyboard` maintains a "base" `KeyEvent` object, per key, that is lazy-constructed (by the `.baseKeyEvent` property) when first needed - the meat of which is performed by the `ActiveKeyBase.constructBaseKeyEvent` method. This is only evaluated up to once per key per activation of the keyboard. As keystrokes are received during OSK use, `VisualKeyboard.keyEventFromSpec` calls the `Keyboard.constructKeyEvent` method to clone that base `KeyEvent` object for the incoming keystroke and then adjust it to match current modifier and state-key settings. +OSK keystroke preprocessing operates a little differently from hardware +keystrokes. The `ActiveLayout` object for the current form-factor of the +`Keyboard` maintains a "base" `KeyEvent` object, per key, that is +lazy-constructed (by the `.baseKeyEvent` property) when first needed - the meat +of which is performed by the `ActiveKeyBase.constructBaseKeyEvent` method. This +is only evaluated up to once per key per activation of the keyboard. As +keystrokes are received during OSK use, `VisualKeyboard.keyEventFromSpec` calls +the `Keyboard.constructKeyEvent` method to clone that base `KeyEvent` object for +the incoming keystroke and then adjust it to match current modifier and +state-key settings. ### Passing `KeyEvent` on for processing -Regardless of the path taken to generate the `KeyEvent` object, _all_ keystroke handling modules of Keyman Engine for Web then raise that `KeyEvent` object via their `keyevent` event as specified by the `KeyEventSourceInterface` type. This event also permits a callback that is used by the final phase of the lifecycle - keystroke resolution - as needed. The main `KeymanEngine` base class listens for these events and forwards them for next phase of the lifecycle - keystroke processing - to the `InputProcessor` module, which passes control to whichever `KeystrokeProcessor` type is active for the keyboard when appropriate. +Regardless of the path taken to generate the `KeyEvent` object, _all_ keystroke +handling modules of Keyman Engine for Web then raise that `KeyEvent` object via +their `keyevent` event as specified by the `KeyEventSourceInterface` type. This +event also permits a callback that is used by the final phase of the lifecycle - +keystroke resolution - as needed. The main `KeymanEngine` base class listens +for these events and forwards them for next phase of the lifecycle - keystroke +processing - to the `InputProcessor` module, which passes control to whichever +`KeystrokeProcessor` type is active for the keyboard when appropriate. ## Keystroke processing -Once the `KeyEvent` object for a keystroke has been passed into the `InputProcessor` module and its `processKeyEvent` method, the keystroke-processing stage has been reached. There are a number of subprocesses that trigger here in sequence - keystrokes don't go _straight_ to evaluation against keyboard rules. +Once the `KeyEvent` object for a keystroke has been passed into the +`InputProcessor` module and its `processKeyEvent` method, the +keystroke-processing stage has been reached. There are a number of subprocesses +that trigger here in sequence - keystrokes don't go _straight_ to evaluation +against keyboard rules. ### Pre-keystroke state management -First, the engine checks the keyboard associated with the `KeyEvent`, ensuring that it is still in place. (See #7543 for more details.) With that assertion in place, it then performs a check needed to support multitaps - it checks to see if the key event has an associated "base context" and reverts the current context to match it if so. Once those checks are fulfilled, the engine then checks to see if the key event corresponds to a pure layer-switching or modifier/state-key interaction. If those are detected, rule-evaluation is bypassed. +First, the engine checks the keyboard associated with the `KeyEvent`, ensuring +that it is still in place. (See #7543 for more details.) With that assertion +in place, it then performs a check needed to support multitaps - it checks to +see if the key event has an associated "base context" and reverts the current +context to match it if so. Once those checks are fulfilled, the engine then +checks to see if the key event corresponds to a pure layer-switching or +modifier/state-key interaction. If those are detected, rule-evaluation is +bypassed. -On a similar note, backspace and spacebar keystrokes receive special handling next in associated with predictive-text functionality. When autocorrect is enabled, the spacebar in particular can be used to accept the current suggestion instead of acting as whitespace; if this is triggered, its `KeyEvent` will be swallowed - no rule processing will occur for the it. The backspace may trigger display of a "reversion" suggestion when applicable but will not be swallowed. +On a similar note, backspace and spacebar keystrokes receive special handling +next in associated with predictive-text functionality. When autocorrect is +enabled, the spacebar in particular can be used to accept the current suggestion +instead of acting as whitespace; if this is triggered, its `KeyEvent` will be +swallowed - no rule processing will occur for the it. The backspace may trigger +display of a "reversion" suggestion when applicable but will not be swallowed. -Once this phase is reached, the engine will then snapshot the current state of the context, then trigger standard rule processing against the original context by calling the current `KeyboardProcessor`'s `processKeystroke` method. Any operations against the context will be persisted and take full effect; DOM input elements (for `app/browser`) are updated during rule evaluation. +Once this phase is reached, the engine will then snapshot the current state of +the context, then trigger standard rule processing against the original context +by calling the current `KeyboardProcessor`'s `processKeystroke` method. Any +operations against the context will be persisted and take full effect; DOM input +elements (for `app/browser`) are updated during rule evaluation. ### Determining direct keystroke effects -The `KeyboardProcessor` classes, which each embody how one keyboard specification pattern interprets keystrokes, are responsible for determining the effects that should arise when evaluating the incoming keystroke with the current context state. While the exact mechanisms of this may vary depending upon the type of keyboard - be it JS, KMX, or KMX+ (LDML), the role is the same - interpreting the keystroke in context. +The `KeyboardProcessor` classes, which each embody how one keyboard +specification pattern interprets keystrokes, are responsible for determining the +effects that should arise when evaluating the incoming keystroke with the +current context state. While the exact mechanisms of this may vary depending +upon the type of keyboard - be it JS, KMX, or KMX+ (LDML), the role is the same +- interpreting the keystroke in context. ### JS keyboards -Before proceeding further, `KeyboardProcessor` does a context check to see whether or not the context contains anything considered deletable - in the case of a BKSP, we need to ensure that the keystroke passes through to the engine's host cleanly, as it may have special implications for the site or host app. +Before proceeding further, `KeyboardProcessor` does a context check to see +whether or not the context contains anything considered deletable - in the case +of a BKSP, we need to ensure that the keystroke passes through to the engine's +host cleanly, as it may have special implications for the site or host app. -With that out of the way, the JS keyboard's main group is then provided with the `KeyEvent` object in order to evaluate the keyboard's rules against the keystroke. This involves constructing a `RuleBehavior` object to track any and all needed side-effects for the keystroke. Such changes are generally not applied to the engine at large at this time in order to prevent unwanted side effects that may arise to and from predictive text operations that follow shortly afterward. +With that out of the way, the JS keyboard's main group is then provided with the +`KeyEvent` object in order to evaluate the keyboard's rules against the +keystroke. This involves constructing a `RuleBehavior` object to track any and +all needed side-effects for the keystroke. Such changes are generally not +applied to the engine at large at this time in order to prevent unwanted side +effects that may arise to and from predictive text operations that follow +shortly afterward. -The `KeyboardInterface` class defines the internal API used by keyboards for their evaluation of keyboard rules. +The `KeyboardInterface` class defines the internal API used by keyboards for +their evaluation of keyboard rules. -Once the keyboard's script returns control to the main engine, the engine then determines the net effects to the context that resulted from applying the keyboard rule and preserves that as a `Transcription`, part of includes a `Transform` that most directly represents the changes to text surrounding the text insertion point. +Once the keyboard's script returns control to the main engine, the engine then +determines the net effects to the context that resulted from applying the +keyboard rule and preserves that as a `Transcription`, part of includes a +`Transform` that most directly represents the changes to text surrounding the +text insertion point. -For JS keyboards, if no keyboard rule is defined for a non-frame key on the `default` or `shift` layer, there is an additional set of implied "default" keyboard rules that is applied. (A keyboard's source must _explicitly_ specify to not emit anything for such keys if such an outcome is desired.) This occurs regardless of the keystroke's source, as such effects are necessary to incorporate for predictive-text operations. If no such rule exists, the processor will add a note to the `RuleBehavior` object that default processing could not be provided and is thus needed from the engine's host. +For JS keyboards, if no keyboard rule is defined for a non-frame key on the +`default` or `shift` layer, there is an additional set of implied "default" +keyboard rules that is applied. (A keyboard's source must _explicitly_ specify +to not emit anything for such keys if such an outcome is desired.) This occurs +regardless of the keystroke's source, as such effects are necessary to +incorporate for predictive-text operations. If no such rule exists, the +processor will add a note to the `RuleBehavior` object that default processing +could not be provided and is thus needed from the engine's host. ### KMX keyboards & KMX+ (LDML) keyboards -For KMX and KMX+ keyboards, keystrokes are evaluated by using the embedded WASM version of Keyman Core. +For KMX and KMX+ keyboards, keystrokes are evaluated by using the embedded WASM +version of Keyman Core. TODO: add link to specific mechanisms here once available. ### "Alternate" processing (predictive-text) -Once the incoming `KeyEvent` has been processed, if predictive-text is active and the `KeyEvent` includes fat-finger oriented data, the engine will then build a set of "alternates" - of "phantom" keystrokes - and process _them_ against headless clones of the original context in the same manner as the original keystroke. +Once the incoming `KeyEvent` has been processed, if predictive-text is active +and the `KeyEvent` includes fat-finger oriented data, the engine will then build +a set of "alternates" - of "phantom" keystrokes - and process _them_ against +headless clones of the original context in the same manner as the original +keystroke. -Once all relevant "alternates" have been evaluated, the engine will then signal the predictive-text engine with all relevant data, including the original, snapshotted state of the context. It does not actually trigger predictive-text at this time; processing of alternates is done before keystroke post-processing in order to avoid cross-effects from JS-keyboard variable store manipulations and similar mechanisms. Fat-finger "alternate" `KeyEvent`s are evaluated as if they occurred under the exact same conditions as the keystroke that was actually detected. +Once all relevant "alternates" have been evaluated, the engine will then signal +the predictive-text engine with all relevant data, including the original, +snapshotted state of the context. It does not actually trigger predictive-text +at this time; processing of alternates is done before keystroke post-processing +in order to avoid cross-effects from JS-keyboard variable store manipulations +and similar mechanisms. Fat-finger "alternate" `KeyEvent`s are evaluated as if +they occurred under the exact same conditions as the keystroke that was actually +detected. ### Keystroke post-processing -At this stage, the side-effects desired for the original keystroke, as saved to its `RuleBehavior`, are then applied. Note that this includes changes to the `&layer` store - this update will also trigger an event that updates the state of the OSK to match the desired layer. +At this stage, the side-effects desired for the original keystroke, as saved to +its `RuleBehavior`, are then applied. Note that this includes changes to the +`&layer` store - this update will also trigger an event that updates the state +of the OSK to match the desired layer. -Once that is done, the engine will then save data relevant to the original context state, the `KeyEvent`, and the `RuleBehavior` to the "context cache" supporting multitap context reversion. These effects include layer-change effects that result from JS keyboard rules, which modify the KMN-style keyboard stores `&oldlayer` and `&newlayer` in preparation for `begin PostKeystroke` group processing, which is then executed (and which can trigger another `&layer` & OSK-layer update). +Once that is done, the engine will then save data relevant to the original +context state, the `KeyEvent`, and the `RuleBehavior` to the "context cache" +supporting multitap context reversion. These effects include layer-change +effects that result from JS keyboard rules, which modify the KMN-style keyboard +stores `&oldlayer` and `&newlayer` in preparation for `begin PostKeystroke` +group processing, which is then executed (and which can trigger another `&layer` +& OSK-layer update). -Once post-keystroke effects have been determined, the engine then signals predictive-text to generate new predictions associated with the keystroke. For `app/browser` variants of the engine, changes to the context will then also trigger the DOM `input` event on the context's element in case third parties wish to leverage such events for their website's pages. +Once post-keystroke effects have been determined, the engine then signals +predictive-text to generate new predictions associated with the keystroke. For +`app/browser` variants of the engine, changes to the context will then also +trigger the DOM `input` event on the context's element in case third parties +wish to leverage such events for their website's pages. ### Keystroke resolution -At this stage, `InputProcessor` passes control back to the main `KeymanEngine` module, which then triggers the "on rule finalization" setting if configured. This setting is mostly used for page-integration within `app/browser`, supporting DOM element `change` event emulation whenever focus shifts away from the active context element. +At this stage, `InputProcessor` passes control back to the main `KeymanEngine` +module, which then triggers the "on rule finalization" setting if configured. +This setting is mostly used for page-integration within `app/browser`, +supporting DOM element `change` event emulation whenever focus shifts away from +the active context element. -For OSK keystrokes, an identifier associated with the `KeyEvent`'s context snapshot will be made accessible through the `keyevent` event's callback parameter - a feature utilized by multitap gesture support. +For OSK keystrokes, an identifier associated with the `KeyEvent`'s context +snapshot will be made accessible through the `keyevent` event's callback +parameter - a feature utilized by multitap gesture support. -For hardware-keyboard keystrokes, the `keyevent` callback is used to determine whether or not native handling for the keystroke should be triggered - such as for TAB and ENTER keys, which may have semantic command-like functionality depending on the state of the Web engine's host - be that a web page or an Android/iOS app utilizing the keyboard. ENTER keys are often used to submit forms, and this helps ensure we trigger such functionality when appropriate. \ No newline at end of file +For hardware-keyboard keystrokes, the `keyevent` callback is used to determine +whether or not native handling for the keystroke should be triggered - such as +for TAB and ENTER keys, which may have semantic command-like functionality +depending on the state of the Web engine's host - be that a web page or an +Android/iOS app utilizing the keyboard. ENTER keys are often used to submit +forms, and this helps ensure we trigger such functionality when appropriate. \ No newline at end of file From dd77c268fc38dbf86ccf9194604fcb4f611e863e Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Mon, 5 May 2025 15:01:33 +0700 Subject: [PATCH 26/57] docs(web): add keystroke-lifecycle sequence diagram --- web/docs/internal/keystroke-lifecycle.md | 70 ++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/web/docs/internal/keystroke-lifecycle.md b/web/docs/internal/keystroke-lifecycle.md index 2e0b37818d..8c71b90e7f 100644 --- a/web/docs/internal/keystroke-lifecycle.md +++ b/web/docs/internal/keystroke-lifecycle.md @@ -28,6 +28,76 @@ The `KeyboardProcessor` classes each handle keystroke processing for one specification format while adhering to a common interface exposed and accessible to the other layers of the keystroke lifecycle. +```mermaid +--- +title: Keystroke lifecycle flowchart +--- +%% For rendering, use e.g. https://mermaid.live +%%{init: {"flowchart": {"htmlLabels": false}} }%% +sequenceDiagram; + +actor User as User + UI +participant Keystroke interpreter + +Note over User, KeymanEngine: Start: Keystroke preprocessing +User ->> Keystroke interpreter: Types a key +Keystroke interpreter ->> Keystroke interpreter: Preprocess keystroke events +Keystroke interpreter ->> KeymanEngine: Raise preprocessed event +Note over User, KeymanEngine: End: Keystroke preprocessing +KeymanEngine ->>+ InputProcessor: Forward keystroke data + +Note over InputProcessor, KeyboardProcessor: Start: Keystroke processing +InputProcessor ->> InputProcessor: Validate context, keyboard +InputProcessor ->> InputProcessor: Snapshot context state + +InputProcessor ->>+ KeyboardProcessor: Process keystroke +KeyboardProcessor ->> KeyboardProcessor: Determine effects +KeyboardProcessor -->> User: Update raw context +KeyboardProcessor ->>- InputProcessor: Return effects + +opt Predictive Text + loop For each nearby key + InputProcessor ->>+ KeyboardProcessor: Fat-finger (alternate) keystrokes + KeyboardProcessor ->> KeyboardProcessor: Determine effects + KeyboardProcessor ->>- InputProcessor: Return effects + end +end + +Note over InputProcessor, KeyboardProcessor: End: Keystroke processing +Note over InputProcessor, KeyboardProcessor: Start: Keystroke post-processing + +InputProcessor ->> InputProcessor: Apply keystroke effects +InputProcessor ->> InputProcessor: Cache context state, keystroke effects +InputProcessor -->> User: Update OSK layer +InputProcessor ->>+ KeyboardProcessor: Process post-keystroke effects +KeyboardProcessor ->>- InputProcessor: Return effects +InputProcessor -->> User: Update OSK layer + +opt Predictive Text + InputProcessor --)+ Predictive-text engine: Request corrections, predictions + InputProcessor -->> User: Invalidate outdated predictions +end + +Note over InputProcessor, KeyboardProcessor: End: Keystroke post-processing + +opt app/browser + InputProcessor ->> InputProcessor: Trigger DOM `input` event +end + +Note over Keystroke interpreter, InputProcessor: Start: Keystroke resolution +InputProcessor ->>- KeymanEngine: Return effects + +KeymanEngine ->> Keystroke interpreter: Store state token for multitaps +KeymanEngine ->> Keystroke interpreter: Determine TAB, ENTER, etc effects +Note over Keystroke interpreter, InputProcessor: End: Keystroke resolution + +opt Predictive Text + Predictive-text engine ->> Predictive-text engine: Determine corrections,
predictions (async) + Note over User, Predictive-text engine: After async delay + Predictive-text engine --)- User: Return new predictions, update banner +end +``` + ## Keystroke pre-processing Both the `app/browser` and `app/webview` products are capable of handling From c95cb5f0c24bb801928bb03ab345831a246ec74e Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Mon, 5 May 2025 19:38:55 +0200 Subject: [PATCH 27/57] maint(common): output script identifier in front of block name --- resources/builder.inc.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/builder.inc.sh b/resources/builder.inc.sh index 7d1f973e14..860bab6865 100755 --- a/resources/builder.inc.sh +++ b/resources/builder.inc.sh @@ -205,7 +205,7 @@ builder_echo() { message="$*" if [[ "${action}" == "start" ]] && ${is_running_on_teamcity}; then - echo -e "##teamcity[blockOpened name='${block}']" + echo -e "##teamcity[blockOpened name='|[${THIS_SCRIPT_IDENTIFIER}|] ${block}']" fi if ${do_output}; then @@ -235,7 +235,7 @@ builder_echo() { fi if [[ "${action}" == "end" ]] && ${is_running_on_teamcity}; then - echo -e "##teamcity[blockClosed name='${block}']" + echo -e "##teamcity[blockClosed name='|[${THIS_SCRIPT_IDENTIFIER}|] ${block}']" fi } From 9976af6f6c598da0851132c760e21641aa3b2f2b Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Tue, 6 May 2025 08:18:42 +0700 Subject: [PATCH 28/57] docs(web): tweak comment per review Co-authored-by: Eberhard Beilharz --- web/src/engine/osk/src/views/oskView.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/engine/osk/src/views/oskView.ts b/web/src/engine/osk/src/views/oskView.ts index 961a246d08..876719017a 100644 --- a/web/src/engine/osk/src/views/oskView.ts +++ b/web/src/engine/osk/src/views/oskView.ts @@ -525,7 +525,7 @@ export default abstract class OSKView // Addresses issue with touch-layouts specifying a unitless fontsize; this // coerces them to `pt` style sizing, like how word-processors present font-size. // - // Returns NaN if not 100% a number. "12px", "12pt", "12%" all return NaN. + // Number() returns NaN if not 100% a number. "12px", "12pt", "12%" all return NaN. const fsRaw = Number(layerFontSizeRaw); const layerFontSize = isNaN(fsRaw) ? layerFontSizeRaw : (fsRaw + 'pt'); From 7d5a83633d8db65281b52c5e569c41708842ec2f Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Tue, 6 May 2025 11:29:31 +0700 Subject: [PATCH 29/57] fix(web): fix var declaration affected by linter strictness + length-style fix Test-bot: skip --- web/src/engine/osk/src/lengthStyle.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/engine/osk/src/lengthStyle.ts b/web/src/engine/osk/src/lengthStyle.ts index c008b5c51a..f0f9830fdb 100644 --- a/web/src/engine/osk/src/lengthStyle.ts +++ b/web/src/engine/osk/src/lengthStyle.ts @@ -10,7 +10,7 @@ export class ParsedLengthStyle implements LengthStyle { public readonly special: 'em' | 'rem'; public constructor(style: LengthStyle | string) { - const parsed: LengthStyle = (typeof style == 'string') ? ParsedLengthStyle.parseLengthStyle(style) : style; + let parsed: LengthStyle = (typeof style == 'string') ? ParsedLengthStyle.parseLengthStyle(style) : style; const fallback: LengthStyle = { val: 1, // 100% From e2fe3861aa0a583536b9fa8adac6b03c724a160f Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Tue, 6 May 2025 13:56:02 +0700 Subject: [PATCH 30/57] maint(common): builder_release -> is_release, other review concerns Co-authored-by: Marc Durdin --- resources/builder.inc.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/resources/builder.inc.sh b/resources/builder.inc.sh index f72206e9b9..2fac674236 100755 --- a/resources/builder.inc.sh +++ b/resources/builder.inc.sh @@ -1048,7 +1048,7 @@ _builder_get_default_description() { :module) description="this module" ;; :tools) description="build tools for this project" ;; --debug) description="debug build" ;; - --release) description="release build" ;; + --release) description="release build (prevents --debug in local-env builds)" ;; esac echo "$description" } @@ -1270,7 +1270,7 @@ _builder_parse_expanded_parameters() { _builder_build_deps=--deps builder_verbose= builder_debug= - local builder_release= + local is_release= local _params=($@) _builder_chosen_action_targets=() _builder_chosen_options=() @@ -1387,15 +1387,15 @@ _builder_parse_expanded_parameters() { _builder_chosen_options+=(--verbose) builder_verbose=--verbose ;; - --debug|-d) + --debug) _builder_chosen_options+=(--debug) builder_debug=--debug ;; - --release|-r) + --release) _builder_chosen_options+=(--release) # As of #13827, this is only checked when detecting if --debug should be auto-applied. # There is no `builder_is_release_build` function yet. - builder_release=--release + is_release=--release ;; --deps|--no-deps|--force-deps) _builder_build_deps=$key @@ -1484,7 +1484,7 @@ _builder_parse_expanded_parameters() { # Per #11106, local builds use --debug by default. # Second condition prevents the block (and message) from executing when --debug is already specified explicitly. - if [[ $VERSION_ENVIRONMENT == "local" ]] && [[ $builder_debug != --debug ]] && [[ $builder_release != --release ]]; then + if [[ $VERSION_ENVIRONMENT == "local" ]] && [[ $builder_debug != --debug ]] && [[ $is_release != --release ]]; then builder_echo grey "Local build environment detected: setting --debug" _params+=(--debug) _builder_chosen_options+=(--debug) From 9b2d21ff2d582fb840f6181dfe8510a766b9da83 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Tue, 6 May 2025 13:58:20 +0700 Subject: [PATCH 31/57] maint(common): use booleans, not strings for is_release Co-authored-by: Marc Durdin --- resources/builder.inc.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/builder.inc.sh b/resources/builder.inc.sh index 2fac674236..43f09fa474 100755 --- a/resources/builder.inc.sh +++ b/resources/builder.inc.sh @@ -1270,7 +1270,7 @@ _builder_parse_expanded_parameters() { _builder_build_deps=--deps builder_verbose= builder_debug= - local is_release= + local is_release=false local _params=($@) _builder_chosen_action_targets=() _builder_chosen_options=() @@ -1395,7 +1395,7 @@ _builder_parse_expanded_parameters() { _builder_chosen_options+=(--release) # As of #13827, this is only checked when detecting if --debug should be auto-applied. # There is no `builder_is_release_build` function yet. - is_release=--release + is_release=true ;; --deps|--no-deps|--force-deps) _builder_build_deps=$key @@ -1484,7 +1484,7 @@ _builder_parse_expanded_parameters() { # Per #11106, local builds use --debug by default. # Second condition prevents the block (and message) from executing when --debug is already specified explicitly. - if [[ $VERSION_ENVIRONMENT == "local" ]] && [[ $builder_debug != --debug ]] && [[ $is_release != --release ]]; then + if [[ $VERSION_ENVIRONMENT == "local" ]] && [[ $builder_debug != --debug ]] && ! $is_release; then builder_echo grey "Local build environment detected: setting --debug" _params+=(--debug) _builder_chosen_options+=(--debug) From a58bf6fb304f33af95ca0d11c6057ccf10ee9464 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Tue, 6 May 2025 15:47:52 +0700 Subject: [PATCH 32/57] chore(android): Update inuktitut_pirurvik to 1.4.1 --- oem/firstvoices/keyboards.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oem/firstvoices/keyboards.csv b/oem/firstvoices/keyboards.csv index ed13eb5aaa..5628d4f9b1 100644 --- a/oem/firstvoices/keyboards.csv +++ b/oem/firstvoices/keyboards.csv @@ -1,6 +1,6 @@ Shortname,ID,Name,Region,9.0 Web Keyboard,Version,Language ID,Language Name fv,fv_inuvialuktun,Inuvialuktun,Arctic,fv_inuvialuktun_kmw-9.0.js,9.1.1,ikt-Latn,Inuinnaqtun (Latin) -i,inuktitut_pirurvik,Kiputtijjut | ᑭᐳᑦᑎᔾᔪᑦ,Arctic,inuktitut_pirurvik-1.1.js,1.4,ike-Cans,Eastern Canadian Inuktitut (Unified Canadian Aboriginal Syllabics) +i,inuktitut_pirurvik,Kiputtijjut | ᑭᐳᑦᑎᔾᔪᑦ,Arctic,inuktitut_pirurvik-1.1.js,1.4.1,ike-Cans,Eastern Canadian Inuktitut (Unified Canadian Aboriginal Syllabics) i,inuktitut_latin,Qaliujaaqpait | ᖃᓕᐅᔮᖅᐸᐃᑦ,Arctic,inuktitut_latin-1.1.js,1.4,ike-Latn,Eastern Canadian Inuktitut (Latin) i,inuktitut_naqittaut,Qaniujaaqpait | ᖃᓂᐅᔮᖅᐸᐃᑦ,Arctic,inuktitut_naqittaut-1.3.js,1.6,ike-Cans,Eastern Canadian Inuktitut (Unified Canadian Aboriginal Syllabics) fv,fv_uummarmiutun,Uummarmiutun,Arctic,fv_uummarmiutun_kmw-9.0.js,9.1.1,ikt-Latn,Inuinnaqtun (Latin) From cf93da452faa62a9fcf3b2bf7c0a7532e38f2c07 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 6 May 2025 11:46:48 +0200 Subject: [PATCH 33/57] maint(linux): add clarifying comment on why different TEAMCITY variables --- linux/keyman-config/run-tests.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/linux/keyman-config/run-tests.sh b/linux/keyman-config/run-tests.sh index 337ebe8bbc..ee8a549b69 100755 --- a/linux/keyman-config/run-tests.sh +++ b/linux/keyman-config/run-tests.sh @@ -19,6 +19,11 @@ if [[ -n "${TEAMCITY_VERSION}" ]]; then # to use a virtualenv. However, that causes other problems, so we # override this check only if we're running in a TC agent or docker # so that we don't accidentally break the local system. + # Note: it is intentional that we use TEAMCITY_VERSION as well + # as TEAMCITY_PLATFORM here so that it is possible to simulate + # running in a TC agent and still not break your local system + # (run in a docker container or explicitly set TEAMCITY_PLATFORM + # to cause the script to install the package). PIP_ARGS="--break-system-packages" fi # shellcheck disable=SC2086 From 397b5bdf93ff511b61a3a4cd5a69177de2706234 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 6 May 2025 11:49:59 +0200 Subject: [PATCH 34/57] maint(linux): streamline use of env variables to detect running on TC This changes the variable we use to detect if we're running on TC to be the same as the one used on #13810. --- linux/keyman-config/run-tests.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/keyman-config/run-tests.sh b/linux/keyman-config/run-tests.sh index ee8a549b69..3fa49f081d 100755 --- a/linux/keyman-config/run-tests.sh +++ b/linux/keyman-config/run-tests.sh @@ -12,14 +12,14 @@ if [[ "$1" == "--coverage" ]]; then coverage="-m coverage run --source=. --data-file=build/.coverage" fi -if [[ -n "${TEAMCITY_VERSION}" ]]; then +if [[ -n "${TEAMCITY_GIT_PATH}" ]]; then if ! pip3 list --format=columns | grep -q teamcity-messages; then if [[ -n "${TEAMCITY_PLATFORM}" ]] || [[ -n "${DOCKER_RUNNING}" ]]; then # Ubuntu 24.04+ prevents mixing pip and system packages and wants us # to use a virtualenv. However, that causes other problems, so we # override this check only if we're running in a TC agent or docker # so that we don't accidentally break the local system. - # Note: it is intentional that we use TEAMCITY_VERSION as well + # Note: it is intentional that we use TEAMCITY_GIT_PATH as well # as TEAMCITY_PLATFORM here so that it is possible to simulate # running in a TC agent and still not break your local system # (run in a docker container or explicitly set TEAMCITY_PLATFORM From 5bc7c22f80e3bf6cd55e6325010fa5577e484f55 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 6 May 2025 12:11:10 +0200 Subject: [PATCH 35/57] change(linux): add ICU dependency needed to build on Arch Linux Co-authored-by: Nikita Moor Fixes: #13814 --- linux/ibus-keyman/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/ibus-keyman/meson.build b/linux/ibus-keyman/meson.build index 401da66004..710bcd1dac 100644 --- a/linux/ibus-keyman/meson.build +++ b/linux/ibus-keyman/meson.build @@ -18,7 +18,7 @@ conf = configuration_data() ibus = dependency('ibus-1.0', version: '>= 1.2.0') gtk = dependency('gtk+-3.0', version: '>= 2.4') json_glib = dependency('json-glib-1.0', version: '>= 1.0') -icu = dependency('icu-i18n') +icu = [dependency('icu-i18n'), dependency('icu-uc')] systemd = dependency('libsystemd', 'libelogind', required: false) if systemd.found() From b83002ca8502b09cf637b23d3c5132b03426a697 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 6 May 2025 16:22:46 +0200 Subject: [PATCH 36/57] maint(common): add `builder_is_running_on_teamcity` function Addresses code review comments. Co-authored-by: Marc Durdin --- resources/builder.inc.sh | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/resources/builder.inc.sh b/resources/builder.inc.sh index 860bab6865..db94226a93 100755 --- a/resources/builder.inc.sh +++ b/resources/builder.inc.sh @@ -1,4 +1,5 @@ #!/usr/bin/env bash +# shellcheck disable=SC2310 # Note: these two lines can be uncommented for debugging and profiling build # scripts: @@ -169,10 +170,7 @@ function builder_heading() { builder_echo() { - local color=white message= mark= block= action= do_output=true is_running_on_teamcity=false - if [[ -n "${TEAMCITY_GIT_PATH:-}" ]]; then - is_running_on_teamcity=true - fi + local color=white message= mark= block= action= do_output=true if [[ $# -gt 1 ]]; then if [[ $1 =~ ^(white|grey|green|success|blue|heading|yellow|warning|red|error|purple|brightwhite|teal|debug|setmark)$ ]]; then @@ -184,9 +182,7 @@ builder_echo() { block="$2" shift 2 color="heading" - if ${is_running_on_teamcity}; then - do_output=true - else + if ! builder_is_running_on_teamcity; then do_output=${_builder_debug_internal:-false} fi elif [[ $1 == "end" ]]; then @@ -195,16 +191,14 @@ builder_echo() { block="$2" color="$3" shift 3 - if [[ "${color}" == "error" ]] || ${is_running_on_teamcity}; then - do_output=true - else + if [[ "${color}" != "error" ]] && ! builder_is_running_on_teamcity; then do_output=${_builder_debug_internal:-false} fi fi fi message="$*" - if [[ "${action}" == "start" ]] && ${is_running_on_teamcity}; then + if [[ "${action}" == "start" ]] && builder_is_running_on_teamcity; then echo -e "##teamcity[blockOpened name='|[${THIS_SCRIPT_IDENTIFIER}|] ${block}']" fi @@ -234,7 +228,7 @@ builder_echo() { fi fi - if [[ "${action}" == "end" ]] && ${is_running_on_teamcity}; then + if [[ "${action}" == "end" ]] && builder_is_running_on_teamcity; then echo -e "##teamcity[blockClosed name='|[${THIS_SCRIPT_IDENTIFIER}|] ${block}']" fi } @@ -1693,7 +1687,7 @@ builder_finish_action() { # Sanity check: if there is a described output for this action, does the corresponding # file or directory exist now? if _builder_dep_output_defined $matched_action && ! _builder_dep_output_exists "$matched_action"; then - builder_echo end "$action_name" warning "Expected output: '${_builder_dep_path[$matched_action]}'." + builder_echo warning "Expected output: '${_builder_dep_path[$matched_action]}'." builder_echo end "$action_name" warning "## $action_name completed successfully, but output does not exist" else builder_echo end "$action_name" success "## $action_name completed successfully" @@ -2129,6 +2123,15 @@ builder_is_target_excluded_by_platform() { return 1 } +# Returns 0 if the script is running on TeamCity +builder_is_running_on_teamcity() { + if [[ -z "${TEAMCITY_GIT_PATH:-}" ]]; then + return 1 + else + return 0 + fi +} + ################################################################################ # Final initialization ################################################################################ From adace45faccb5fd6c4dc708323c7e176039ff890 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 6 May 2025 16:29:42 +0200 Subject: [PATCH 37/57] maint(common): fixed tests --- resources/build/test/test.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/resources/build/test/test.sh b/resources/build/test/test.sh index fcce015ff5..52c4a0b572 100755 --- a/resources/build/test/test.sh +++ b/resources/build/test/test.sh @@ -192,7 +192,7 @@ fi function builder_echo_tests() { echo -e "${COLOR_BLUE}## Testing builder_echo${COLOR_RESET}" _old_builder_debug_internal=${_builder_debug_internal} - _OLD_TEAMICITY_GIT_PATH=${TEAMCITY_GIT_PATH} + _OLD_TEAMICITY_GIT_PATH=${TEAMCITY_GIT_PATH:-} # regular build, no internal debug TEAMCITY_GIT_PATH="" @@ -235,20 +235,20 @@ function builder_echo_tests() { TEAMCITY_GIT_PATH="foo" # TC build, no internal debug _builder_debug_internal=false - expected="##teamcity[blockOpened name='foo'] + expected="##teamcity[blockOpened name='|[resources/build/test|] foo'] $(builder_echo heading "description")" result=$(builder_echo start "foo" "description") if [[ "${result[*]}" != "${expected}" ]]; then builder_die "FAIL: Wrong output for 'builder_echo start foo description' on TC (no debug):\n Actual : ${result[*]}\n Expected: ${expected}" fi expected="$(builder_echo success "description") -##teamcity[blockClosed name='foo']" +##teamcity[blockClosed name='|[resources/build/test|] foo']" result=$(builder_echo end "foo" success "description") if [[ "${result[*]}" != "${expected}" ]]; then builder_die "FAIL: Wrong output for 'builder_echo end foo success description' on TC (no debug):\n Actual : ${result[*]}\n Expected: ${expected}" fi expected="$(builder_echo error "description") -##teamcity[blockClosed name='foo']" +##teamcity[blockClosed name='|[resources/build/test|] foo']" result=$(builder_echo end "foo" error "description") if [[ "${result[*]}" != "${expected}" ]]; then builder_die "FAIL: Wrong output for 'builder_echo end foo error description' on TC (no debug):\n Actual : ${result[*]}\n Expected: ${expected}" @@ -256,20 +256,20 @@ $(builder_echo heading "description")" # TC build, with internal debug _builder_debug_internal=true - expected="##teamcity[blockOpened name='foo'] + expected="##teamcity[blockOpened name='|[resources/build/test|] foo'] $(builder_echo heading "description")" result=$(builder_echo start "foo" "description") if [[ "${result[*]}" != "${expected}" ]]; then builder_die "FAIL: Wrong output for 'builder_echo start foo description' on TC (debug):\n Actual : ${result[*]}\n Expected: ${expected}" fi expected="$(builder_echo success "description") -##teamcity[blockClosed name='foo']" +##teamcity[blockClosed name='|[resources/build/test|] foo']" result=$(builder_echo end "foo" success "description") if [[ "${result[*]}" != "${expected}" ]]; then builder_die "FAIL: Wrong output for 'builder_echo end foo success description' on TC (debug):\n Actual : ${result[*]}\n Expected: ${expected}" fi expected="$(builder_echo error "description") -##teamcity[blockClosed name='foo']" +##teamcity[blockClosed name='|[resources/build/test|] foo']" result=$(builder_echo end "foo" error "description") if [[ "${result[*]}" != "${expected}" ]]; then builder_die "FAIL: Wrong output for 'builder_echo end foo error description' on TC (debug):\n Actual : ${result[*]}\n Expected: ${expected}" From 460de65f0dfeb89cf400b518636b49f238fb5101 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 6 May 2025 16:34:57 +0200 Subject: [PATCH 38/57] maint(common): use same TC variable everywhere Standardize on `TEAMCITY_GIT_PATH` environment variable to detect if we're running on TeamCity. Test-bot: skip --- common/windows/delphi/general/DUnitX.Loggers.TeamCity.pas | 2 +- web/src/test/manual/web/regression-tests/test-builder.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/windows/delphi/general/DUnitX.Loggers.TeamCity.pas b/common/windows/delphi/general/DUnitX.Loggers.TeamCity.pas index 1277d8436c..a8cec8047d 100644 --- a/common/windows/delphi/general/DUnitX.Loggers.TeamCity.pas +++ b/common/windows/delphi/general/DUnitX.Loggers.TeamCity.pas @@ -14,7 +14,7 @@ var KeymanRoot: string; ReportPath: string; begin - if GetEnvironmentVariable('TEAMCITY_VERSION') <> '' then + if GetEnvironmentVariable('TEAMCITY_GIT_PATH') <> '' then begin KeymanRoot := ExcludeTrailingPathDelimiter(GetEnvironmentVariable('KEYMAN_ROOT')); ReportPath := ExtractRelativePath(KeymanRoot, ExtractFilePath(ParamStr(0)) + 'dunitx-results.xml'); diff --git a/web/src/test/manual/web/regression-tests/test-builder.js b/web/src/test/manual/web/regression-tests/test-builder.js index 125d2d9203..00594c973c 100644 --- a/web/src/test/manual/web/regression-tests/test-builder.js +++ b/web/src/test/manual/web/regression-tests/test-builder.js @@ -61,7 +61,7 @@ const cfg = require('karma').config; // Note: if karma.conf.js is invalid, then this will die with exit code 1 // without logging the error. The easiest way to see the error is to // run `node_modules/bin/karma start karma.conf.js` -const karmaConfig = cfg.parseConfig(path.resolve('./karma.conf.js'), process.env.TEAMCITY_PROJECT_NAME ? {'reporters': ['teamcity']} : {}); +const karmaConfig = cfg.parseConfig(path.resolve('./karma.conf.js'), process.env.TEAMCITY_GIT_PATH ? {'reporters': ['teamcity']} : {}); let server = new Server(karmaConfig, function(exitCode) { console.log('Karma has exited with ' + exitCode) From af1f2629dd21f9b230a9d454ff28895905bcd270 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 6 May 2025 16:36:55 +0200 Subject: [PATCH 39/57] maint(common): use function to detect if running on TC This change makes use of the new builder script function to detect if the script is running on TeamCity. --- common/web/types/build.sh | 2 +- resources/shellHelperFunctions.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/web/types/build.sh b/common/web/types/build.sh index a392ec022c..5a9243e6cd 100755 --- a/common/web/types/build.sh +++ b/common/web/types/build.sh @@ -82,7 +82,7 @@ function do_configure() { function do_test() { local MOCHA_FLAGS= - if [[ "${TEAMCITY_GIT_PATH:-}" != "" ]]; then + if builder_is_running_on_teamcity; then # we're running in TeamCity MOCHA_FLAGS="-reporter mocha-teamcity-reporter" fi diff --git a/resources/shellHelperFunctions.sh b/resources/shellHelperFunctions.sh index 5ec0203d3c..469e8204fb 100755 --- a/resources/shellHelperFunctions.sh +++ b/resources/shellHelperFunctions.sh @@ -337,7 +337,7 @@ check-markdown() { builder_do_typescript_tests() { local MOCHA_FLAGS= - if [[ "${TEAMCITY_GIT_PATH:-}" != "" ]]; then + if builder_is_running_on_teamcity; then # we're running in TeamCity MOCHA_FLAGS="-reporter mocha-teamcity-reporter" fi From 5ebc26ec11dfb4217d3f98aa8b83176ccbc872cf Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Tue, 6 May 2025 14:03:11 -0400 Subject: [PATCH 40/57] auto: increment master version to 19.0.33 --- HISTORY.md | 14 ++++++++++++++ VERSION.md | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 3256af2e7a..96049f2853 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,19 @@ # Keyman Version History +## 19.0.32 alpha 2025-05-06 + +* change(web): replace USVString with string in predictive-text engine (#13785) +* chore(web): replace --ci flag with builder_is_ci_build (#13819) +* maint(web): simplify worker-main test.sh (#13820) +* change(web): lint kmwstring web-utility (#13800) +* fix(web): fix extraction of gesture-engine fixture used in DOM-based unit tests (#13805) +* fix(web): add robustness for bad touch-layout fontsize specs (#13774) +* fix(web): fix var declaration affected by linter strictness + length-style fix (#13839) +* chore(ios): Update inuktitut_pirurvik to 1.4.1 (#13840) +* chore(common): override check when running on TC (#13779) +* change(linux): add ICU dependency needed to build on Arch Linux (#13842) +* maint(common): add support for TC blocks (#13810) + ## 19.0.31 alpha 2025-05-05 * fix(mac): add version metadata after building tests (#13818) diff --git a/VERSION.md b/VERSION.md index cc92e71b86..aec8dab02b 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -19.0.32 \ No newline at end of file +19.0.33 \ No newline at end of file From ea88aaeb3e92ebd56f980939fe31c9f1c448c858 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Wed, 7 May 2025 08:25:52 +0700 Subject: [PATCH 41/57] docs(web): apply suggestions from code review Co-authored-by: Eberhard Beilharz --- web/docs/internal/keystroke-lifecycle.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web/docs/internal/keystroke-lifecycle.md b/web/docs/internal/keystroke-lifecycle.md index 8c71b90e7f..c2e401b008 100644 --- a/web/docs/internal/keystroke-lifecycle.md +++ b/web/docs/internal/keystroke-lifecycle.md @@ -37,13 +37,13 @@ title: Keystroke lifecycle flowchart sequenceDiagram; actor User as User + UI -participant Keystroke interpreter +participant Keystroke interpretation functionality -Note over User, KeymanEngine: Start: Keystroke preprocessing +Note over User, KeymanEngine: Start: Keystroke pre-processing User ->> Keystroke interpreter: Types a key Keystroke interpreter ->> Keystroke interpreter: Preprocess keystroke events Keystroke interpreter ->> KeymanEngine: Raise preprocessed event -Note over User, KeymanEngine: End: Keystroke preprocessing +Note over User, KeymanEngine: End: Keystroke pre-processing KeymanEngine ->>+ InputProcessor: Forward keystroke data Note over InputProcessor, KeyboardProcessor: Start: Keystroke processing @@ -173,7 +173,7 @@ against keyboard rules. ### Pre-keystroke state management First, the engine checks the keyboard associated with the `KeyEvent`, ensuring -that it is still in place. (See #7543 for more details.) With that assertion +that it is still in place. (See [#7543](https://github.com/keymanapp/keyman/issues/7543) for more details.) With that assertion in place, it then performs a check needed to support multitaps - it checks to see if the key event has an associated "base context" and reverts the current context to match it if so. Once those checks are fulfilled, the engine then From c389267a22bbb3d0ecf196011e3dc320faabe8d8 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Wed, 7 May 2025 08:29:35 +0700 Subject: [PATCH 42/57] docs(common): comment removed per PR review Co-authored-by: Marc Durdin --- resources/builder.inc.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/builder.inc.sh b/resources/builder.inc.sh index 43f09fa474..82fd2e9efa 100755 --- a/resources/builder.inc.sh +++ b/resources/builder.inc.sh @@ -1394,7 +1394,6 @@ _builder_parse_expanded_parameters() { --release) _builder_chosen_options+=(--release) # As of #13827, this is only checked when detecting if --debug should be auto-applied. - # There is no `builder_is_release_build` function yet. is_release=true ;; --deps|--no-deps|--force-deps) From e145163fc0a1aaf26865be3fe9d7c8bbfefca0e0 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Wed, 7 May 2025 08:35:23 +0700 Subject: [PATCH 43/57] fix(common): change --debug shorthand use from builder test script --- resources/build/test/debug-deps/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/build/test/debug-deps/test.sh b/resources/build/test/debug-deps/test.sh index fe0c29c32f..9ac32d474a 100755 --- a/resources/build/test/debug-deps/test.sh +++ b/resources/build/test/debug-deps/test.sh @@ -17,6 +17,6 @@ function do_build() { echo "PASS: parent: builder_has_option --debug is true" } -builder_parse build:child -d +builder_parse build:child --debug builder_run_action build do_build builder_run_child_actions build From addd8b2471dd52a1493a885a6263afc21a183479 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Wed, 7 May 2025 11:02:25 +0200 Subject: [PATCH 44/57] docs(common): document new `builder_is_running_on_teamcity` function --- docs/builder.md | 15 +++++++++++++++ resources/build/README.md | 4 ++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/docs/builder.md b/docs/builder.md index 1e097fcc17..f4e3f88313 100644 --- a/docs/builder.md +++ b/docs/builder.md @@ -867,6 +867,21 @@ fi -------------------------------------------------------------------------------- +## `builder_is_running_on_teamcity` function + +Returns `true` (aka 0) if the script runs on TeamCity (i.e. if the +`TEAMCITY_GIT_PATH` environment variable is set). + +### Usage + +```bash +if builder_is_running_on_teamcity; then + ... +fi +``` + +-------------------------------------------------------------------------------- + ## `builder_parse` function Initializes a build.sh script, parses command line. Will abort the script if diff --git a/resources/build/README.md b/resources/build/README.md index ead7975b8b..79e953a066 100644 --- a/resources/build/README.md +++ b/resources/build/README.md @@ -16,9 +16,9 @@ including this file... See [build-utils.md](build-utils.md) -### jq-win64 +### jq/jq-win64 -jq-win64.exe is used by various builds for json query. +jq resp. jq-win64.exe is used by various builds for json query. Official source: . [License](jq-license.txt) From 4d81589f48f998206af4306a61e28e84bd9ea0bb Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Wed, 7 May 2025 14:55:28 +0200 Subject: [PATCH 45/57] maint(common): use unique names for Keyman version variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously the builder scripts defined a readonly `VERSION` environment variable for the Keyman version. That caused problems when another (external) script tried to define a `VERSION` variable. We encountered this problem when trying to move the TC build steps of a configuration into a single script (#13399) when we tried to source `~/.nvm/nvm.sh`. This change uses a Keyman specific prefix for the version variables and renames `VERSION` → `KEYMAN_VERSION` etc. Unfortunately these variables are used in a lot of places, so this turned out to be a bit of a yak shave. Test-bot: skip --- .github/workflows/api-verification.yml | 4 +- .github/workflows/deb-packaging.yml | 24 +- android/KMAPro/build-play-store-notes.inc.sh | 2 +- android/KMAPro/build.sh | 10 +- android/KMAPro/kMAPro/build.gradle | 18 +- .../com/keyman/android/SystemKeyboard.java | 4 +- .../com/tavultesoft/kmapro/MainActivity.java | 4 +- android/KMEA/app/build.gradle | 6 +- .../com/keyman/engine/util/VersionUtils.java | 4 +- .../Tests/KeyboardHarness/app/build.gradle | 8 +- android/Tests/keycode/app/build.gradle | 8 +- android/version.gradle | 50 ++-- common/test/keyboards/build.sh | 6 +- common/web/keyman-version/build.sh | 20 +- developer/src/inst/build.sh | 40 +-- developer/src/inst/kmdev.wxs | 12 +- developer/src/kmc/build.sh | 2 +- .../src/server/src/site/lib/sentry/init.js.in | 4 +- developer/src/server/src/version-data.ts | 24 +- .../src/tike/xml/app/lib/sentry/init.js.in | 4 +- developer/src/tools/sentry-upload-difs.sh | 2 +- docs/linux/packaging.md | 8 +- ios/engine/build.sh | 12 +- ios/keyman/build.sh | 14 +- ios/scripts/kme-universal.sh | 8 +- ios/tools/prepRelease.sh | 12 +- linux/ibus-keyman/src/keyman-version.h.in | 2 +- linux/ibus-keyman/src/keyman.xml.in | 2 +- linux/ibus-keyman/src/meson.build | 2 +- linux/keyman-config/Makefile | 8 +- linux/keyman-config/build.sh | 16 +- .../keyman-config/keyman_config/version.py.in | 16 +- .../resources/VERSION_WITH_TAG.md | 1 + linux/scripts/dist.sh | 12 +- linux/scripts/launchpad.sh | 4 +- linux/scripts/package-build.inc.sh | 8 +- linux/scripts/reconf.sh | 18 +- linux/scripts/test/test.inc.sh | 4 +- linux/scripts/verify_api.inc.sh | 10 +- .../Keyman4MacIM.xcodeproj/project.pbxproj | 2 +- mac/Keyman4MacIM/make-km-dmg.sh | 10 +- mac/Keyman4MacIM/write-download_info.sh | 12 +- .../project.pbxproj | 2 +- mac/build.sh | 24 +- mac/is_same_version.sh | 6 +- oem/firstvoices/android/app/build.gradle | 14 +- .../firstvoices/keyboards/MainActivity.java | 4 +- .../firstvoices/keyboards/SystemKeyboard.java | 4 +- oem/firstvoices/android/build.sh | 4 +- oem/firstvoices/ios/build.sh | 16 +- oem/firstvoices/windows/src/inst/build.sh | 18 +- .../windows/src/inst/firstvoices.wxs | 12 +- resources/build/build-utils-ci.inc.sh | 22 +- resources/build/build-utils.sh | 233 +++++++++--------- resources/build/ci/pull-requests.inc.sh | 4 +- resources/build/help-keyman-com.sh | 30 +-- resources/build/increment-version.sh | 14 +- .../build/meson/standard_meson_build.inc.sh | 4 +- resources/build/publish-minimum-versions.sh | 14 +- resources/build/sentry-control.inc.sh | 12 +- ...set-bundle-versions-and-settings-tagged.sh | 4 +- ...t-bundle-versions-and-settings-untagged.sh | 4 +- resources/build/set-bundle-versions-tagged.sh | 4 +- resources/build/test/test.sh | 4 +- resources/build/trigger-builds.inc.sh | 4 +- resources/build/version/src/fixupHistory.ts | 2 +- resources/build/win/environment.inc.sh | 8 +- resources/build/xcode-utils.sh | 40 +-- resources/builder.inc.sh | 2 +- resources/locate_emscripten.inc.sh | 2 +- resources/shellHelperFunctions.sh | 14 +- web/ci.sh | 18 +- web/src/tools/building/check-build-size.sh | 8 +- windows/src/buildtools/sentry-upload-difs.sh | 2 +- windows/src/desktop/inst/build.sh | 26 +- windows/src/desktop/inst/keymandesktop.wxs | 14 +- windows/src/engine/inst/build.sh | 16 +- windows/src/engine/inst/keymanengine.wxs | 2 +- 78 files changed, 530 insertions(+), 518 deletions(-) create mode 100644 linux/keyman-system-service/resources/VERSION_WITH_TAG.md diff --git a/.github/workflows/api-verification.yml b/.github/workflows/api-verification.yml index 8f37141c08..b8b2e35563 100644 --- a/.github/workflows/api-verification.yml +++ b/.github/workflows/api-verification.yml @@ -15,7 +15,7 @@ jobs: name: Verify API for libkeymancore*.so runs-on: ubuntu-latest outputs: - VERSION: ${{ steps.environment_step.outputs.VERSION }} + KEYMAN_VERSION: ${{ steps.environment_step.outputs.KEYMAN_VERSION }} PRERELEASE_TAG: ${{ steps.environment_step.outputs.PRERELEASE_TAG }} GIT_SHA: ${{ steps.environment_step.outputs.GIT_SHA }} GIT_BASE: ${{ steps.environment_step.outputs.GIT_BASE }} @@ -69,7 +69,7 @@ jobs: run: | echo "Verify API for libkeymancore*.so (${{ steps.environment_step.outputs.GIT_BRANCH }}, branch ${{ steps.environment_step.outputs.GIT_BASE_BRANCH }}, by ${{ steps.environment_step.outputs.GIT_USER }}):" >> $GITHUB_STEP_SUMMARY - BIN_PACKAGE=$(ls "${GITHUB_WORKSPACE}/artifacts/" | grep "${PKG_NAME}[0-9]*_${{ steps.environment_step.outputs.VERSION }}-1${{ steps.environment_step.outputs.PRERELEASE_TAG }}+$(lsb_release -c -s)1_amd64.deb") + BIN_PACKAGE=$(ls "${GITHUB_WORKSPACE}/artifacts/" | grep "${PKG_NAME}[0-9]*_${{ steps.environment_step.outputs.KEYMAN_VERSION }}-1${{ steps.environment_step.outputs.PRERELEASE_TAG }}+$(lsb_release -c -s)1_amd64.deb") cd ${{ github.workspace }}/keyman/linux ./scripts/deb-packaging.sh \ --gha \ diff --git a/.github/workflows/deb-packaging.yml b/.github/workflows/deb-packaging.yml index c026acafeb..c7bc098d8b 100644 --- a/.github/workflows/deb-packaging.yml +++ b/.github/workflows/deb-packaging.yml @@ -37,7 +37,7 @@ jobs: if: github.repository == 'keymanapp/keyman' runs-on: ubuntu-24.04 outputs: - VERSION: ${{ steps.version_step.outputs.VERSION }} + KEYMAN_VERSION: ${{ steps.version_step.outputs.KEYMAN_VERSION }} PRERELEASE_TAG: ${{ steps.prerelease_tag.outputs.PRERELEASE_TAG }} steps: - name: Checkout @@ -72,10 +72,10 @@ jobs: - name: Build source package id: build_source_package run: | - export TIER=$(cat TIER.md) + export KEYMAN_TIER=$(cat TIER.md) export GHA_TEST_BUILD="${{ github.event.client_payload.isTestBuild }}" export GHA_BRANCH="${{ github.event.client_payload.branch }}" - echo "TIER=$TIER" >> $GITHUB_ENV + echo "KEYMAN_TIER=$KEYMAN_TIER" >> $GITHUB_ENV echo "GHA_TEST_BUILD=${GHA_TEST_BUILD}" >> $GITHUB_ENV echo "GHA_BRANCH=${GHA_BRANCH}" >> $GITHUB_ENV cd linux @@ -87,7 +87,7 @@ jobs: run: | THIS_SCRIPT="$GITHUB_WORKSPACE/.github/workflows/deb-packaging.yml" . "${THIS_SCRIPT%/*}/../../resources/build/build-utils.sh" - echo "VERSION=$VERSION" >> $GITHUB_OUTPUT + echo "KEYMAN_VERSION=$KEYMAN_VERSION" >> $GITHUB_OUTPUT - name: Set prerelease tag as output parameter id: prerelease_tag @@ -103,9 +103,9 @@ jobs: - name: Output which branch or PR we're building plus name of .dsc file run: | if [ "${{ github.event.client_payload.isTestBuild }}" == "true" ]; then - echo ":checkered_flag: **Test build of version ${{ steps.version_step.outputs.VERSION }} for ${{ github.event.client_payload.branch }}**" >> $GITHUB_STEP_SUMMARY + echo ":checkered_flag: **Test build of version ${{ steps.version_step.outputs.KEYMAN_VERSION }} for ${{ github.event.client_payload.branch }}**" >> $GITHUB_STEP_SUMMARY else - echo ":ship: **Release build of ${{ github.event.client_payload.branch }} branch (${{ github.event.client_payload.branch}}), version ${{ steps.version_step.outputs.VERSION }}**" >> $GITHUB_STEP_SUMMARY + echo ":ship: **Release build of ${{ github.event.client_payload.branch }} branch (${{ github.event.client_payload.branch}}), version ${{ steps.version_step.outputs.KEYMAN_VERSION }}**" >> $GITHUB_STEP_SUMMARY fi echo "" >> $GITHUB_STEP_SUMMARY echo ":gift: Generated source package:" >> $GITHUB_STEP_SUMMARY @@ -140,7 +140,7 @@ jobs: uses: ./.github/actions/build-binary-packages with: dist: ${{ matrix.dist }} - version: ${{ needs.sourcepackage.outputs.VERSION }} + version: ${{ needs.sourcepackage.outputs.KEYMAN_VERSION }} prerelease_tag: ${{ needs.sourcepackage.outputs.PRERELEASE_TAG }} deb_fullname: ${{env.DEBFULLNAME}} deb_email: ${{env.DEBEMAIL}} @@ -166,7 +166,7 @@ jobs: uses: ./.github/actions/build-binary-packages with: dist: ${{ matrix.dist }} - version: ${{ needs.sourcepackage.outputs.VERSION }} + version: ${{ needs.sourcepackage.outputs.KEYMAN_VERSION }} prerelease_tag: ${{ needs.sourcepackage.outputs.PRERELEASE_TAG }} deb_fullname: ${{env.DEBFULLNAME}} deb_email: ${{env.DEBEMAIL}} @@ -211,8 +211,8 @@ jobs: - name: Sign packages uses: sillsdev/gha-deb-signing@a38dbde6bc9afabede5e07609105acc83c760ad4 # v0.6 with: - src-pkg-name: "keyman_${{ needs.sourcepackage.outputs.VERSION }}-1_source.changes" - bin-pkg-name: "keyman_${{ needs.sourcepackage.outputs.VERSION }}-1${{ needs.sourcepackage.outputs.PRERELEASE_TAG }}+" + src-pkg-name: "keyman_${{ needs.sourcepackage.outputs.KEYMAN_VERSION }}-1_source.changes" + bin-pkg-name: "keyman_${{ needs.sourcepackage.outputs.KEYMAN_VERSION }}-1${{ needs.sourcepackage.outputs.PRERELEASE_TAG }}+" artifacts-prefix: "keyman-" artifacts-result-name: "keyman-signedpkgs" gpg-signing-key: "${{ secrets.GPG_SIGNING_KEY }}" @@ -293,7 +293,7 @@ jobs: echo "::endgroup::" echo -e "::group::${COLOR_GREEN}Uploading binary packages" - pattern="keyman_${{ needs.sourcepackage.outputs.VERSION }}.+\+(.*)[0-9]_[^.]+.changes" + pattern="keyman_${{ needs.sourcepackage.outputs.KEYMAN_VERSION }}.+\+(.*)[0-9]_[^.]+.changes" for f in *_amd64.changes; do if [[ $f =~ $pattern ]]; then dist=${BASH_REMATCH[1]} @@ -316,7 +316,7 @@ jobs: - name: Save environment run: | - echo "VERSION=${{ needs.sourcepackage.outputs.VERSION }}" > artifacts/env + echo "KEYMAN_VERSION=${{ needs.sourcepackage.outputs.KEYMAN_VERSION }}" > artifacts/env echo "PRERELEASE_TAG=${{ needs.sourcepackage.outputs.PRERELEASE_TAG }}" >> artifacts/env echo "GIT_SHA=${{ github.event.client_payload.buildSha }}" >> artifacts/env echo "GIT_BASE=${{ github.event.client_payload.baseRef }}" >> artifacts/env diff --git a/android/KMAPro/build-play-store-notes.inc.sh b/android/KMAPro/build-play-store-notes.inc.sh index 56b9a92326..23a14d4eb3 100755 --- a/android/KMAPro/build-play-store-notes.inc.sh +++ b/android/KMAPro/build-play-store-notes.inc.sh @@ -12,7 +12,7 @@ function generateReleaseNotes() { # Reference: https://github.com/Triple-T/gradle-play-publisher#uploading-release-notes # local PLAY_RELEASE_NOTES="$KEYMAN_ROOT/android/KMAPro/kMAPro/src/main/play/release-notes/en-US/$TIER.txt" - if [ $TIER = "stable" ]; then + if [ $KEYMAN_TIER = "stable" ]; then PLAY_RELEASE_NOTES="$KEYMAN_ROOT/android/KMAPro/kMAPro/src/main/play/release-notes/en-US/default.txt" fi builder_heading "Generating Play Store release notes to $PLAY_RELEASE_NOTES" diff --git a/android/KMAPro/build.sh b/android/KMAPro/build.sh index bfe81bba5b..aef29ae0a0 100755 --- a/android/KMAPro/build.sh +++ b/android/KMAPro/build.sh @@ -43,7 +43,7 @@ fi builder_describe_outputs \ configure /android/KMAPro/kMAPro/libs/keyman-engine.aar \ - build /android/KMAPro/kMAPro/build/outputs/apk/$CONFIG/keyman-${VERSION}.apk + build /android/KMAPro/kMAPro/build/outputs/apk/$CONFIG/keyman-${KEYMAN_VERSION}.apk #### Build @@ -57,12 +57,12 @@ fi #### Build action definitions #### function makeLocalSentryRelease() { - echo "Making a Sentry release for tag $VERSION_GIT_TAG" + echo "Making a Sentry release for tag $KEYMAN_VERSION_GIT_TAG" sentry-cli upload-dif -p keyman-android --include-sources - sentry-cli releases -p keyman-android files $VERSION_GIT_TAG upload-sourcemaps ./ + sentry-cli releases -p keyman-android files $KEYMAN_VERSION_GIT_TAG upload-sourcemaps ./ - echo "Finalizing release tag $VERSION_GIT_TAG" - sentry-cli releases finalize "$VERSION_GIT_TAG" + echo "Finalizing release tag $KEYMAN_VERSION_GIT_TAG" + sentry-cli releases finalize "$KEYMAN_VERSION_GIT_TAG" } diff --git a/android/KMAPro/kMAPro/build.gradle b/android/KMAPro/kMAPro/build.gradle index 768d98d933..46750a183f 100644 --- a/android/KMAPro/kMAPro/build.gradle +++ b/android/KMAPro/kMAPro/build.gradle @@ -29,11 +29,11 @@ android { //dumpProperties(project) // Use this to dump all external properties for debugging TeamCity integration //println "===END DUMP===" - // VERSION strings from version.gradle - versionCode VERSION_CODE as Integer - versionName VERSION_NAME - buildConfigField 'String', 'VERSION_ENVIRONMENT', '"'+VERSION_ENVIRONMENT+'"' - buildConfigField 'String', 'VERSION_GIT_TAG', '"'+VERSION_GIT_TAG+'"' + // KEYMAN_VERSION strings from version.gradle + versionCode KEYMAN_VERSION_CODE as Integer + versionName KEYMAN_VERSION_NAME + buildConfigField 'String', 'KEYMAN_VERSION_ENVIRONMENT', '"'+KEYMAN_VERSION_ENVIRONMENT+'"' + buildConfigField 'String', 'KEYMAN_VERSION_GIT_TAG', '"'+KEYMAN_VERSION_GIT_TAG+'"' } String env_release_store_file = System.getenv("release_store_file") @@ -77,7 +77,7 @@ android { // - PR builds also have "-test-1234" suffix (where 1234 is PR#) // Gradle sync will nullify these values, so have a fallback String appSuffix = '' - String tag = VERSION_TAG ? VERSION_TAG : '-' + tier; + String tag = KEYMAN_VERSION_TAG ? KEYMAN_VERSION_TAG : '-' + tier; if (tag.startsWithAny("-beta", "beta")) { appSuffix = ' Beta'; } else if (tag.startsWithAny("-alpha", "alpha")) { @@ -88,16 +88,16 @@ android { // -test-PR_NUMBER appSuffix = appSuffix + match.group(1) } else { - String environment = VERSION_ENVIRONMENT ? VERSION_ENVIRONMENT : 'local'; + String environment = KEYMAN_VERSION_ENVIRONMENT ? KEYMAN_VERSION_ENVIRONMENT : 'local'; if (environment.matches("local")) { appSuffix = appSuffix + '-' + environment; } } variant.resValue "string", "app_name", 'Keyman' + appSuffix; - // Adjust output name to "keyman-${VERSION_MD}.apk" + // Adjust output name to "keyman-${KEYMAN_VERSION_MD}.apk" variant.outputs.all { - outputFileName = "keyman-" + VERSION_MD + ".apk" + outputFileName = "keyman-" + KEYMAN_VERSION_MD + ".apk" } } lintOptions { diff --git a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java index e6016202a0..2d03311d50 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java +++ b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java @@ -62,8 +62,8 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven Log.d(TAG, "Initializing Sentry"); SentryAndroid.init(getApplicationContext(), options -> { options.setEnableAutoSessionTracking(false); - options.setRelease(com.tavultesoft.kmapro.BuildConfig.VERSION_GIT_TAG); - options.setEnvironment(com.tavultesoft.kmapro.BuildConfig.VERSION_ENVIRONMENT); + options.setRelease(com.tavultesoft.kmapro.BuildConfig.KEYMAN_VERSION_GIT_TAG); + options.setEnvironment(com.tavultesoft.kmapro.BuildConfig.KEYMAN_VERSION_ENVIRONMENT); }); } if (BuildConfig.DEBUG) { diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java index 07ce5c4cbb..fbe8475f09 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java @@ -144,8 +144,8 @@ public class MainActivity extends BaseActivity implements OnKeyboardEventListene if (KMManager.getMaySendCrashReport()) { SentryAndroid.init(context, options -> { options.setEnableAutoSessionTracking(false); - options.setRelease(com.tavultesoft.kmapro.BuildConfig.VERSION_GIT_TAG); - options.setEnvironment(com.tavultesoft.kmapro.BuildConfig.VERSION_ENVIRONMENT); + options.setRelease(com.tavultesoft.kmapro.BuildConfig.KEYMAN_VERSION_GIT_TAG); + options.setEnvironment(com.tavultesoft.kmapro.BuildConfig.KEYMAN_VERSION_ENVIRONMENT); }); } diff --git a/android/KMEA/app/build.gradle b/android/KMEA/app/build.gradle index c80a4fd66e..c556e2588c 100644 --- a/android/KMEA/app/build.gradle +++ b/android/KMEA/app/build.gradle @@ -14,9 +14,9 @@ android { minSdkVersion 21 targetSdkVersion 34 - // VERSION_CODE and VERSION_NAME from version.gradle but Gradle removes them for libraries - buildConfigField "String", "KEYMAN_ENGINE_VERSION_NAME", "\""+VERSION_NAME+"\"" - buildConfigField "String", "VERSION_ENVIRONMENT", "\""+VERSION_ENVIRONMENT+"\"" + // KEYMAN_VERSION_CODE and KEYMAN_VERSION_NAME from version.gradle but Gradle removes them for libraries + buildConfigField "String", "KEYMAN_ENGINE_VERSION_NAME", "\""+KEYMAN_VERSION_NAME+"\"" + buildConfigField "String", "KEYMAN_VERSION_ENVIRONMENT", "\""+KEYMAN_VERSION_ENVIRONMENT+"\"" // Sepcify library filename keyman-engine-$CONFIG.aar setProperty("archivesBaseName", "keyman-engine") diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/util/VersionUtils.java b/android/KMEA/app/src/main/java/com/keyman/engine/util/VersionUtils.java index 58e80399f5..7188280615 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/util/VersionUtils.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/util/VersionUtils.java @@ -12,11 +12,11 @@ public final class VersionUtils { public static final String TAG = "VersionUtils"; public static boolean isLocalBuild() { - return BuildConfig.VERSION_ENVIRONMENT.equalsIgnoreCase("local"); + return BuildConfig.KEYMAN_VERSION_ENVIRONMENT.equalsIgnoreCase("local"); } public static boolean isTestBuild() { - return BuildConfig.VERSION_ENVIRONMENT.equalsIgnoreCase("test"); + return BuildConfig.KEYMAN_VERSION_ENVIRONMENT.equalsIgnoreCase("test"); } // Utility for local and PR test builds - e.g. force check of keyboard updates diff --git a/android/Tests/KeyboardHarness/app/build.gradle b/android/Tests/KeyboardHarness/app/build.gradle index 5462622cfa..3eba70ec99 100644 --- a/android/Tests/KeyboardHarness/app/build.gradle +++ b/android/Tests/KeyboardHarness/app/build.gradle @@ -19,10 +19,10 @@ android { minSdkVersion 21 targetSdkVersion 34 - // VERSION_CODE and VERSION_NAME from version.gradle - versionCode VERSION_CODE as Integer - versionName VERSION_NAME - buildConfigField "String", "VERSION_ENVIRONMENT", "\""+VERSION_ENVIRONMENT+"\"" + // KEYMAN_VERSION_CODE and KEYMAN_VERSION_NAME from version.gradle + versionCode KEYMAN_VERSION_CODE as Integer + versionName KEYMAN_VERSION_NAME + buildConfigField "String", "KEYMAN_VERSION_ENVIRONMENT", "\""+KEYMAN_VERSION_ENVIRONMENT+"\"" } buildTypes { release { diff --git a/android/Tests/keycode/app/build.gradle b/android/Tests/keycode/app/build.gradle index ffba4c0cc4..a0b24abb44 100644 --- a/android/Tests/keycode/app/build.gradle +++ b/android/Tests/keycode/app/build.gradle @@ -12,10 +12,10 @@ android { minSdkVersion 21 targetSdkVersion 34 - // VERSION_CODE and VERSION_NAME from version.gradle - versionCode VERSION_CODE as Integer - versionName VERSION_NAME - buildConfigField "String", "VERSION_ENVIRONMENT", "\""+VERSION_ENVIRONMENT+"\"" + // KEYMAN_VERSION_CODE and KEYMAN_VERSION_NAME from version.gradle + versionCode KEYMAN_VERSION_CODE as Integer + versionName KEYMAN_VERSION_NAME + buildConfigField "String", "KEYMAN_VERSION_ENVIRONMENT", "\""+KEYMAN_VERSION_ENVIRONMENT+"\"" } buildTypes { release { diff --git a/android/version.gradle b/android/version.gradle index ebf68a94e0..ea7342166c 100644 --- a/android/version.gradle +++ b/android/version.gradle @@ -7,9 +7,9 @@ // def getVersionCode = { -> - String env_version_major = System.getenv("VERSION_MAJOR") - String env_version_minor = System.getenv("VERSION_MINOR") - String env_version_patch = System.getenv("VERSION_PATCH") + String env_version_major = System.getenv("KEYMAN_VERSION_MAJOR") + String env_version_minor = System.getenv("KEYMAN_VERSION_MINOR") + String env_version_patch = System.getenv("KEYMAN_VERSION_PATCH") if(env_version_patch != null && env_version_minor != null && env_version_patch != null) { // Version code is, for 17.1.33: 1810033. This supports up to 9999 // builds for a given major.minor version. We only support up to 9 minor @@ -36,10 +36,10 @@ def getVersionCode = { -> } def getVersionMD = { -> - String env_version = System.getenv("VERSION") + String env_version = System.getenv("KEYMAN_VERSION") if (env_version != null) { - // If building from script, we have build number in VERSION - println "Using build $env_version from VERSION" + // If building from script, we have build number in KEYMAN_VERSION + println "Using build $env_version from KEYMAN_VERSION" return "$env_version" } else { String version_md = file("$rootPath/../VERSION.md").text.trim() @@ -48,15 +48,15 @@ def getVersionMD = { -> } def getVersionName = { -> - String env_version = System.getenv("VERSION_WITH_TAG") + String env_version = System.getenv("KEYMAN_VERSION_WITH_TAG") if (env_version != null) { - // If building from script, we have build number in VERSION_WITH_TAG - println "Using build $env_version from VERSION_WITH_TAG" + // If building from script, we have build number in KEYMAN_VERSION_WITH_TAG + println "Using build $env_version from KEYMAN_VERSION_WITH_TAG" return "$env_version" } else { // Building probably from IDE, so let's use VERSION.md and TIER.md directly - // This is a close match with VERSION_WITH_TAG, except that 'stable' tier - // is not normally included with VERSION_WITH_TAG + // This is a close match with KEYMAN_VERSION_WITH_TAG, except that 'stable' tier + // is not normally included with KEYMAN_VERSION_WITH_TAG String version_md = file("$rootPath/../VERSION.md").text.trim() String tier_md = file("$rootPath/../TIER.md").text.trim() println "Using build $version_md-$tier_md-local from project VERSION.md/TIER.md" @@ -65,10 +65,10 @@ def getVersionName = { -> } def getVersionEnvironment = { -> - String env_environment = System.getenv("VERSION_ENVIRONMENT") + String env_environment = System.getenv("KEYMAN_VERSION_ENVIRONMENT") if (env_environment != null) { - // If building from script, we have build number in VERSION_ENVIRONMENT - println "Using $env_environment from VERSION_ENVIRONMENT" + // If building from script, we have build number in KEYMAN_VERSION_ENVIRONMENT + println "Using $env_environment from KEYMAN_VERSION_ENVIRONMENT" return "$env_environment" } else { // Building probably from IDE, so use "local" @@ -78,23 +78,23 @@ def getVersionEnvironment = { -> } def getVersionGitTag = { -> - String env_git_tag = System.getenv("VERSION_GIT_TAG") + String env_git_tag = System.getenv("KEYMAN_VERSION_GIT_TAG") if (env_git_tag != null) { - println "Using $env_git_tag from VERSION_GIT_TAG" + println "Using $env_git_tag from KEYMAN_VERSION_GIT_TAG" return "$env_git_tag" } else { // Building probably from IDE - println "Using release@$VERSION_NAME" - return "release@$VERSION_NAME" + println "Using release@$KEYMAN_VERSION_NAME" + return "release@$KEYMAN_VERSION_NAME" } } ext { - VERSION_CODE=getVersionCode() - VERSION_MD=getVersionMD() - VERSION_NAME=getVersionName() - VERSION_ENVIRONMENT=getVersionEnvironment() - VERSION_TAG=System.getenv("VERSION_TAG") - VERSION_GIT_TAG=getVersionGitTag() + KEYMAN_VERSION_CODE=getVersionCode() + KEYMAN_VERSION_MD=getVersionMD() + KEYMAN_VERSION_NAME=getVersionName() + KEYMAN_VERSION_ENVIRONMENT=getVersionEnvironment() + KEYMAN_VERSION_TAG=System.getenv("KEYMAN_VERSION_TAG") + KEYMAN_VERSION_GIT_TAG=getVersionGitTag() } -//println "version.gradle: VERSION_TAG: " + VERSION_TAG \ No newline at end of file +//println "version.gradle: KEYMAN_VERSION_TAG: " + KEYMAN_VERSION_TAG \ No newline at end of file diff --git a/common/test/keyboards/build.sh b/common/test/keyboards/build.sh index 2c8cc19ff4..1a1c9c2675 100755 --- a/common/test/keyboards/build.sh +++ b/common/test/keyboards/build.sh @@ -40,10 +40,10 @@ function build_index() { - Test Keyboards - $VERSION_WITH_TAG + Test Keyboards - $KEYMAN_VERSION_WITH_TAG -

Test Keyboards - $VERSION_WITH_TAG

+

Test Keyboards - $KEYMAN_VERSION_WITH_TAG

    EOF @@ -90,4 +90,4 @@ function build() { fi } -builder_run_action build build \ No newline at end of file +builder_run_action build build diff --git a/common/web/keyman-version/build.sh b/common/web/keyman-version/build.sh index 8fb4884812..9de3da3f8f 100755 --- a/common/web/keyman-version/build.sh +++ b/common/web/keyman-version/build.sh @@ -33,16 +33,16 @@ function do_build() { // Note: does not use the 'default' keyword so that the export name is // correct when converted to a CommonJS module with \`esbuild\`. export class KEYMAN_VERSION { - static readonly VERSION = \"$VERSION\"; - static readonly VERSION_RELEASE =\"$VERSION_RELEASE\"; - static readonly VERSION_MAJOR = \"$VERSION_MAJOR\"; - static readonly VERSION_MINOR = \"$VERSION_MINOR\"; - static readonly VERSION_PATCH = \"$VERSION_PATCH\"; - static readonly TIER =\"$TIER\"; - static readonly VERSION_TAG = \"$VERSION_TAG\"; - static readonly VERSION_WITH_TAG = \"$VERSION_WITH_TAG\"; - static readonly VERSION_ENVIRONMENT = \"$VERSION_ENVIRONMENT\"; - static readonly VERSION_GIT_TAG = \"$VERSION_GIT_TAG\"; + static readonly VERSION = \"$KEYMAN_VERSION\"; + static readonly VERSION_RELEASE =\"$KEYMAN_VERSION_RELEASE\"; + static readonly VERSION_MAJOR = \"$KEYMAN_VERSION_MAJOR\"; + static readonly VERSION_MINOR = \"$KEYMAN_VERSION_MINOR\"; + static readonly VERSION_PATCH = \"$KEYMAN_VERSION_PATCH\"; + static readonly TIER =\"$KEYMAN_TIER\"; + static readonly VERSION_TAG = \"$KEYMAN_VERSION_TAG\"; + static readonly VERSION_WITH_TAG = \"$KEYMAN_VERSION_WITH_TAG\"; + static readonly VERSION_ENVIRONMENT = \"$KEYMAN_VERSION_ENVIRONMENT\"; + static readonly VERSION_GIT_TAG = \"$KEYMAN_VERSION_GIT_TAG\"; } // Also provides it as a 'default' export. diff --git a/developer/src/inst/build.sh b/developer/src/inst/build.sh index 95551a45a7..8f5b722506 100755 --- a/developer/src/inst/build.sh +++ b/developer/src/inst/build.sh @@ -16,7 +16,7 @@ builder_describe "Installation files for Keyman Developer" \ # after all other builds complete builder_describe_outputs \ - publish /developer/src/inst/keymandeveloper-${VERSION}.exe + publish /developer/src/inst/keymandeveloper-${KEYMAN_VERSION}.exe builder_parse "$@" @@ -25,8 +25,8 @@ builder_parse "$@" . "$KEYMAN_ROOT/resources/build/win/zip.inc.sh" # In dev environments, we'll hack the tier to alpha; CI sets this for us in real builds. -if [[ -z ${TIER+x} ]]; then - TIER=alpha +if [[ -z ${KEYMAN_TIER+x} ]]; then + KEYMAN_TIER=alpha fi # We use different directories so that heat generates @@ -90,13 +90,13 @@ function do_test() { function copy-kmdev() { builder_heading copy-kmdev - mkdir -p "$DEVELOPER_ROOT/release/${VERSION}" + mkdir -p "$DEVELOPER_ROOT/release/${KEYMAN_VERSION}" make-installer make-kmc-install-zip - cp -f "$DEVELOPER_ROOT/src/inst/keymandeveloper.msi" "$DEVELOPER_ROOT/release/${VERSION}/keymandeveloper.msi" - cp -f "$DEVELOPER_ROOT/src/inst/keymandeveloper-${VERSION}.exe" "$DEVELOPER_ROOT/release/${VERSION}/keymandeveloper-${VERSION}.exe" + cp -f "$DEVELOPER_ROOT/src/inst/keymandeveloper.msi" "$DEVELOPER_ROOT/release/${KEYMAN_VERSION}/keymandeveloper.msi" + cp -f "$DEVELOPER_ROOT/src/inst/keymandeveloper-${KEYMAN_VERSION}.exe" "$DEVELOPER_ROOT/release/${KEYMAN_VERSION}/keymandeveloper-${KEYMAN_VERSION}.exe" } function verify-program-signatures() { @@ -108,7 +108,7 @@ function verify-program-signatures() { function verify-installer-signatures() { builder_heading verify-installer-signatures - verify-all-executable-signatures-in-folder "$DEVELOPER_ROOT/release/${VERSION}" + verify-all-executable-signatures-in-folder "$DEVELOPER_ROOT/release/${KEYMAN_VERSION}" } function verify-node-installer-version() { @@ -126,8 +126,8 @@ function verify-node-installer-version() { } function test-releaseexists() { - if [[ -d "$DEVELOPER_ROOT/release/${VERSION}" ]]; then - builder_die "Release ${VERSION} already exists. Delete it or update VERSION.md and try again" + if [[ -d "$DEVELOPER_ROOT/release/${KEYMAN_VERSION}" ]]; then + builder_die "Release ${KEYMAN_VERSION} already exists. Delete it or update VERSION.md and try again" fi } @@ -141,12 +141,12 @@ function candle() { heat-kmc builder_heading "candle: calling WIX:candle" - "$WIXCANDLE" -wx -nologo "-dVERSION=${VERSION_WIN}" "-dRELEASE=${VERSION_RELEASE}" kmdev.wxs - "$WIXCANDLE" -wx -nologo "-dVERSION=${VERSION_WIN}" "-dRELEASE=${VERSION_RELEASE}" "-dXmlSourceDir=${DEVELOPER_ROOT}/src/tike/xml" xml.wxs - "$WIXCANDLE" -wx -nologo "-dVERSION=${VERSION_WIN}" "-dRELEASE=${VERSION_RELEASE}" "-dCefSourceDir=${KEYMAN_CEF4DELPHI_ROOT}" cef.wxs - "$WIXCANDLE" -wx -nologo "-dVERSION=${VERSION_WIN}" "-dRELEASE=${VERSION_RELEASE}" "-dTemplatesSourceDir=${KEYMAN_DEVELOPER_TEMPLATES_ROOT}" templates.wxs - "$WIXCANDLE" -wx -nologo "-dVERSION=${VERSION_WIN}" "-dRELEASE=${VERSION_RELEASE}" "-dkmcSourceDir=${KEYMAN_WIX_TEMP_KMC}" kmc.wxs - "$WIXCANDLE" -wx -nologo "-dVERSION=${VERSION_WIN}" "-dRELEASE=${VERSION_RELEASE}" "-dServerSourceDir=${KEYMAN_WIX_KMDEV_SERVER}" server.wxs + "$WIXCANDLE" -wx -nologo "-dKEYMAN_VERSION=${KEYMAN_VERSION_WIN}" "-dRELEASE=${KEYMAN_VERSION_RELEASE}" kmdev.wxs + "$WIXCANDLE" -wx -nologo "-dKEYMAN_VERSION=${KEYMAN_VERSION_WIN}" "-dRELEASE=${KEYMAN_VERSION_RELEASE}" "-dXmlSourceDir=${DEVELOPER_ROOT}/src/tike/xml" xml.wxs + "$WIXCANDLE" -wx -nologo "-dKEYMAN_VERSION=${KEYMAN_VERSION_WIN}" "-dRELEASE=${KEYMAN_VERSION_RELEASE}" "-dCefSourceDir=${KEYMAN_CEF4DELPHI_ROOT}" cef.wxs + "$WIXCANDLE" -wx -nologo "-dKEYMAN_VERSION=${KEYMAN_VERSION_WIN}" "-dRELEASE=${KEYMAN_VERSION_RELEASE}" "-dTemplatesSourceDir=${KEYMAN_DEVELOPER_TEMPLATES_ROOT}" templates.wxs + "$WIXCANDLE" -wx -nologo "-dKEYMAN_VERSION=${KEYMAN_VERSION_WIN}" "-dRELEASE=${KEYMAN_VERSION_RELEASE}" "-dkmcSourceDir=${KEYMAN_WIX_TEMP_KMC}" kmc.wxs + "$WIXCANDLE" -wx -nologo "-dKEYMAN_VERSION=${KEYMAN_VERSION_WIN}" "-dRELEASE=${KEYMAN_VERSION_RELEASE}" "-dServerSourceDir=${KEYMAN_WIX_KMDEV_SERVER}" server.wxs } function heat-xml() { @@ -230,12 +230,12 @@ function make-installer() { builder_heading make-installer echo [Setup] > setup.inf - echo "Version=$VERSION" >> setup.inf + echo "Version=$KEYMAN_VERSION" >> setup.inf echo "MSIFileName=keymandeveloper.msi" >> setup.inf - echo "Title=Keyman Developer ${VERSION_WITH_TAG}" >>setup.inf + echo "Title=Keyman Developer ${KEYMAN_VERSION_WITH_TAG}" >>setup.inf wzzip setup.zip keymandeveloper.msi setup.inf - cat "$DEVELOPER_PROGRAM/setup.exe" setup.zip > "keymandeveloper-$VERSION.exe" - wrap-signcode //d "Keyman Developer" "keymandeveloper-$VERSION.exe" + cat "$DEVELOPER_PROGRAM/setup.exe" setup.zip > "keymandeveloper-$KEYMAN_VERSION.exe" + wrap-signcode //d "Keyman Developer" "keymandeveloper-$KEYMAN_VERSION.exe" # # Zip the files we distribute as part of the standalone kmc distro into release\$Version\kmcomp-$Version.zip @@ -243,7 +243,7 @@ function make-installer() { } # TODO: rename this to keyman-developer-cli-$Version.zip -KMC_ZIP="$DEVELOPER_ROOT/release/$VERSION/kmcomp-$VERSION.zip" +KMC_ZIP="$DEVELOPER_ROOT/release/$KEYMAN_VERSION/kmcomp-$KEYMAN_VERSION.zip" function make-kmc-install-zip() { builder_heading make-kmc-install-zip diff --git a/developer/src/inst/kmdev.wxs b/developer/src/inst/kmdev.wxs index 1602f624ff..c57de43d82 100644 --- a/developer/src/inst/kmdev.wxs +++ b/developer/src/inst/kmdev.wxs @@ -2,7 +2,7 @@ + Name="Keyman Developer $(var.RELEASE)" Version="$(var.KEYMAN_VERSION)" Language="1033"> @@ -40,10 +40,10 @@ - - + Maximum="$(var.KEYMAN_VERSION)" IncludeMaximum="no" MigrateFeatures="yes" Property="VERSION11FOUND" /> + + @@ -309,7 +309,7 @@ - + diff --git a/developer/src/kmc/build.sh b/developer/src/kmc/build.sh index 29016300a2..15e8e18302 100755 --- a/developer/src/kmc/build.sh +++ b/developer/src/kmc/build.sh @@ -87,7 +87,7 @@ function do_bundle() { sentry-cli sourcemaps inject \ --org keyman \ --project keyman-developer \ - --release "$VERSION_GIT_TAG" \ + --release "$KEYMAN_VERSION_GIT_TAG" \ build/dist/ "${SOURCEMAP_PATHS[@]}" # Manually copy over kmcmplib module diff --git a/developer/src/server/src/site/lib/sentry/init.js.in b/developer/src/server/src/site/lib/sentry/init.js.in index 21ceba901b..dbaf0ea5c1 100644 --- a/developer/src/server/src/site/lib/sentry/init.js.in +++ b/developer/src/server/src/site/lib/sentry/init.js.in @@ -9,8 +9,8 @@ Sentry.init({ dsn: 'https://39b25a09410349a58fe12aaf721565af@o1005580.ingest.sentry.io/5983519', // Keyman Developer - environment: '$VERSION_ENVIRONMENT', - release: '$VERSION_GIT_TAG' + environment: '$KEYMAN_VERSION_ENVIRONMENT', + release: '$KEYMAN_VERSION_GIT_TAG' }); function keymanEnableDiagnostics() { diff --git a/developer/src/server/src/version-data.ts b/developer/src/server/src/version-data.ts index 79e930da2a..05f266c5c6 100644 --- a/developer/src/server/src/version-data.ts +++ b/developer/src/server/src/version-data.ts @@ -1,18 +1,18 @@ /* Version information from build-utils.sh: - # VERSION: Full current build version, e.g. "14.0.1" - # [VERSION_WIN: Full current build version for Windows, e.g. "14.0.1.0"] - # VERSION_RELEASE: Current release version, e.g. "14.0" - # VERSION_MAJOR: Major version, e.g. "14" - # VERSION_MINOR: Minor version, e.g. "0" - # VERSION_PATCH: Patch version, e.g. "1" - # TIER: Current tier, one of "alpha", "beta" or "stable" - # VERSION_TAG: Tier + Pull Request + Location of build [-alpha|-beta][-test[-1234]][-local] - # VERSION_WITH_TAG: e.g. "14.0.1-alpha-test-1234" or "14.0.5-beta-local" or "14.0.1-alpha-test" - # [KEYMAN_ROOT: fully resolved root path of Keyman repository] - # VERSION_ENVIRONMENT: One of: local, test, alpha, beta, stable - # VERSION_GIT_TAG: Git tag for the release, "release@$VERSION_WITH_TAG", e.g. "release@14.0.1-alpha-test-1234" + # KEYMAN_VERSION: Full current build version, e.g. "14.0.1" + # [KEYMAN_VERSION_WIN: Full current build version for Windows, e.g. "14.0.1.0"] + # KEYMAN_VERSION_RELEASE: Current release version, e.g. "14.0" + # KEYMAN_VERSION_MAJOR: Major version, e.g. "14" + # KEYMAN_VERSION_MINOR: Minor version, e.g. "0" + # KEYMAN_VERSION_PATCH: Patch version, e.g. "1" + # KEYMAN_TIER: Current tier, one of "alpha", "beta" or "stable" + # KEYMAN_VERSION_TAG: Tier + Pull Request + Location of build [-alpha|-beta][-test[-1234]][-local] + # KEYMAN_VERSION_WITH_TAG: e.g. "14.0.1-alpha-test-1234" or "14.0.5-beta-local" or "14.0.1-alpha-test" + # [KEYMAN_ROOT: fully resolved root path of Keyman repository] + # KEYMAN_VERSION_ENVIRONMENT: One of: local, test, alpha, beta, stable + # KEYMAN_VERSION_GIT_TAG: Git tag for the release, "release@$KEYMAN_VERSION_WITH_TAG", e.g. "release@14.0.1-alpha-test-1234" */ export interface Environment { diff --git a/developer/src/tike/xml/app/lib/sentry/init.js.in b/developer/src/tike/xml/app/lib/sentry/init.js.in index 21ceba901b..dbaf0ea5c1 100644 --- a/developer/src/tike/xml/app/lib/sentry/init.js.in +++ b/developer/src/tike/xml/app/lib/sentry/init.js.in @@ -9,8 +9,8 @@ Sentry.init({ dsn: 'https://39b25a09410349a58fe12aaf721565af@o1005580.ingest.sentry.io/5983519', // Keyman Developer - environment: '$VERSION_ENVIRONMENT', - release: '$VERSION_GIT_TAG' + environment: '$KEYMAN_VERSION_ENVIRONMENT', + release: '$KEYMAN_VERSION_GIT_TAG' }); function keymanEnableDiagnostics() { diff --git a/developer/src/tools/sentry-upload-difs.sh b/developer/src/tools/sentry-upload-difs.sh index b2368f54cc..34ab4c60b0 100755 --- a/developer/src/tools/sentry-upload-difs.sh +++ b/developer/src/tools/sentry-upload-difs.sh @@ -79,7 +79,7 @@ upload_sourcemap() { --no-dedupe \ --org keyman \ --project keyman-developer \ - --release "$VERSION_GIT_TAG" \ + --release "$KEYMAN_VERSION_GIT_TAG" \ --ext js --ext mjs --ext ts --ext map \ "$smpath" } diff --git a/docs/linux/packaging.md b/docs/linux/packaging.md index bb2763d686..d7d58fc977 100644 --- a/docs/linux/packaging.md +++ b/docs/linux/packaging.md @@ -98,8 +98,8 @@ You'll have to create the docker image. ```bash cd $KEYMAN_ROOT - TIER=$(cat TIER.md) - export TIER + KEYMAN_TIER=$(cat TIER.md) + export KEYMAN_TIER cd linux ./scripts/deb-packaging.sh source ``` @@ -149,13 +149,13 @@ for the different distros and architectures. To upload the packages to launchpad, run the following script from the `linux/` directory: ```bash -./scripts/launchpad.sh [UPLOAD="yes"] [TIER=""] [PROJECT=""] [DIST=""] [PACKAGEVERSION=""] +./scripts/launchpad.sh [UPLOAD="yes"] [KEYMAN_TIER=""] [PROJECT=""] [DIST=""] [PACKAGEVERSION=""] ``` #### Parameters - `UPLOAD="yes"` - do the dput for real -- `TIER=""` - alpha, beta, or stable, default from `../TIER.md` +- `KEYMAN_TIER=""` - alpha, beta, or stable, default from `../TIER.md` - `PROJECT=""` - only upload this package - `DIST=""` - only upload for this distribution - `PACKAGEVERSION=""` - normally use the default so don't specify diff --git a/ios/engine/build.sh b/ios/engine/build.sh index f6687f0a00..5a8d02b840 100755 --- a/ios/engine/build.sh +++ b/ios/engine/build.sh @@ -118,9 +118,9 @@ function build_engine() { echo echo "Build products will be set with the following version metadata:" - echo " * VERSION=$VERSION" - echo " * VERSION_WITH_TAG=$VERSION_WITH_TAG" - echo " * VERSION_ENVIRONMENT=$VERSION_ENVIRONMENT" + echo " * KEYMAN_VERSION=$KEYMAN_VERSION" + echo " * KEYMAN_VERSION_WITH_TAG=$KEYMAN_VERSION_WITH_TAG" + echo " * KEYMAN_VERSION_ENVIRONMENT=$KEYMAN_VERSION_ENVIRONMENT" echo " * UPLOAD_SENTRY=$UPLOAD_SENTRY" echo echo "Building KMEI..." @@ -130,9 +130,9 @@ function build_engine() { run_xcodebuild $XCODEFLAGS_EXT \ $CODE_SIGN \ -scheme KME-universal \ - VERSION=$VERSION \ - VERSION_WITH_TAG=$VERSION_WITH_TAG \ - VERSION_ENVIRONMENT=$VERSION_ENVIRONMENT \ + KEYMAN_VERSION=$KEYMAN_VERSION \ + KEYMAN_VERSION_WITH_TAG=$KEYMAN_VERSION_WITH_TAG \ + KEYMAN_VERSION_ENVIRONMENT=$KEYMAN_VERSION_ENVIRONMENT \ UPLOAD_SENTRY=$UPLOAD_SENTRY assertDirExists "$KEYMAN_XCFRAMEWORK" diff --git a/ios/keyman/build.sh b/ios/keyman/build.sh index 1f5aa57b19..cc43d42e60 100755 --- a/ios/keyman/build.sh +++ b/ios/keyman/build.sh @@ -87,9 +87,9 @@ function build_app() { -archivePath "$ARCHIVE_PATH" \ archive \ -allowProvisioningUpdates \ - VERSION=$VERSION \ - VERSION_WITH_TAG=$VERSION_WITH_TAG \ - VERSION_ENVIRONMENT=$VERSION_ENVIRONMENT \ + KEYMAN_VERSION=$KEYMAN_VERSION \ + KEYMAN_VERSION_WITH_TAG=$KEYMAN_VERSION_WITH_TAG \ + KEYMAN_VERSION_ENVIRONMENT=$KEYMAN_VERSION_ENVIRONMENT \ UPLOAD_SENTRY=$UPLOAD_SENTRY assertDirExists "$ARCHIVE_PATH" @@ -112,13 +112,13 @@ function build_app() { $CODE_SIGN \ -scheme Keyman \ -sdk iphonesimulator \ - VERSION=$VERSION \ - VERSION_WITH_TAG=$VERSION_WITH_TAG \ - VERSION_ENVIRONMENT=$VERSION_ENVIRONMENT \ + KEYMAN_VERSION=$KEYMAN_VERSION \ + KEYMAN_VERSION_WITH_TAG=$KEYMAN_VERSION_WITH_TAG \ + KEYMAN_VERSION_ENVIRONMENT=$KEYMAN_VERSION_ENVIRONMENT \ UPLOAD_SENTRY=$UPLOAD_SENTRY fi } builder_run_action clean do_clean builder_run_action configure do_configure -builder_run_action build build_app \ No newline at end of file +builder_run_action build build_app diff --git a/ios/scripts/kme-universal.sh b/ios/scripts/kme-universal.sh index 57d9280996..ab61a5b7ce 100755 --- a/ios/scripts/kme-universal.sh +++ b/ios/scripts/kme-universal.sh @@ -38,9 +38,9 @@ build_archive ( ) { -quiet \ BUILD_DIR="${BUILD_DIR}" \ BUILD_ROOT="${BUILD_ROOT}" \ - VERSION=$VERSION \ - VERSION_WITH_TAG=$VERSION_WITH_TAG \ - VERSION_ENVIRONMENT=$VERSION_ENVIRONMENT \ + KEYMAN_VERSION=$KEYMAN_VERSION \ + KEYMAN_VERSION_WITH_TAG=$KEYMAN_VERSION_WITH_TAG \ + KEYMAN_VERSION_ENVIRONMENT=$KEYMAN_VERSION_ENVIRONMENT \ UPLOAD_SENTRY=$UPLOAD_SENTRY } @@ -72,4 +72,4 @@ run_xcodebuild -create-xcframework \ -allow-internal-distribution \ -framework ${IPHONE_FRAMEWORK} \ -framework ${SIMULATOR_FRAMEWORK} \ - -output ${XCFRAMEWORK} \ No newline at end of file + -output ${XCFRAMEWORK} diff --git a/ios/tools/prepRelease.sh b/ios/tools/prepRelease.sh index 0da59d2174..22e580555e 100755 --- a/ios/tools/prepRelease.sh +++ b/ios/tools/prepRelease.sh @@ -28,9 +28,9 @@ fi #. ../resources/shellHelperFunctions.sh BUILD_NUMBER=`cat ../VERSION.md` -TIER=`cat ../TIER.md` +KEYMAN_TIER=`cat ../TIER.md` -KEYMAN_CHANGELOG="changelog-${BUILD_NUMBER}-${TIER}.txt" +KEYMAN_CHANGELOG="changelog-${BUILD_NUMBER}-${KEYMAN_TIER}.txt" CHANGELOG_PATH="upload/$BUILD_NUMBER/$KEYMAN_CHANGELOG" WORK_DIR=`pwd` @@ -46,7 +46,7 @@ mkdir -p "${UPLOAD_DIR}" # First, we prep the files for publication: write changelog echo "Writing changelog to $CHANGELOG_PATH" -get_version_notes "ios" "${BUILD_NUMBER}" "$TIER" > $CHANGELOG_PATH +get_version_notes "ios" "${BUILD_NUMBER}" "$KEYMAN_TIER" > $CHANGELOG_PATH echo "* Minor fixes and performance improvements" >> $CHANGELOG_PATH assertFileExists "${CHANGELOG_PATH}" @@ -128,9 +128,9 @@ fi cd "${UPLOAD_DIR}" -write_download_info "Keyman Engine for iOS" "${KMEI_DST_NAME}" "${BUILD_NUMBER}" "${TIER}" "ios" -write_download_info "Keyman for iPhone and iPad" "${KEYMANAPP_IPA_DST}" "${BUILD_NUMBER}" "${TIER}" "ios" +write_download_info "Keyman Engine for iOS" "${KMEI_DST_NAME}" "${BUILD_NUMBER}" "${KEYMAN_TIER}" "ios" +write_download_info "Keyman for iPhone and iPad" "${KEYMANAPP_IPA_DST}" "${BUILD_NUMBER}" "${KEYMAN_TIER}" "ios" if [ ${RELEASE_OEM_FIRSTVOICES} = true ]; then - write_download_info "FirstVoices Keyboards" "${FIRSTVOICESAPP_IPA_DST}" "${BUILD_NUMBER}" "${TIER}" "ios" + write_download_info "FirstVoices Keyboards" "${FIRSTVOICESAPP_IPA_DST}" "${BUILD_NUMBER}" "${KEYMAN_TIER}" "ios" fi diff --git a/linux/ibus-keyman/src/keyman-version.h.in b/linux/ibus-keyman/src/keyman-version.h.in index c842f9557a..eb6cb79785 100644 --- a/linux/ibus-keyman/src/keyman-version.h.in +++ b/linux/ibus-keyman/src/keyman-version.h.in @@ -1,5 +1,5 @@ #ifndef __KEYMAN_VERSION_H__ #define __KEYMAN_VERSION_H__ -#define KEYMAN_VERSION "@VERSION@" +#define KEYMAN_VERSION "@KEYMAN_VERSION@" #endif diff --git a/linux/ibus-keyman/src/keyman.xml.in b/linux/ibus-keyman/src/keyman.xml.in index 5b958e78b5..8a7aeb3d2a 100644 --- a/linux/ibus-keyman/src/keyman.xml.in +++ b/linux/ibus-keyman/src/keyman.xml.in @@ -3,7 +3,7 @@ org.freedesktop.IBus.Keyman Keyman Component @LIBEXECDIR@/ibus-engine-keyman --ibus - @VERSION@ + @KEYMAN_VERSION@ Keyman Team <support@keyman.com> GPL https://keyman.com diff --git a/linux/ibus-keyman/src/meson.build b/linux/ibus-keyman/src/meson.build index 13b3caafc0..1f77fdb765 100644 --- a/linux/ibus-keyman/src/meson.build +++ b/linux/ibus-keyman/src/meson.build @@ -21,7 +21,7 @@ deps = [gtk, ibus, icu, json_glib, keymancore_lib, systemd] prefix = get_option('prefix') cfg = configuration_data() -cfg.set('VERSION', meson.project_version()) +cfg.set('KEYMAN_VERSION', meson.project_version()) cfg.set('LIBEXECDIR', get_option('prefix') / get_option('libexecdir')) configure_file( diff --git a/linux/keyman-config/Makefile b/linux/keyman-config/Makefile index ad5b0d2c53..b75c6b17ab 100644 --- a/linux/keyman-config/Makefile +++ b/linux/keyman-config/Makefile @@ -24,8 +24,8 @@ dist: clean version fi deb: dist - @VERSION=$(shell echo `basename dist/*.gz .tar.gz|cut -d "-" -f2` > /tmp/keyman_version) - @echo VERSION is $(shell cat /tmp/keyman_version) + @KEYMAN_VERSION=$(shell echo `basename dist/*.gz .tar.gz|cut -d "-" -f2` > /tmp/keyman_version) + @echo KEYMAN_VERSION is $(shell cat /tmp/keyman_version) @mkdir -p make_deb cd make_deb && tar xf ../dist/keyman_config-$(shell cat /tmp/keyman_version).tar.gz && \ mv keyman_config-$(shell cat /tmp/keyman_version) keyman-config-$(shell cat /tmp/keyman_version) && \ @@ -41,7 +41,7 @@ version_reconf: cd .. && ./scripts/reconf.sh version: version_reconf - $(eval VERSION := $(shell python3 -c "from keyman_config import __releaseversion__; print(__releaseversion__)")) + $(eval KEYMAN_VERSION := $(shell python3 -c "from keyman_config import __releaseversion__; print(__releaseversion__)")) # i18n @@ -49,7 +49,7 @@ POFILES := $(shell find locale -name \*.po) MOFILES := $(POFILES:.po=/LC_MESSAGES/keyman-config.mo) update-template: version - xgettext --package-name "keyman" --package-version "$(VERSION)" \ + xgettext --package-name "keyman" --package-version "$(KEYMAN_VERSION)" \ --msgid-bugs-address "" --copyright-holder "SIL Global" \ --language=Python --directory=. --output-dir=locale --output=keyman-config.pot \ --add-comments=i18n: --sort-by-file --width=98 \ diff --git a/linux/keyman-config/build.sh b/linux/keyman-config/build.sh index b4b4bd0377..0eccb04b13 100755 --- a/linux/keyman-config/build.sh +++ b/linux/keyman-config/build.sh @@ -62,14 +62,14 @@ build_action() { builder_echo "Create version.py" pushd keyman_config sed \ - -e "s/_VERSION_/${VERSION}/g" \ - -e "s/_VERSIONWITHTAG_/${VERSION_WITH_TAG}/g" \ - -e "s/_VERSIONGITTAG_/${VERSION_GIT_TAG}/g" \ - -e "s/_MAJORVERSION_/${VERSION_MAJOR}/g" \ - -e "s/_RELEASEVERSION_/${VERSION_RELEASE}/g" \ - -e "s/_TIER_/${TIER}/g" \ - -e "s/_ENVIRONMENT_/${VERSION_ENVIRONMENT}/g" \ - -e "s/_UPLOADSENTRY_/${UPLOAD_SENTRY}/g" \ + -e "s/_KEYMAN_VERSION_/${KEYMAN_VERSION}/g" \ + -e "s/_KEYMAN_VERSION_WITH_TAG_/${KEYMAN_VERSION_WITH_TAG}/g" \ + -e "s/_KEYMAN_VERSION_GIT_TAG_/${KEYMAN_VERSION_GIT_TAG}/g" \ + -e "s/_KEYMAN_VERSION_MAJOR_/${KEYMAN_VERSION_MAJOR}/g" \ + -e "s/_KEYMAN_VERSION_RELEASE_/${KEYMAN_VERSION_RELEASE}/g" \ + -e "s/_KEYMAN_TIER_/${KEYMAN_TIER}/g" \ + -e "s/_KEYMAN_VERSION_ENVIRONMENT_/${KEYMAN_VERSION_ENVIRONMENT}/g" \ + -e "s/_UPLOAD_SENTRY_/${UPLOAD_SENTRY}/g" \ version.py.in > version.py popd pushd buildtools diff --git a/linux/keyman-config/keyman_config/version.py.in b/linux/keyman-config/keyman_config/version.py.in index f611bfc75a..3221a6ddff 100644 --- a/linux/keyman-config/keyman_config/version.py.in +++ b/linux/keyman-config/keyman_config/version.py.in @@ -4,12 +4,12 @@ # 1) we don't load dependencies by storing it in __init__.py # 2) we can import it in setup.py for the same reason # 3) we can import it into your module module -__version__ = "_VERSION_" -__versionwithtag__ = "_VERSIONWITHTAG_" -__majorversion__ = "_MAJORVERSION_" -__releaseversion__ = "_RELEASEVERSION_" -__tier__ = "_TIER_" +__version__ = "_KEYMAN_VERSION_" +__versionwithtag__ = "_KEYMAN_VERSION_WITH_TAG_" +__majorversion__ = "_KEYMAN_VERSION_MAJOR_" +__releaseversion__ = "_KEYMAN_VERSION_RELEASE_" +__tier__ = "_KEYMAN_TIER_" __pkgversion__ = "(local)" -__environment__ = "_ENVIRONMENT_" -__uploadsentry__ = "_UPLOADSENTRY_" -__versiongittag__ = "_VERSIONGITTAG_" \ No newline at end of file +__environment__ = "_KEYMAN_VERSION_ENVIRONMENT_" +__uploadsentry__ = "_UPLOAD_SENTRY_" +__versiongittag__ = "_KEYMAN_VERSION_GIT_TAG_" diff --git a/linux/keyman-system-service/resources/VERSION_WITH_TAG.md b/linux/keyman-system-service/resources/VERSION_WITH_TAG.md new file mode 100644 index 0000000000..6a37350605 --- /dev/null +++ b/linux/keyman-system-service/resources/VERSION_WITH_TAG.md @@ -0,0 +1 @@ +19.0.32-alpha-local diff --git a/linux/scripts/dist.sh b/linux/scripts/dist.sh index 1b8f0dee87..33bf0a1091 100755 --- a/linux/scripts/dist.sh +++ b/linux/scripts/dist.sh @@ -29,7 +29,7 @@ mkdir -p dist cp -a debian ../ cd .. echo "3.0 (native)" > debian/source/format -dch keyman --newversion "${VERSION}" --force-bad-version --nomultimaint +dch keyman --newversion "${KEYMAN_VERSION}" --force-bad-version --nomultimaint # Create the tarball # Note: the files end up in subdirectories under `keyman`, so we can @@ -87,17 +87,17 @@ dpkg-source \ --tar-ignore=keyman/windows \ \ -Zgzip -b . -mv ../keyman_"${VERSION}".tar.gz linux/dist/keyman-"${VERSION}".tar.gz +mv ../keyman_"${KEYMAN_VERSION}".tar.gz linux/dist/keyman-"${KEYMAN_VERSION}".tar.gz echo "3.0 (quilt)" > debian/source/format cd "${BASEDIR}" # create orig.tar.gz if [[ ! -z "${create_origdist+x}" ]]; then cd dist - pkgvers="keyman-$VERSION" - tar xfz keyman-"${VERSION}".tar.gz + pkgvers="keyman-$KEYMAN_VERSION" + tar xfz keyman-"${KEYMAN_VERSION}".tar.gz mv -v keyman "${pkgvers}" 2>/dev/null || mv -v "$(find . -mindepth 1 -maxdepth 1 -type d)" "${pkgvers}" - tar cfz "keyman_${VERSION}.orig.tar.gz" "${pkgvers}" - rm "keyman-${VERSION}.tar.gz" + tar cfz "keyman_${KEYMAN_VERSION}.orig.tar.gz" "${pkgvers}" + rm "keyman-${KEYMAN_VERSION}.tar.gz" rm -rf "${pkgvers}" fi diff --git a/linux/scripts/launchpad.sh b/linux/scripts/launchpad.sh index 4b89980994..a2139f4a5c 100755 --- a/linux/scripts/launchpad.sh +++ b/linux/scripts/launchpad.sh @@ -24,9 +24,9 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" checkPrerequisites -if [ "${TIER}" == "stable" ]; then +if [ "${KEYMAN_TIER}" == "stable" ]; then ppa="ppa:keymanapp/keyman" -elif [ "${TIER}" == "beta" ]; then +elif [ "${KEYMAN_TIER}" == "beta" ]; then ppa="ppa:keymanapp/keyman-beta" else ppa="ppa:keymanapp/keyman-alpha" diff --git a/linux/scripts/package-build.inc.sh b/linux/scripts/package-build.inc.sh index 79ce92644e..450ba5f832 100644 --- a/linux/scripts/package-build.inc.sh +++ b/linux/scripts/package-build.inc.sh @@ -8,8 +8,8 @@ function checkPrerequisites() { fi # Check the tier - if [[ -z "${TIER:=}" ]]; then - echo "TIER.md or \${TIER} must be set to (alpha, beta, stable) to use this script" + if [[ -z "${KEYMAN_TIER:=}" ]]; then + echo "TIER.md or \${KEYMAN_TIER} must be set to (alpha, beta, stable) to use this script" exit 1 fi @@ -32,7 +32,7 @@ function downloadSource() { fi # Update tier in Debian watch files (replacing any previously set tier) and remove comment - sed -e "s/\$tier\|alpha\|beta\|stable/${TIER}/g" -e "s/^# .*$//" "$BASEDIR"/scripts/watch.in > debian/watch + sed -e "s/\$tier\|alpha\|beta\|stable/${KEYMAN_TIER}/g" -e "s/^# .*$//" "$BASEDIR"/scripts/watch.in > debian/watch version=$(uscan --report --dehs|xmllint --xpath "//dehs/upstream-version/text()" -) dirversion=$(uscan --report --dehs|xmllint --xpath "//dehs/upstream-url/text()" - | cut -d/ -f6) @@ -45,7 +45,7 @@ function downloadSource() { mv "${proj}"*.asc "${BASEDIR}/${packageDir}" rm "${proj}"*.debian.tar.xz cd "${BASEDIR}/${packageDir}" || exit - wget -N "https://downloads.keyman.com/linux/${TIER}/${dirversion}/SHA256SUMS" + wget -N "https://downloads.keyman.com/linux/${KEYMAN_TIER}/${dirversion}/SHA256SUMS" sha256sum -c --ignore-missing SHA256SUMS |grep "${proj}" } diff --git a/linux/scripts/reconf.sh b/linux/scripts/reconf.sh index c05148a818..da1610545b 100755 --- a/linux/scripts/reconf.sh +++ b/linux/scripts/reconf.sh @@ -11,7 +11,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" BASEDIR="$KEYMAN_ROOT/linux" echo "basedir is $BASEDIR" -echo "Found tier ${TIER}, version ${VERSION}" +echo "Found tier ${KEYMAN_TIER}, version ${KEYMAN_VERSION}" # We need to configure+build core before we can configure ibus-keyman cd ../core @@ -32,14 +32,14 @@ quilt new version_py.diff quilt add "version.py" sed \ - -e "s/_VERSION_/${VERSION}/g" \ - -e "s/_VERSIONWITHTAG_/${VERSION_WITH_TAG}/g" \ - -e "s/_VERSIONGITTAG_/${VERSION_GIT_TAG}/g" \ - -e "s/_MAJORVERSION_/${VERSION_MAJOR}/g" \ - -e "s/_RELEASEVERSION_/${VERSION_RELEASE}/g" \ - -e "s/_TIER_/${TIER}/g" \ - -e "s/_ENVIRONMENT_/${VERSION_ENVIRONMENT}/g" \ - -e "s/_UPLOADSENTRY_/${UPLOAD_SENTRY}/g" \ + -e "s/_KEYMAN_VERSION_/${KEYMAN_VERSION}/g" \ + -e "s/_KEYMAN_VERSION_WITH_TAG_/${KEYMAN_VERSION_WITH_TAG}/g" \ + -e "s/_KEYMAN_VERSION_GIT_TAG_/${KEYMAN_VERSION_GIT_TAG}/g" \ + -e "s/_KEYMAN_VERSION_MAJOR_/${KEYMAN_VERSION_MAJOR}/g" \ + -e "s/_KEYMAN_VERSION_RELEASE_/${KEYMAN_VERSION_RELEASE}/g" \ + -e "s/_KEYMAN_TIER_/${KEYMAN_TIER}/g" \ + -e "s/_KEYMAN_VERSION_ENVIRONMENT_/${KEYMAN_VERSION_ENVIRONMENT}/g" \ + -e "s/_UPLOAD_SENTRY_/${UPLOAD_SENTRY}/g" \ version.py.in > version.py quilt refresh quilt pop -a diff --git a/linux/scripts/test/test.inc.sh b/linux/scripts/test/test.inc.sh index 6e21ef2b5d..16c0bda2f7 100644 --- a/linux/scripts/test/test.inc.sh +++ b/linux/scripts/test/test.inc.sh @@ -20,7 +20,7 @@ mockDebPkgTools() { } createBase() { - TIER=$1 + KEYMAN_TIER=$1 remoteDir=$(mktemp -d) cd "${remoteDir}" git init --bare --initial-branch=master . @@ -68,7 +68,7 @@ createBase() { git tag -m "16.0.145" release-16.0.145 git push origin release-16.0.145 - echo "${TIER}" > TIER.md + echo "${KEYMAN_TIER}" > TIER.md git add TIER.md echo "17.0.255" > VERSION.md diff --git a/linux/scripts/verify_api.inc.sh b/linux/scripts/verify_api.inc.sh index 8334bc84b8..0caaa6d23f 100644 --- a/linux/scripts/verify_api.inc.sh +++ b/linux/scripts/verify_api.inc.sh @@ -32,7 +32,7 @@ check_api_not_changed() { trap "rm -rf \"${tmpDir}\"" ERR dpkg -x "${BIN_PKG}" "${tmpDir}" mkdir -p debian/tmp/DEBIAN - if dpkg-gensymbols -v"${VERSION}" -p"${PKG_NAME}" -e"${tmpDir}"/usr/lib/x86_64-linux-gnu/"${LIB_NAME}".so* -c4; then + if dpkg-gensymbols -v"${KEYMAN_VERSION}" -p"${PKG_NAME}" -e"${tmpDir}"/usr/lib/x86_64-linux-gnu/"${LIB_NAME}".so* -c4; then output_ok "${LIB_NAME} API didn't change" else output_error "${LIB_NAME} API changed" @@ -205,7 +205,7 @@ get_api_version_from_core() { # NOTE: it is up to the caller to check if this is a major version # change that requires an API version update. is_api_version_updated() { - local OLD_API_VERSION NEW_API_VERSION TIER + local OLD_API_VERSION NEW_API_VERSION KEYMAN_TIER OLD_API_VERSION=$(get_api_version_in_symbols_file "${GIT_BASE}") NEW_API_VERSION=$(get_api_version_in_symbols_file "${GIT_SHA}") if (( NEW_API_VERSION > OLD_API_VERSION )); then @@ -215,11 +215,11 @@ is_api_version_updated() { # API version didn't change. However, that might be ok if we're in alpha # and a major change happened previously. - TIER=$(cat "${REPO_ROOT}/TIER.md") - case ${TIER} in + KEYMAN_TIER=$(cat "${REPO_ROOT}/TIER.md") + case ${KEYMAN_TIER} in alpha) local STABLE_VERSION STABLE_API_VERSION STABLE_BRANCH - STABLE_VERSION=$((${VERSION%%.*} - 1)) + STABLE_VERSION=$((${KEYMAN_VERSION%%.*} - 1)) STABLE_BRANCH="origin/stable-${STABLE_VERSION}.0" STABLE_API_VERSION=$(get_api_version_in_symbols_file "${STABLE_BRANCH}") if (( STABLE_API_VERSION == -1 )); then diff --git a/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj b/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj index ad57bfbd66..89bbfb022e 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj +++ b/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj @@ -954,7 +954,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# check that our PRODUCT_VERSION matches this git branch's VERSION from ../../VERSION.md\n(cd .. ; ./is_same_version.sh Keyman4MacIM || exit 1 ; cd -)\n"; + shellScript = "# check that our PRODUCT_VERSION matches this git branch's KEYMAN_VERSION from ../../VERSION.md\n(cd .. ; ./is_same_version.sh Keyman4MacIM || exit 1 ; cd -)\n"; showEnvVarsInLog = 0; }; D2FF67BB6C749BA6861F5E25 /* [CP] Check Pods Manifest.lock */ = { diff --git a/mac/Keyman4MacIM/make-km-dmg.sh b/mac/Keyman4MacIM/make-km-dmg.sh index f51f5dc02a..84d09312c1 100755 --- a/mac/Keyman4MacIM/make-km-dmg.sh +++ b/mac/Keyman4MacIM/make-km-dmg.sh @@ -110,7 +110,7 @@ while [[ $# -gt 0 ]] ; do done # Step 0 - check parameter and initial file state -if [ "$VERSION" = "" ]; then +if [ "$KEYMAN_VERSION" = "" ]; then builder_die "Required -version parameter not specified!" fi @@ -129,7 +129,7 @@ elif [[ ! -d "$OUTPUT_DIR" ]]; then fi if $ADD_VERSION_TO_DEST_DIR ; then - DEST_DIR="$DEST_DIR/$VERSION" + DEST_DIR="$DEST_DIR/$KEYMAN_VERSION" fi if [[ ! -e "$DEST_DIR" ]]; then mkdir -p "$DEST_DIR" @@ -140,7 +140,7 @@ fi # TODO: Check that no Keyman volume is already mounted. # Step 1 - Copy template to working copy to prevent unintended changes -WORKING_COPY_OF_IMAGE="$OUTPUT_DIR/Keyman-temp-$VERSION.dmg" +WORKING_COPY_OF_IMAGE="$OUTPUT_DIR/Keyman-temp-$KEYMAN_VERSION.dmg" displayInfo "Copying \"$TEMPLATE_IMAGE\" to \"$WORKING_COPY_OF_IMAGE\"..." if [[ -e "$WORKING_COPY_OF_IMAGE" && "$VERBOSITY" != "-quiet" ]] ; then builder_warn "Overwriting: $WORKING_COPY_OF_IMAGE" @@ -212,7 +212,7 @@ if (( DETACH_SUCCESS < 999 )); then fi # Step 5 - Convert image to a compressed readonly DMG image -DMG_FILE_PATH="$DEST_DIR/keyman-$VERSION.dmg" +DMG_FILE_PATH="$DEST_DIR/keyman-$KEYMAN_VERSION.dmg" displayInfo "Converting/compressing image to create \"$DMG_FILE_PATH\"" if [[ -e "$DMG_FILE_PATH" ]] ; then if [[ "$VERBOSITY" != "-quiet" ]] ; then @@ -230,4 +230,4 @@ displayInfo "Cleaning up..." rm "$WORKING_COPY_OF_IMAGE" displayInfo "Make DMG completed successfully." -exit 0 \ No newline at end of file +exit 0 diff --git a/mac/Keyman4MacIM/write-download_info.sh b/mac/Keyman4MacIM/write-download_info.sh index b8fa5e6952..656d0ce385 100755 --- a/mac/Keyman4MacIM/write-download_info.sh +++ b/mac/Keyman4MacIM/write-download_info.sh @@ -39,7 +39,7 @@ popd > /dev/null DEST_DIR="$KEYMAN_MACIM_BASE_PATH/output/upload" ADD_VERSION_TO_DEST_DIR=true -KM_BLD_COUNTER="$((${VERSION##*.}))" +KM_BLD_COUNTER="$((${KEYMAN_VERSION##*.}))" # Parse args shopt -s nocasematch @@ -67,7 +67,7 @@ while [[ $# -gt 0 ]] ; do done if $ADD_VERSION_TO_DEST_DIR ; then - DEST_DIR="$DEST_DIR/$VERSION" + DEST_DIR="$DEST_DIR/$KEYMAN_VERSION" fi if [[ ! -e $DEST_DIR ]]; then mkdir -p $DEST_DIR @@ -75,7 +75,7 @@ elif [[ ! -d $DEST_DIR ]]; then builder_die "Destination dir exists but is not a directory: $2" fi -DMG_FILENAME="keyman-$VERSION.dmg" +DMG_FILENAME="keyman-$KEYMAN_VERSION.dmg" DMG_FILEPATH="$DEST_DIR/$DMG_FILENAME" DOWNLOAD_INFO_FILEPATH="${DMG_FILEPATH}.download_info" if [[ ! -f "$DMG_FILEPATH" ]]; then @@ -90,10 +90,10 @@ fi echo { > "$DOWNLOAD_INFO_FILEPATH" echo " \"name\": \"Keyman4MacIM\"," >> "$DOWNLOAD_INFO_FILEPATH" -echo " \"version\": \"${VERSION}\"," >> "$DOWNLOAD_INFO_FILEPATH" +echo " \"version\": \"${KEYMAN_VERSION}\"," >> "$DOWNLOAD_INFO_FILEPATH" echo " \"date\": \"$(date "+%Y-%m-%d")\"," >> "$DOWNLOAD_INFO_FILEPATH" echo " \"platform\": \"mac\"," >> "$DOWNLOAD_INFO_FILEPATH" -echo " \"stability\": \"${TIER}\"," >> "$DOWNLOAD_INFO_FILEPATH" +echo " \"stability\": \"${KEYMAN_TIER}\"," >> "$DOWNLOAD_INFO_FILEPATH" echo " \"file\": \"${DMG_FILENAME}\"," >> "$DOWNLOAD_INFO_FILEPATH" echo " \"md5\": \"${DMG_MD5}\"," >> "$DOWNLOAD_INFO_FILEPATH" echo " \"type\": \"dmg\"," >> "$DOWNLOAD_INFO_FILEPATH" @@ -101,4 +101,4 @@ echo " \"build\": \"${KM_BLD_COUNTER}\"," >> "$DOWNLOAD_INFO_FILEPATH" echo " \"size\": \"${DMG_FILE_SIZE}\"" >> "$DOWNLOAD_INFO_FILEPATH" echo } >> "$DOWNLOAD_INFO_FILEPATH" -exit 0 \ No newline at end of file +exit 0 diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac.xcodeproj/project.pbxproj b/mac/KeymanEngine4Mac/KeymanEngine4Mac.xcodeproj/project.pbxproj index f87288a953..aafac72d49 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac.xcodeproj/project.pbxproj +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac.xcodeproj/project.pbxproj @@ -494,7 +494,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# check that our PRODUCT_VERSION matches this git branch's VERSION from ../../VERSION.md\n(cd .. ; ./is_same_version.sh KeymanEngine4Mac || exit 1 ; cd -)\n"; + shellScript = "# check that our PRODUCT_VERSION matches this git branch's KEYMAN_VERSION from ../../VERSION.md\n(cd .. ; ./is_same_version.sh KeymanEngine4Mac || exit 1 ; cd -)\n"; showEnvVarsInLog = 0; }; E2588F2F1F2647A50061C9C4 /* ShellScript */ = { diff --git a/mac/build.sh b/mac/build.sh index 77e1596744..db61eed053 100755 --- a/mac/build.sh +++ b/mac/build.sh @@ -97,7 +97,7 @@ if [[ -f "$THIS_SCRIPT_PATH/localenv.sh" ]]; then . "$THIS_SCRIPT_PATH/localenv.sh" fi -BUILD_OPTIONS="-configuration $CONFIG $BUILD_OPTIONS PRODUCT_VERSION=$VERSION" +BUILD_OPTIONS="-configuration $CONFIG $BUILD_OPTIONS PRODUCT_VERSION=$KEYMAN_VERSION" ### START OF THE BUILD ### @@ -151,16 +151,16 @@ updatePlist() { builder_die "File not found: $KM_PLIST" fi local YEAR=`date "+%Y"` - echo "Setting version and related fields to $VERSION_WITH_TAG in $KM_PLIST" - /usr/libexec/Plistbuddy -c "Set CFBundleVersion $VERSION" "$KM_PLIST" - /usr/libexec/Plistbuddy -c "Set CFBundleShortVersionString $VERSION" "$KM_PLIST" - /usr/libexec/Plistbuddy -c "Set :Keyman:SentryEnvironment $VERSION_ENVIRONMENT" "$KM_PLIST" - /usr/libexec/Plistbuddy -c "Set :Keyman:Tier $TIER" "$KM_PLIST" - /usr/libexec/Plistbuddy -c "Set :Keyman:VersionTag $VERSION_TAG" "$KM_PLIST" - /usr/libexec/Plistbuddy -c "Set :Keyman:VersionWithTag $VERSION_WITH_TAG" "$KM_PLIST" - /usr/libexec/Plistbuddy -c "Set :Keyman:VersionGitTag $VERSION_GIT_TAG" "$KM_PLIST" - /usr/libexec/Plistbuddy -c "Set :Keyman:VersionRelease $VERSION_RELEASE" "$KM_PLIST" - /usr/libexec/Plistbuddy -c "Set CFBundleGetInfoString $APPNAME $VERSION_WITH_TAG for macOS, Copyright © 2017-$YEAR SIL International." "$KM_PLIST" + echo "Setting version and related fields to $KEYMAN_VERSION_WITH_TAG in $KM_PLIST" + /usr/libexec/Plistbuddy -c "Set CFBundleVersion $KEYMAN_VERSION" "$KM_PLIST" + /usr/libexec/Plistbuddy -c "Set CFBundleShortVersionString $KEYMAN_VERSION" "$KM_PLIST" + /usr/libexec/Plistbuddy -c "Set :Keyman:SentryEnvironment $KEYMAN_VERSION_ENVIRONMENT" "$KM_PLIST" + /usr/libexec/Plistbuddy -c "Set :Keyman:Tier $KEYMAN_TIER" "$KM_PLIST" + /usr/libexec/Plistbuddy -c "Set :Keyman:VersionTag $KEYMAN_VERSION_TAG" "$KM_PLIST" + /usr/libexec/Plistbuddy -c "Set :Keyman:VersionWithTag $KEYMAN_VERSION_WITH_TAG" "$KM_PLIST" + /usr/libexec/Plistbuddy -c "Set :Keyman:VersionGitTag $KEYMAN_VERSION_GIT_TAG" "$KM_PLIST" + /usr/libexec/Plistbuddy -c "Set :Keyman:VersionRelease $KEYMAN_VERSION_RELEASE" "$KM_PLIST" + /usr/libexec/Plistbuddy -c "Set CFBundleGetInfoString $APPNAME $KEYMAN_VERSION_WITH_TAG for macOS, Copyright © 2017-$YEAR SIL International." "$KM_PLIST" /usr/libexec/Plistbuddy -c "Set NSHumanReadableCopyright Copyright © 2017-$YEAR SIL International." "$KM_PLIST" fi } @@ -321,4 +321,4 @@ builder_run_action build:testapp do_build_testapp builder_run_action install do_install -builder_run_action publish do_publish \ No newline at end of file +builder_run_action publish do_publish diff --git a/mac/is_same_version.sh b/mac/is_same_version.sh index 024902317f..da9daf1610 100755 --- a/mac/is_same_version.sh +++ b/mac/is_same_version.sh @@ -41,15 +41,15 @@ echo $PROJ_PROD_VERSION_LINE | sed /\ /s///g > ./PROJ_VERSION.md . ./PROJ_VERSION.md echo Product version in the project file PRODUCT_VERSION is $PRODUCT_VERSION -echo Keyman version VERSION is $VERSION +echo Keyman version VERSION is $KEYMAN_VERSION -if [ x$VERSION = x$PRODUCT_VERSION ] +if [ x$KEYMAN_VERSION = x$PRODUCT_VERSION ] then echo the versions are the same, all is well. # clean up rm ./PROJ_VERSION.md exit 0 else - echo the version $VERSION and $PRODUCT_VERSION are NOT the same! + echo the version $KEYMAN_VERSION and $PRODUCT_VERSION are NOT the same! exit 1 fi diff --git a/oem/firstvoices/android/app/build.gradle b/oem/firstvoices/android/app/build.gradle index 95bbcf2fa2..5c014021a6 100644 --- a/oem/firstvoices/android/app/build.gradle +++ b/oem/firstvoices/android/app/build.gradle @@ -16,11 +16,11 @@ android { minSdkVersion 21 targetSdkVersion 34 - // VERSION_CODE and VERSION_NAME from version.gradle - versionCode VERSION_CODE as Integer - versionName VERSION_NAME - buildConfigField "String", "VERSION_ENVIRONMENT", "\""+VERSION_ENVIRONMENT+"\"" - buildConfigField "String", "VERSION_GIT_TAG", "\""+VERSION_GIT_TAG+"\"" + // KEYMAN_VERSION_CODE and KEYMAN_VERSION_NAME from version.gradle + versionCode KEYMAN_VERSION_CODE as Integer + versionName KEYMAN_VERSION_NAME + buildConfigField "String", "KEYMAN_VERSION_ENVIRONMENT", "\""+KEYMAN_VERSION_ENVIRONMENT+"\"" + buildConfigField "String", "KEYMAN_VERSION_GIT_TAG", "\""+KEYMAN_VERSION_GIT_TAG+"\"" } String env_release_store_file = System.getenv("oem_firstvoices_release_store_file") @@ -55,9 +55,9 @@ android { } applicationVariants.all { variant -> - // Adjust output name to "firstvoices-${VERSION_MD}.apk" + // Adjust output name to "firstvoices-${KEYMAN_VERSION_MD}.apk" variant.outputs.all { - outputFileName = "firstvoices-" + VERSION_MD + ".apk" + outputFileName = "firstvoices-" + KEYMAN_VERSION_MD + ".apk" } } lintOptions { diff --git a/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/MainActivity.java b/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/MainActivity.java index d38d5b9bc0..01086ebf73 100644 --- a/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/MainActivity.java +++ b/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/MainActivity.java @@ -41,8 +41,8 @@ public class MainActivity extends AppCompatActivity implements OnKeyboardDownloa SentryAndroid.init(context, options -> { options.setEnableAutoSessionTracking(false); - options.setRelease(com.firstvoices.keyboards.BuildConfig.VERSION_GIT_TAG); - options.setEnvironment(com.firstvoices.keyboards.BuildConfig.VERSION_ENVIRONMENT); + options.setRelease(com.firstvoices.keyboards.BuildConfig.KEYMAN_VERSION_GIT_TAG); + options.setEnvironment(com.firstvoices.keyboards.BuildConfig.KEYMAN_VERSION_ENVIRONMENT); }); resultReceiver = new FVDownloadResultReceiver(new Handler(), context); diff --git a/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/SystemKeyboard.java b/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/SystemKeyboard.java index f991720420..496ce8d51d 100644 --- a/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/SystemKeyboard.java +++ b/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/SystemKeyboard.java @@ -50,8 +50,8 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven Log.d(TAG, "Initializing Sentry"); SentryAndroid.init(getApplicationContext(), options -> { options.setEnableAutoSessionTracking(false); - options.setRelease(com.firstvoices.keyboards.BuildConfig.VERSION_GIT_TAG); - options.setEnvironment(com.firstvoices.keyboards.BuildConfig.VERSION_ENVIRONMENT); + options.setRelease(com.firstvoices.keyboards.BuildConfig.KEYMAN_VERSION_GIT_TAG); + options.setEnvironment(com.firstvoices.keyboards.BuildConfig.KEYMAN_VERSION_ENVIRONMENT); }); } diff --git a/oem/firstvoices/android/build.sh b/oem/firstvoices/android/build.sh index f7cb441f00..5d521c775a 100755 --- a/oem/firstvoices/android/build.sh +++ b/oem/firstvoices/android/build.sh @@ -26,7 +26,7 @@ builder_describe "Builds FirstVoices for Android app." \ "configure" \ "build" \ "test Runs lint and tests." \ - "publish Publishes symbols to Sentry and the APK to the Play Store." + "publish Publishes symbols to Sentry and the APK to the Play Store." # parse before describe_outputs to check debug flags builder_parse "$@" @@ -38,7 +38,7 @@ if builder_is_debug_build; then TEST_FLAGS="-x assembleDebug lintDebug testDebug" fi -ARTIFACT="firstvoices-$VERSION.apk" +ARTIFACT="firstvoices-$KEYMAN_VERSION.apk" builder_describe_outputs \ configure /oem/firstvoices/android/app/libs/keyman-engine.aar \ diff --git a/oem/firstvoices/ios/build.sh b/oem/firstvoices/ios/build.sh index d35d7896c6..1b13248f98 100755 --- a/oem/firstvoices/ios/build.sh +++ b/oem/firstvoices/ios/build.sh @@ -106,8 +106,8 @@ function do_build() { -archivePath "$ARCHIVE_PATH" \ archive \ -allowProvisioningUpdates \ - VERSION=$VERSION \ - VERSION_WITH_TAG=$VERSION_WITH_TAG + KEYMAN_VERSION=$KEYMAN_VERSION \ + KEYMAN_VERSION_WITH_TAG=$KEYMAN_VERSION_WITH_TAG assertDirExists "$ARCHIVE_PATH" @@ -120,14 +120,14 @@ function do_build() { -exportOptionsPlist exportAppStore.plist \ -exportPath "$BUILD_PATH/${CONFIG}-iphoneos" \ -allowProvisioningUpdates \ - VERSION=$VERSION \ - VERSION_WITH_TAG=$VERSION_WITH_TAG + KEYMAN_VERSION=$KEYMAN_VERSION \ + KEYMAN_VERSION_WITH_TAG=$KEYMAN_VERSION_WITH_TAG else run_xcodebuild $CODE_SIGN \ $XCODEFLAGS_EXT \ -scheme "$TARGET" \ - VERSION=$VERSION \ - VERSION_WITH_TAG=$VERSION_WITH_TAG + KEYMAN_VERSION=$KEYMAN_VERSION \ + KEYMAN_VERSION_WITH_TAG=$KEYMAN_VERSION_WITH_TAG fi if builder_has_option --sim-artifact; then @@ -136,8 +136,8 @@ function do_build() { $XCODEFLAGS_EXT \ -scheme "$TARGET" \ -sdk iphonesimulator \ - VERSION=$VERSION \ - VERSION_WITH_TAG=$VERSION_WITH_TAG + KEYMAN_VERSION=$KEYMAN_VERSION \ + KEYMAN_VERSION_WITH_TAG=$KEYMAN_VERSION_WITH_TAG fi } diff --git a/oem/firstvoices/windows/src/inst/build.sh b/oem/firstvoices/windows/src/inst/build.sh index e12c0c3e5d..f427c0dfc0 100755 --- a/oem/firstvoices/windows/src/inst/build.sh +++ b/oem/firstvoices/windows/src/inst/build.sh @@ -16,7 +16,7 @@ builder_describe "Installation files for FirstVoices Keyboards" \ # after all other builds complete builder_describe_outputs \ - publish /windows/release/${VERSION}/firstvoices-${VERSION}.exe + publish /windows/release/${KEYMAN_VERSION}/firstvoices-${KEYMAN_VERSION}.exe builder_parse "$@" @@ -25,8 +25,8 @@ builder_parse "$@" . "$KEYMAN_ROOT/resources/build/win/zip.inc.sh" # In dev environments, we'll hack the tier to alpha; CI sets this for us in real builds. -if [[ -z ${TIER+x} ]]; then - TIER=alpha +if [[ -z ${KEYMAN_TIER+x} ]]; then + KEYMAN_TIER=alpha fi # TODO: why are we not bundling CEF? @@ -61,7 +61,7 @@ function do_publish() { "$WIXHEAT" dir ../xml -o desktopui.wxs -ag -cg DesktopUI -dr INSTALLDIR -suid -var var.DESKTOPUISOURCE -wx -nologo "$WIXCANDLE" -dOEMNAME="FirstVoices" -dPRODUCTNAME="FirstVoices Keyboards" -dROOT="$KEYMAN_ROOT/windows" \ - -dVERSION=$VERSION_WIN -dRELEASE=$VERSION_RELEASE \ + -dKEYMAN_VERSION=$KEYMAN_VERSION_WIN -dRELEASE=$KEYMAN_VERSION_RELEASE \ -dPRODUCTID=$GUID1 -dDESKTOPUISOURCE=../xml \ firstvoices.wxs desktopui.wxs @@ -101,9 +101,9 @@ function do_publish() { function copy-installer() { builder_heading copy-installer - mkdir -p "$KEYMAN_ROOT/windows/release/${VERSION}" - cp firstvoices.msi "$KEYMAN_ROOT/windows/release/${VERSION}/firstvoices.msi" - cp firstvoices.exe "$KEYMAN_ROOT/windows/release/${VERSION}/firstvoices-${VERSION}.exe" + mkdir -p "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}" + cp firstvoices.msi "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}/firstvoices.msi" + cp firstvoices.exe "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}/firstvoices-${KEYMAN_VERSION}.exe" verify-installer-signatures } @@ -111,14 +111,14 @@ function copy-installer() { function verify-installer-signatures() { builder_heading verify-installer-signatures - verify-all-executable-signatures-in-folder "$KEYMAN_ROOT/windows/release/${VERSION}" + verify-all-executable-signatures-in-folder "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}" } function create-setup-inf() { builder_heading create-setup-inf echo "[Setup]" > setup.inf - echo "Version=$VERSION_WIN" >> setup.inf + echo "Version=$KEYMAN_VERSION_WIN" >> setup.inf echo "MSIFileName=firstvoices.msi" >> setup.inf echo "MSIOptions=" >> setup.inf echo "AppName=FirstVoices Keyboards" >> setup.inf diff --git a/oem/firstvoices/windows/src/inst/firstvoices.wxs b/oem/firstvoices/windows/src/inst/firstvoices.wxs index 6388ec9b2b..ad5b02e15c 100644 --- a/oem/firstvoices/windows/src/inst/firstvoices.wxs +++ b/oem/firstvoices/windows/src/inst/firstvoices.wxs @@ -1,7 +1,7 @@  + Id="*" Name="$(var.PRODUCTNAME) $(var.RELEASE)" Version="$(var.KEYMAN_VERSION)" Language="1033"> @@ -25,10 +25,10 @@ - - + Maximum="$(var.KEYMAN_VERSION)" IncludeMaximum="no" MigrateFeatures="yes" Property="VERSION11FOUND" /> + + @@ -88,7 +88,7 @@ - + diff --git a/resources/build/build-utils-ci.inc.sh b/resources/build/build-utils-ci.inc.sh index a67f285254..66f3904192 100644 --- a/resources/build/build-utils-ci.inc.sh +++ b/resources/build/build-utils-ci.inc.sh @@ -22,7 +22,7 @@ builder_is_ci_build() { # Returns 0 if current build is running as a release build in CI # builder_is_ci_release_build() { - if [[ "$VERSION_ENVIRONMENT" =~ ^alpha|beta|stable$ ]]; then + if [[ "$KEYMAN_VERSION_ENVIRONMENT" =~ ^alpha|beta|stable$ ]]; then return 0 fi return 1 @@ -33,7 +33,7 @@ builder_is_ci_release_build() { # mainline branch test # builder_is_ci_test_build() { - if [[ "$VERSION_ENVIRONMENT" == test ]]; then + if [[ "$KEYMAN_VERSION_ENVIRONMENT" == test ]]; then return 0 fi return 1 @@ -115,7 +115,7 @@ function builder_pull_has_label() { function builder_publish_npm() { if builder_has_option --npm-publish; then # Require --dry-run if local or test to avoid accidentally clobbering npm packages - if [[ $VERSION_ENVIRONMENT =~ local|test ]] && ! builder_has_option --dry-run; then + if [[ $KEYMAN_VERSION_ENVIRONMENT =~ local|test ]] && ! builder_has_option --dry-run; then builder_die "publish --npm-publish must use --dry-run flag for local or test builds" fi _builder_publish_npm_package publish @@ -126,9 +126,9 @@ function builder_publish_npm() { function _builder_publish_npm_package() { local action=$1 - local dist_tag=$TIER dry_run= + local dist_tag=$KEYMAN_TIER dry_run= - if [[ $TIER == stable ]]; then + if [[ $KEYMAN_TIER == stable ]]; then dist_tag=latest fi @@ -164,7 +164,7 @@ function _builder_write_npm_version() { # git tagging. :) if ! "$JQ" -e '.version' package.json > /dev/null; then pushd "$KEYMAN_ROOT" > /dev/null - npm version --allow-same-version --no-git-tag-version --no-commit-hooks --workspaces "$VERSION_WITH_TAG" + npm version --allow-same-version --no-git-tag-version --no-commit-hooks --workspaces "$KEYMAN_VERSION_WITH_TAG" popd > /dev/null fi @@ -174,12 +174,12 @@ function _builder_write_npm_version() { # the local package.json files, so they do need to be restored afterwards find "$KEYMAN_ROOT" -name "package.json" -not -path '*/node_modules/*' -print0 | \ while IFS= read -r -d '' line; do - cat "$line" | "$JQ" --arg VERSION_WITH_TAG "$VERSION_WITH_TAG" \ + cat "$line" | "$JQ" --arg KEYMAN_VERSION_WITH_TAG "$KEYMAN_VERSION_WITH_TAG" \ ' . + - (try { dependencies: (.dependencies | to_entries | . + map(select(.key | match("@keymanapp/.*")) .value |= $VERSION_WITH_TAG) | from_entries) } catch {}) + - (try { devDependencies: (.devDependencies | to_entries | . + map(select(.key | match("@keymanapp/.*")) .value |= $VERSION_WITH_TAG) | from_entries) } catch {}) + - (try { optionalDependencies: (.optionalDependencies | to_entries | . + map(select(.key | match("@keymanapp/.*")) .value |= $VERSION_WITH_TAG) | from_entries) } catch {}) + (try { dependencies: (.dependencies | to_entries | . + map(select(.key | match("@keymanapp/.*")) .value |= $KEYMAN_VERSION_WITH_TAG) | from_entries) } catch {}) + + (try { devDependencies: (.devDependencies | to_entries | . + map(select(.key | match("@keymanapp/.*")) .value |= $KEYMAN_VERSION_WITH_TAG) | from_entries) } catch {}) + + (try { optionalDependencies: (.optionalDependencies | to_entries | . + map(select(.key | match("@keymanapp/.*")) .value |= $KEYMAN_VERSION_WITH_TAG) | from_entries) } catch {}) ' > "${line}_" mv -f "${line}_" "$line" done @@ -243,4 +243,4 @@ function _builder_publish_cache_package_json() { function builder_publish_cleanup() { rm -f "$KEYMAN_ROOT/builder_package_publish.json" -} \ No newline at end of file +} diff --git a/resources/build/build-utils.sh b/resources/build/build-utils.sh index 2cbbcbfba9..8b38a0ae90 100755 --- a/resources/build/build-utils.sh +++ b/resources/build/build-utils.sh @@ -1,19 +1,19 @@ #!/usr/bin/env bash # -# This script sets build environment variables. VERSION vars are also exported: -# VERSION: Full current build version, e.g. "14.0.1" -# VERSION_WIN: Full current build version for Windows, e.g. "14.0.1.0" -# VERSION_RELEASE: Current release version, e.g. "14.0" -# VERSION_MAJOR: Major version, e.g. "14" -# VERSION_MINOR: Minor version, e.g. "0" -# VERSION_PATCH: Patch version, e.g. "1" -# TIER: Current tier, one of "alpha", "beta" or "stable" -# VERSION_TAG: Tier + Pull Request + Location of build [-alpha|-beta][-test[-1234]][-local] -# VERSION_WITH_TAG: e.g. "14.0.1-alpha-test-1234" or "14.0.5-beta-local" or "14.0.1-alpha-test" -# VERSION_GIT_TAG: Git tag for the release, "release@$VERSION_WITH_TAG", e.g. "release@14.0.1-alpha-test-1234" +# This script sets build environment variables. KEYMAN_VERSION vars are also exported: +# KEYMAN_VERSION: Full current build version, e.g. "14.0.1" +# KEYMAN_VERSION_WIN: Full current build version for Windows, e.g. "14.0.1.0" +# KEYMAN_VERSION_RELEASE: Current release version, e.g. "14.0" +# KEYMAN_VERSION_MAJOR: Major version, e.g. "14" +# KEYMAN_VERSION_MINOR: Minor version, e.g. "0" +# KEYMAN_VERSION_PATCH: Patch version, e.g. "1" +# KEYMAN_TIER: Current tier, one of "alpha", "beta" or "stable" +# KEYMAN_VERSION_TAG: Tier + Pull Request + Location of build [-alpha|-beta][-test[-1234]][-local] +# KEYMAN_VERSION_WITH_TAG: e.g. "14.0.1-alpha-test-1234" or "14.0.5-beta-local" or "14.0.1-alpha-test" +# KEYMAN_VERSION_GIT_TAG: Git tag for the release, "release@$KEYMAN_VERSION_WITH_TAG", e.g. "release@14.0.1-alpha-test-1234" # KEYMAN_ROOT: fully resolved root path of Keyman repository -# VERSION_ENVIRONMENT: One of: local, test, alpha, beta, stable -# UPLOAD_SENTRY: true - if VERSION_ENVIRONMENT is one of alpha, beta, stable +# KEYMAN_VERSION_ENVIRONMENT: One of: local, test, alpha, beta, stable +# UPLOAD_SENTRY: true - if KEYMAN_VERSION_ENVIRONMENT is one of alpha, beta, stable # false - if local, test. Indicates if debug artifacts should be uploaded to Sentry # BUILDER_OS: win|mac|linux -- current build environment # @@ -57,20 +57,20 @@ function findKeymanRoot() { } function findVersion() { - local VERSION_MD="$KEYMAN_ROOT/VERSION.md" - VERSION=$(builder_trim $(<"$VERSION_MD")) - [[ "$VERSION" =~ ^([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)$ ]] && { - VERSION_MAJOR="${BASH_REMATCH[1]}" - VERSION_MINOR="${BASH_REMATCH[2]}" - VERSION_PATCH="${BASH_REMATCH[3]}" - VERSION_RELEASE="$VERSION_MAJOR.$VERSION_MINOR" + local KEYMAN_VERSION_MD="$KEYMAN_ROOT/VERSION.md" + KEYMAN_VERSION=$(builder_trim $(<"$KEYMAN_VERSION_MD")) + [[ "$KEYMAN_VERSION" =~ ^([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)$ ]] && { + KEYMAN_VERSION_MAJOR="${BASH_REMATCH[1]}" + KEYMAN_VERSION_MINOR="${BASH_REMATCH[2]}" + KEYMAN_VERSION_PATCH="${BASH_REMATCH[3]}" + KEYMAN_VERSION_RELEASE="$KEYMAN_VERSION_MAJOR.$KEYMAN_VERSION_MINOR" } || { echo "Invalid VERSION.md file: expected major.minor.patch"; exit 1; } # Used for Windows, which requires a four part version string - VERSION_WIN="$VERSION.0" + KEYMAN_VERSION_WIN="$KEYMAN_VERSION.0" # # Build a tag to append to the version string. This is not assigned @@ -78,70 +78,70 @@ function findVersion() { # display string and in TeamCity configuration # - if [ "$TIER" == "alpha" ] || [ "$TIER" == "beta" ]; then - VERSION_TAG="-$TIER" + if [ "$KEYMAN_TIER" == "alpha" ] || [ "$KEYMAN_TIER" == "beta" ]; then + KEYMAN_VERSION_TAG="-$KEYMAN_TIER" else - VERSION_TAG= + KEYMAN_VERSION_TAG= fi if [[ -z "${TEAMCITY_VERSION-}" && -z "${GITHUB_ACTIONS-}" && -z "${KEYMAN_PKG_BUILD-}" ]]; then # Local dev machine, not TeamCity or GitHub Action and not .deb package build - VERSION_TAG="$VERSION_TAG-local" - VERSION_ENVIRONMENT=local + KEYMAN_VERSION_TAG="$KEYMAN_VERSION_TAG-local" + KEYMAN_VERSION_ENVIRONMENT=local elif [ -n "${TEAMCITY_PR_NUMBER-}" ]; then # On TeamCity: are we running a pull request build or a master/beta/stable build? - VERSION_ENVIRONMENT="test" + KEYMAN_VERSION_ENVIRONMENT="test" # Note TEAMCITY_PR_NUMBER can also be 'master', 'beta', or 'stable-x.y' # This indicates we are running a Test build. if [[ $TEAMCITY_PR_NUMBER =~ ^(master|beta|stable(-[0-9]+\.[0-9]+)?)$ ]]; then - VERSION_TAG="$VERSION_TAG-test" + KEYMAN_VERSION_TAG="$KEYMAN_VERSION_TAG-test" else - VERSION_TAG="$VERSION_TAG-test-$TEAMCITY_PR_NUMBER" + KEYMAN_VERSION_TAG="$KEYMAN_VERSION_TAG-test-$TEAMCITY_PR_NUMBER" fi elif [ -n "${GITHUB_ACTIONS-}" ] && ${GHA_TEST_BUILD-}; then - VERSION_ENVIRONMENT="test" + KEYMAN_VERSION_ENVIRONMENT="test" # Note GHA_BRANCH can be 'master', 'beta', or 'stable-x.y' # This indicates we are running a Test build. if [[ ${GHA_BRANCH-} =~ ^(master|beta|stable(-[0-9]+\.[0-9]+)?)$ ]]; then - VERSION_TAG="${VERSION_TAG}-test" + KEYMAN_VERSION_TAG="${KEYMAN_VERSION_TAG}-test" else - VERSION_TAG="${VERSION_TAG}-test-${GHA_BRANCH-unset}" + KEYMAN_VERSION_TAG="${KEYMAN_VERSION_TAG}-test-${GHA_BRANCH-unset}" fi else - VERSION_ENVIRONMENT="$TIER" + KEYMAN_VERSION_ENVIRONMENT="$KEYMAN_TIER" fi - VERSION_WITH_TAG="$VERSION$VERSION_TAG" - VERSION_GIT_TAG="release@$VERSION_WITH_TAG" + KEYMAN_VERSION_WITH_TAG="$KEYMAN_VERSION$KEYMAN_VERSION_TAG" + KEYMAN_VERSION_GIT_TAG="release@$KEYMAN_VERSION_WITH_TAG" - readonly VERSION - readonly VERSION_MAJOR - readonly VERSION_MINOR - readonly VERSION_PATCH - readonly VERSION_RELEASE - readonly VERSION_WIN - readonly VERSION_TAG - readonly VERSION_WITH_TAG - readonly VERSION_ENVIRONMENT - readonly VERSION_GIT_TAG + readonly KEYMAN_VERSION + readonly KEYMAN_VERSION_MAJOR + readonly KEYMAN_VERSION_MINOR + readonly KEYMAN_VERSION_PATCH + readonly KEYMAN_VERSION_RELEASE + readonly KEYMAN_VERSION_WIN + readonly KEYMAN_VERSION_TAG + readonly KEYMAN_VERSION_WITH_TAG + readonly KEYMAN_VERSION_ENVIRONMENT + readonly KEYMAN_VERSION_GIT_TAG # Export version strings so places like version.gradle can access them - export VERSION - export VERSION_MAJOR - export VERSION_MINOR - export VERSION_PATCH - export VERSION_RELEASE - export VERSION_WIN - export VERSION_TAG - export VERSION_WITH_TAG - export VERSION_ENVIRONMENT - export VERSION_GIT_TAG + export KEYMAN_VERSION + export KEYMAN_VERSION_MAJOR + export KEYMAN_VERSION_MINOR + export KEYMAN_VERSION_PATCH + export KEYMAN_VERSION_RELEASE + export KEYMAN_VERSION_WIN + export KEYMAN_VERSION_TAG + export KEYMAN_VERSION_WITH_TAG + export KEYMAN_VERSION_ENVIRONMENT + export KEYMAN_VERSION_GIT_TAG } function findTier() { - local TIER_MD="$KEYMAN_ROOT/TIER.md" - TIER=$(builder_trim $(<"$TIER_MD")) - [[ "$TIER" =~ ^(alpha|beta|stable)$ ]] || { + local KEYMAN_TIER_MD="$KEYMAN_ROOT/TIER.md" + KEYMAN_TIER=$(builder_trim $(<"$KEYMAN_TIER_MD")) + [[ "$KEYMAN_TIER" =~ ^(alpha|beta|stable)$ ]] || { echo "Invalid TIER.md file: expected alpha, beta or stable." exit 1; } @@ -150,39 +150,40 @@ function findTier() { function printBuildNumberForTeamCity() { if [ ! -z "${TEAMCITY_VERSION-}" ]; then if [ ! -z "${TEAMCITY_PR_NUMBER-}" ]; then - echo "##teamcity[buildNumber '$VERSION_WITH_TAG']" + echo "##teamcity[buildNumber '$KEYMAN_VERSION_WITH_TAG']" else # For alpha/beta builds, for now we don't append the # version tag as buildNumber is used in the delivery # of the build version. We may improve this in the # future. - echo "##teamcity[buildNumber '$VERSION']" + echo "##teamcity[buildNumber '$KEYMAN_VERSION']" fi fi } function printVersionUtilsDebug() { - echo "KEYMAN_ROOT: $KEYMAN_ROOT" - echo "VERSION: $VERSION" - echo "VERSION_WIN: $VERSION_WIN" - echo "VERSION_RELEASE: $VERSION_RELEASE" - echo "VERSION_MAJOR: $VERSION_MAJOR" - echo "VERSION_MINOR: $VERSION_MINOR" - echo "VERSION_PATCH: $VERSION_PATCH" - echo "TIER: $TIER" - echo "VERSION_TAG: $VERSION_TAG" - echo "VERSION_WITH_TAG: $VERSION_WITH_TAG" - echo "VERSION_GIT_TAG: $VERSION_GIT_TAG" - echo "VERSION_ENVIRONMENT: $VERSION_ENVIRONMENT" + echo "KEYMAN_ROOT: $KEYMAN_ROOT" + echo "KEYMAN_VERSION: $KEYMAN_VERSION" + echo "KEYMAN_VERSION_WIN: $KEYMAN_VERSION_WIN" + echo "KEYMAN_VERSION_RELEASE: $KEYMAN_VERSION_RELEASE" + echo "KEYMAN_VERSION_MAJOR: $KEYMAN_VERSION_MAJOR" + echo "KEYMAN_VERSION_MINOR: $KEYMAN_VERSION_MINOR" + echo "KEYMAN_VERSION_PATCH: $KEYMAN_VERSION_PATCH" + echo "KEYMAN_TIER: $KEYMAN_TIER" + echo "KEYMAN_VERSION_TAG: $KEYMAN_VERSION_TAG" + echo "KEYMAN_VERSION_WITH_TAG: $KEYMAN_VERSION_WITH_TAG" + echo "KEYMAN_VERSION_GIT_TAG: $KEYMAN_VERSION_GIT_TAG" + echo "KEYMAN_VERSION_ENVIRONMENT: $KEYMAN_VERSION_ENVIRONMENT" } function findShouldSentryRelease() { - # Default, for 'test' or 'local' environment, or in case $VERSION_ENVIRONMENT is improperly specified. + # Default, for 'test' or 'local' environment, or in case + # $KEYMAN_VERSION_ENVIRONMENT is improperly specified. # (May be overridden by -upload-sentry in supporting build scripts.) UPLOAD_SENTRY=false # Default: override to `true` for release builds. - case $VERSION_ENVIRONMENT in + case $KEYMAN_VERSION_ENVIRONMENT in # Actual release tiers alpha | beta | stable) UPLOAD_SENTRY=true @@ -236,12 +237,12 @@ function exportEnvironmentDefinitionScript() { echo "# This file redefines critical environment variables for import to Xcode build phases." >> "$ENVIRONMENT_SH" echo "" >> "$ENVIRONMENT_SH" - # Defining variables for VERSION here will leave static definitions that don't automatically update when a user + # Defining variables for KEYMAN_VERSION here will leave static definitions that don't automatically update when a user # changes branches; some branches are 'similar enough' to not require full command-line based rebuilds. - # We want that VERSION number to properly mirror the state of its branch during development so that it matches + # We want that KEYMAN_VERSION number to properly mirror the state of its branch during development so that it matches # any error reports that get logged to Sentry. # - # As a result, we explicitly do NOT define VERSION or VERSION_TAG as part of ENVIRONMENT_SH. + # As a result, we explicitly do NOT define KEYMAN_VERSION or KEYMAN_VERSION_TAG as part of ENVIRONMENT_SH. echo "# Required for successful dSYM upload for Sentry error reporting" >> "$ENVIRONMENT_SH" echo "export SENTRY_AUTH_TOKEN=${SENTRY_AUTH_TOKEN:-}" >> "$ENVIRONMENT_SH" @@ -267,17 +268,17 @@ replaceVersionStrings() { local outfile=$2 sed " - s/\$VERSION_WIN/$VERSION_WIN/g; - s/\$VERSION_RELEASE/$VERSION_RELEASE/g; - s/\$VERSION_MAJOR/$VERSION_MAJOR/g; - s/\$VERSION_MINOR/$VERSION_MINOR/g; - s/\$VERSION_PATCH/$VERSION_PATCH/g; - s/\$TIER/$TIER/g; - s/\$VERSION_TAG/$VERSION_TAG/g; - s/\$VERSION_WITH_TAG/$VERSION_WITH_TAG/g; - s/\$VERSION_GIT_TAG/$VERSION_GIT_TAG/g; - s/\$VERSION_ENVIRONMENT/$VERSION_ENVIRONMENT/g; - s/\$VERSION/$VERSION/g; + s/\$KEYMAN_VERSION_WIN/$KEYMAN_VERSION_WIN/g; + s/\$KEYMAN_VERSION_RELEASE/$KEYMAN_VERSION_RELEASE/g; + s/\$KEYMAN_VERSION_MAJOR/$KEYMAN_VERSION_MAJOR/g; + s/\$KEYMAN_VERSION_MINOR/$KEYMAN_VERSION_MINOR/g; + s/\$KEYMAN_VERSION_PATCH/$KEYMAN_VERSION_PATCH/g; + s/\$KEYMAN_TIER/$KEYMAN_TIER/g; + s/\$KEYMAN_VERSION_TAG/$KEYMAN_VERSION_TAG/g; + s/\$KEYMAN_VERSION_WITH_TAG/$KEYMAN_VERSION_WITH_TAG/g; + s/\$KEYMAN_VERSION_GIT_TAG/$KEYMAN_VERSION_GIT_TAG/g; + s/\$KEYMAN_VERSION_ENVIRONMENT/$KEYMAN_VERSION_ENVIRONMENT/g; + s/\$KEYMAN_VERSION/$KEYMAN_VERSION/g; " "$infile" > "$outfile" } @@ -287,39 +288,39 @@ replaceVersionStrings_Mkver() { local infile=$1 local outfile=$2 - # Note that $VERSION differs between the two functions! + # Note that $KEYMAN_VERSION differs between the two functions! # We should be deprecating all the mkver strings sed " - s/\$VersionWin/$VERSION_WIN/g; - s/\$VersionRelease/$VERSION_RELEASE/g; - s/\$VersionMajor/$VERSION_MAJOR/g; - s/\$VersionMinor/$VERSION_MINOR/g; - s/\$VersionPatch/$VERSION_PATCH/g; - s/\$Tier/$TIER/g; - s/\$Tag/$VERSION_TAG/g; - s/\$VersionWithTag/$VERSION_WITH_TAG/g; - s/\$VersionGitTag/$VERSION_GIT_TAG/g; - s/\$VersionRc/$VERSION_MAJOR,$VERSION_MINOR,$VERSION_PATCH,0/g; - s/\$Environment/$VERSION_ENVIRONMENT/g; - s/\$Version/$VERSION/g; - s/\$VERSIONNUM/$VERSION_MAJOR,$VERSION_MINOR,$VERSION_PATCH,0/g; - s/\$RELEASE_MAJOR/$VERSION_MAJOR/g; - s/\$RELEASE_MINOR/$VERSION_MINOR/g; - s/\$RELEASE/$VERSION_RELEASE/g; + s/\$VersionWin/$KEYMAN_VERSION_WIN/g; + s/\$VersionRelease/$KEYMAN_VERSION_RELEASE/g; + s/\$VersionMajor/$KEYMAN_VERSION_MAJOR/g; + s/\$VersionMinor/$KEYMAN_VERSION_MINOR/g; + s/\$VersionPatch/$KEYMAN_VERSION_PATCH/g; + s/\$Tier/$KEYMAN_TIER/g; + s/\$Tag/$KEYMAN_VERSION_TAG/g; + s/\$VersionWithTag/$KEYMAN_VERSION_WITH_TAG/g; + s/\$VersionGitTag/$KEYMAN_VERSION_GIT_TAG/g; + s/\$VersionRc/$KEYMAN_VERSION_MAJOR,$KEYMAN_VERSION_MINOR,$KEYMAN_VERSION_PATCH,0/g; + s/\$Environment/$KEYMAN_VERSION_ENVIRONMENT/g; + s/\$Version/$KEYMAN_VERSION/g; + s/\$KEYMAN_VERSIONNUM/$KEYMAN_VERSION_MAJOR,$KEYMAN_VERSION_MINOR,$KEYMAN_VERSION_PATCH,0/g; + s/\$RELEASE_MAJOR/$KEYMAN_VERSION_MAJOR/g; + s/\$RELEASE_MINOR/$KEYMAN_VERSION_MINOR/g; + s/\$RELEASE/$KEYMAN_VERSION_RELEASE/g; - s/\$VERSION_WIN/$VERSION_WIN/g; - s/\$VERSION_RELEASE/$VERSION_RELEASE/g; - s/\$VERSION_MAJOR/$VERSION_MAJOR/g; - s/\$VERSION_MINOR/$VERSION_MINOR/g; - s/\$VERSION_PATCH/$VERSION_PATCH/g; - s/\$TIER/$TIER/g; - s/\$VERSION_TAG/$VERSION_TAG/g; - s/\$VERSION_WITH_TAG/$VERSION_WITH_TAG/g; - s/\$VERSION_GIT_TAG/$VERSION_GIT_TAG/g; - s/\$VERSION_ENVIRONMENT/$VERSION_ENVIRONMENT/g; + s/\$KEYMAN_VERSION_WIN/$KEYMAN_VERSION_WIN/g; + s/\$KEYMAN_VERSION_RELEASE/$KEYMAN_VERSION_RELEASE/g; + s/\$KEYMAN_VERSION_MAJOR/$KEYMAN_VERSION_MAJOR/g; + s/\$KEYMAN_VERSION_MINOR/$KEYMAN_VERSION_MINOR/g; + s/\$KEYMAN_VERSION_PATCH/$KEYMAN_VERSION_PATCH/g; + s/\$KEYMAN_TIER/$KEYMAN_TIER/g; + s/\$KEYMAN_VERSION_TAG/$KEYMAN_VERSION_TAG/g; + s/\$KEYMAN_VERSION_WITH_TAG/$KEYMAN_VERSION_WITH_TAG/g; + s/\$KEYMAN_VERSION_GIT_TAG/$KEYMAN_VERSION_GIT_TAG/g; + s/\$KEYMAN_VERSION_ENVIRONMENT/$KEYMAN_VERSION_ENVIRONMENT/g; - s/\$VERSION/$VERSION_WIN/g; + s/\$KEYMAN_VERSION/$KEYMAN_VERSION_WIN/g; " "$infile" > "$outfile" } diff --git a/resources/build/ci/pull-requests.inc.sh b/resources/build/ci/pull-requests.inc.sh index 09c0903fe5..6959f826d3 100644 --- a/resources/build/ci/pull-requests.inc.sh +++ b/resources/build/ci/pull-requests.inc.sh @@ -73,7 +73,7 @@ function ci_repo_has_cached_changes { # * hub # * uuidgen (or TeamCity `$BUILD_NUMBER` if `uuidgen` not present on system) # Example: -# ci_open_pull_request "$S_KEYMAN_COM" auto/keymanweb/release "auto: KeymanWeb release $VERSION_RELEASE"" +# ci_open_pull_request "$S_KEYMAN_COM" auto/keymanweb/release "auto: KeymanWeb release $KEYMAN_VERSION_RELEASE"" # function ci_open_pull_request { local repo="$1" @@ -117,4 +117,4 @@ function ci_open_pull_request { builder_echo "Pull request successfully created" return 0 -} \ No newline at end of file +} diff --git a/resources/build/help-keyman-com.sh b/resources/build/help-keyman-com.sh index 7901be5475..0bf4067bfa 100755 --- a/resources/build/help-keyman-com.sh +++ b/resources/build/help-keyman-com.sh @@ -74,38 +74,38 @@ function upload { function upload_keyman_help { case $platform in android) - upload android/docs/help products/android/$VERSION_RELEASE - upload android/docs/engine developer/engine/android/$VERSION_RELEASE + upload android/docs/help products/android/$KEYMAN_VERSION_RELEASE + upload android/docs/engine developer/engine/android/$KEYMAN_VERSION_RELEASE ;; ios) - upload ios/docs/help products/iphone-and-ipad/$VERSION_RELEASE - upload ios/docs/engine developer/engine/iphone-and-ipad/$VERSION_RELEASE + upload ios/docs/help products/iphone-and-ipad/$KEYMAN_VERSION_RELEASE + upload ios/docs/engine developer/engine/iphone-and-ipad/$KEYMAN_VERSION_RELEASE ;; linux) pushd "$KEYMAN_ROOT/linux/keyman-config" > /dev/null ./build.sh build popd > /dev/null - upload linux/docs/help products/linux/$VERSION_RELEASE + upload linux/docs/help products/linux/$KEYMAN_VERSION_RELEASE ;; mac) - upload mac/docs/help products/mac/$VERSION_RELEASE + upload mac/docs/help products/mac/$KEYMAN_VERSION_RELEASE ;; web) - upload web/docs/engine developer/engine/web/$VERSION_RELEASE + upload web/docs/engine developer/engine/web/$KEYMAN_VERSION_RELEASE ;; windows) # Note: `/windows/src/desktop/help/build.sh web` must be run first - upload windows/bin/help/md/desktop products/windows/$VERSION_RELEASE - upload windows/docs/engine developer/engine/windows/$VERSION_RELEASE + upload windows/bin/help/md/desktop products/windows/$KEYMAN_VERSION_RELEASE + upload windows/docs/engine developer/engine/windows/$KEYMAN_VERSION_RELEASE ;; developer) # Note: `/developer/build.sh api` must be run first - covers both uploads - upload developer/docs/help developer/$VERSION_RELEASE - upload developer/build/docs developer/$VERSION_RELEASE/reference/api - upload developer/src/kmc/build/messages developer/$VERSION_RELEASE/reference/messages + upload developer/docs/help developer/$KEYMAN_VERSION_RELEASE + upload developer/build/docs developer/$KEYMAN_VERSION_RELEASE/reference/api + upload developer/src/kmc/build/messages developer/$KEYMAN_VERSION_RELEASE/reference/messages # Note: we publish the core help alongside developer because we don't have # a core CI release build - upload core/docs/api developer/core/$VERSION_RELEASE + upload core/docs/api developer/core/$KEYMAN_VERSION_RELEASE ;; *) display_usage @@ -152,6 +152,6 @@ if ! ci_repo_has_cached_changes "$HELP_KEYMAN_COM"; then exit 0 fi -ci_open_pull_request "$HELP_KEYMAN_COM" "auto/$platform-help-$VERSION_WITH_TAG" "auto: Keyman for $platform help deployment" +ci_open_pull_request "$HELP_KEYMAN_COM" "auto/$platform-help-$KEYMAN_VERSION_WITH_TAG" "auto: Keyman for $platform help deployment" -exit 0 \ No newline at end of file +exit 0 diff --git a/resources/build/increment-version.sh b/resources/build/increment-version.sh index 9e9ac699b8..f1d15c6a7d 100755 --- a/resources/build/increment-version.sh +++ b/resources/build/increment-version.sh @@ -111,10 +111,10 @@ fi if [[ $ABORT = 50 ]]; then if [[ $FORCE = 0 ]]; then - echo "Skipping version increment from $VERSION: no recently merged pull requests were found" + echo "Skipping version increment from $KEYMAN_VERSION: no recently merged pull requests were found" if [ ! -z "${TEAMCITY_VERSION-}" ]; then # Send TeamCity a build status - echo "##teamcity[buildStatus status='SUCCESS' text='Skipping version increment from $VERSION: no recently merged pull requests were found']" + echo "##teamcity[buildStatus status='SUCCESS' text='Skipping version increment from $KEYMAN_VERSION: no recently merged pull requests were found']" fi exit 0 else @@ -131,14 +131,14 @@ popd > /dev/null # if [ "$action" == "commit" ]; then - echo "increment-version.sh: committing to repository and tagging release version $VERSION_WITH_TAG" - VERSION_MD="$KEYMAN_ROOT/VERSION.md" - NEWVERSION=`cat $VERSION_MD | tr -d "[:space:]"` + echo "increment-version.sh: committing to repository and tagging release version $KEYMAN_VERSION_WITH_TAG" + KEYMAN_VERSION_MD="$KEYMAN_ROOT/VERSION.md" + NEWVERSION=`cat $KEYMAN_VERSION_MD | tr -d "[:space:]"` pushd "$KEYMAN_ROOT" > /dev/null message="auto: increment $base version to $NEWVERSION" branch="auto/version-$base-$NEWVERSION" - git tag -a "$VERSION_GIT_TAG" -m "Keyman release $VERSION_WITH_TAG" + git tag -a "$KEYMAN_VERSION_GIT_TAG" -m "Keyman release $KEYMAN_VERSION_WITH_TAG" git checkout -b "$branch" git add VERSION.md HISTORY.md @@ -206,7 +206,7 @@ if [ "$action" == "commit" ]; then echo "Version was incremented and pull request was created, and builds were triggered" if [ ! -z "${TEAMCITY_VERSION-}" ]; then # Send TeamCity a build status - echo "##teamcity[buildStatus status='SUCCESS' text='Version was incremented from $VERSION to $NEWVERSION and pull request was created']" + echo "##teamcity[buildStatus status='SUCCESS' text='Version was incremented from $KEYMAN_VERSION to $NEWVERSION and pull request was created']" fi # diff --git a/resources/build/meson/standard_meson_build.inc.sh b/resources/build/meson/standard_meson_build.inc.sh index 39fd49de05..f910b8e35d 100644 --- a/resources/build/meson/standard_meson_build.inc.sh +++ b/resources/build/meson/standard_meson_build.inc.sh @@ -8,7 +8,7 @@ # resources/ folder (which should be git-ignored): # # * resources/meson.build - a copy of standard.meson.build from this folder -# * resources/VERSION_WITH_TAG.md - the value of the env var $VERSION_WITH_TAG +# * resources/KEYMAN_VERSION_WITH_TAG.md - the value of the env var $KEYMAN_VERSION_WITH_TAG # # We do this because meson doesn't allow us to: # @@ -31,5 +31,5 @@ standard_meson_build() { mkdir -p "$THIS_SCRIPT_PATH/resources" cp "$KEYMAN_ROOT/resources/build/meson/standard.meson.build" "$THIS_SCRIPT_PATH/resources/meson.build" - echo "$VERSION_WITH_TAG" > "$THIS_SCRIPT_PATH/resources/VERSION_WITH_TAG.md" + echo "$KEYMAN_VERSION_WITH_TAG" > "$THIS_SCRIPT_PATH/resources/KEYMAN_VERSION_WITH_TAG.md" } diff --git a/resources/build/publish-minimum-versions.sh b/resources/build/publish-minimum-versions.sh index 90ff5ca3d5..4a65c3352d 100755 --- a/resources/build/publish-minimum-versions.sh +++ b/resources/build/publish-minimum-versions.sh @@ -31,7 +31,17 @@ generate_table() { # echo "${strarr[@]}" for n in ${!strarr[@]}; do - echo "| ${strarr[n]} | ${!strarr[n]} |" + case "${strarr[n]}" in + KEYMAN_VERSION | KEYMAN_VERSION_MAJOR | KEYMAN_VERSION_MINOR | \ + KEYMAN_VERSION_PATCH | KEYMAN_VERSION_RELEASE | KEYMAN_VERSION_WIN | \ + KEYMAN_VERSION_TAG | KEYMAN_VERSION_WITH_TAG | \ + KEYMAN_VERSION_ENVIRONMENT | KEYMAN_VERSION_GIT_TAG) + # ignore the variables that contain the Keyman version + ;; + *) + echo "| ${strarr[n]} | ${!strarr[n]} |" + ;; + esac done echo "" @@ -62,4 +72,4 @@ do_test() { builder_run_action clean rm -f "$KEYMAN_ROOT/docs/minimum-versions.md" builder_run_action build do_build -builder_run_action test do_test \ No newline at end of file +builder_run_action test do_test diff --git a/resources/build/sentry-control.inc.sh b/resources/build/sentry-control.inc.sh index e7909e4b99..b01695af19 100644 --- a/resources/build/sentry-control.inc.sh +++ b/resources/build/sentry-control.inc.sh @@ -27,14 +27,14 @@ function makeSentryRelease() { if isSentryConfigured; then if isSentryCliAvailable; then # This version tag matches the repository version tag release@x.y.z - echo "Making a Sentry release for tag $VERSION_GIT_TAG" - sentry-cli releases new -p keyman-android -p keyman-developer -p keyman-ios -p keyman-linux -p keyman-mac -p keyman-web -p keyman-windows $VERSION_GIT_TAG + echo "Making a Sentry release for tag $KEYMAN_VERSION_GIT_TAG" + sentry-cli releases new -p keyman-android -p keyman-developer -p keyman-ios -p keyman-linux -p keyman-mac -p keyman-web -p keyman-windows $KEYMAN_VERSION_GIT_TAG - echo "Setting commits for release tag $VERSION_GIT_TAG" - sentry-cli releases set-commits --auto $VERSION_GIT_TAG + echo "Setting commits for release tag $KEYMAN_VERSION_GIT_TAG" + sentry-cli releases set-commits --auto $KEYMAN_VERSION_GIT_TAG - echo "Finalizing release tag $VERSION_GIT_TAG" - sentry-cli releases finalize "$VERSION_GIT_TAG" + echo "Finalizing release tag $KEYMAN_VERSION_GIT_TAG" + sentry-cli releases finalize "$KEYMAN_VERSION_GIT_TAG" fi fi } diff --git a/resources/build/set-bundle-versions-and-settings-tagged.sh b/resources/build/set-bundle-versions-and-settings-tagged.sh index 9ad0e9758c..6985ae3c3c 100755 --- a/resources/build/set-bundle-versions-and-settings-tagged.sh +++ b/resources/build/set-bundle-versions-and-settings-tagged.sh @@ -1,11 +1,11 @@ #!/usr/bin/env bash # Calls script in xcode-utils to update the version -# true: applies VERSION_WITH_TAG to custom KeymanVersionWithTag plist member used for in-app display +# true: applies KEYMAN_VERSION_WITH_TAG to custom KeymanVersionWithTag plist member used for in-app display # updates the version string for Settings source "$KEYMAN_ROOT/resources/build/xcode-utils.sh" phaseSetBundleVersions true -setSettingsBundleVersion \ No newline at end of file +setSettingsBundleVersion diff --git a/resources/build/set-bundle-versions-and-settings-untagged.sh b/resources/build/set-bundle-versions-and-settings-untagged.sh index 38256c7a9a..93cd8a7eab 100755 --- a/resources/build/set-bundle-versions-and-settings-untagged.sh +++ b/resources/build/set-bundle-versions-and-settings-untagged.sh @@ -1,11 +1,11 @@ #!/usr/bin/env bash # Calls script in xcode-utils to update the version -# true: applies VERSION_WITH_TAG to custom KeymanVersionWithTag plist member used for in-app display +# true: applies KEYMAN_VERSION_WITH_TAG to custom KeymanVersionWithTag plist member used for in-app display # updates the version string for Settings source "$KEYMAN_ROOT/resources/build/xcode-utils.sh" phaseSetBundleVersions -setSettingsBundleVersion \ No newline at end of file +setSettingsBundleVersion diff --git a/resources/build/set-bundle-versions-tagged.sh b/resources/build/set-bundle-versions-tagged.sh index 8b4075a037..a941d460fe 100755 --- a/resources/build/set-bundle-versions-tagged.sh +++ b/resources/build/set-bundle-versions-tagged.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Calls script in xcode-utils to update the version -# true: applies VERSION_WITH_TAG to custom KeymanVersionWithTag plist member used for in-app display +# true: applies KEYMAN_VERSION_WITH_TAG to custom KeymanVersionWithTag plist member used for in-app display source "$KEYMAN_ROOT/resources/build/xcode-utils.sh" -phaseSetBundleVersions true \ No newline at end of file +phaseSetBundleVersions true diff --git a/resources/build/test/test.sh b/resources/build/test/test.sh index 48fad740e4..246838b8ac 100755 --- a/resources/build/test/test.sh +++ b/resources/build/test/test.sh @@ -91,7 +91,7 @@ builder_parse_test() { local expected_options="$2" # When testing in a local environment, --debug will be added by default (see #11106) - if [[ $VERSION_ENVIRONMENT == "local" ]]; then + if [[ $KEYMAN_VERSION_ENVIRONMENT == "local" ]]; then expected_options="${expected_options} --debug" fi @@ -191,7 +191,7 @@ echo -e "${COLOR_BLUE}## Testing output of: builder_parse --feature xyzzy --bar parse_output=$(builder_parse --feature xyzzy --bar abc --baz def test) expected="$(builder_echo setmark "test.sh parameters: <--feature xyzzy --bar abc --baz def test>")" -if [[ $VERSION_ENVIRONMENT == "local" ]]; then +if [[ $KEYMAN_VERSION_ENVIRONMENT == "local" ]]; then # When run in a local-dev environment, an extra line appears about the automatic --debug option. expected="$(builder_echo grey "Local build environment detected: setting --debug")"$'\n'"$(builder_echo setmark "test.sh parameters: <--feature xyzzy --bar abc --baz def test --debug>")" fi diff --git a/resources/build/trigger-builds.inc.sh b/resources/build/trigger-builds.inc.sh index 42de09dae1..639c3d240b 100644 --- a/resources/build/trigger-builds.inc.sh +++ b/resources/build/trigger-builds.inc.sh @@ -78,9 +78,9 @@ function triggerGitHubActionsBuild() { if [ "${action:-""}" == "commit" ]; then # This will only be true if we created and pushed a tag - GIT_BUILD_SHA="$(git rev-parse "refs/tags/release@$VERSION_WITH_TAG")" + GIT_BUILD_SHA="$(git rev-parse "refs/tags/release@$KEYMAN_VERSION_WITH_TAG")" GIT_BASE_REF="$(git rev-parse "${GIT_BUILD_SHA}^")" - GIT_EVENT_TYPE="${GITHUB_ACTION}: release@${VERSION_WITH_TAG}" + GIT_EVENT_TYPE="${GITHUB_ACTION}: release@${KEYMAN_VERSION_WITH_TAG}" elif [[ $GIT_BRANCH != stable-* ]] && [[ $GIT_BRANCH =~ [0-9]+ ]]; then local JSON=$(call_curl "${GITHUB_SERVER}/pulls/${GIT_BRANCH}" --header "Authorization: token $GITHUB_TOKEN") GIT_BUILD_SHA="$(echo "$JSON" | $JQ -r '.head.sha')" diff --git a/resources/build/version/src/fixupHistory.ts b/resources/build/version/src/fixupHistory.ts index 884e9c5557..03dd3967cf 100644 --- a/resources/build/version/src/fixupHistory.ts +++ b/resources/build/version/src/fixupHistory.ts @@ -39,7 +39,7 @@ const splicePullsIntoHistory = async (pulls: PRInformation[], base?: string): Pr tier = (await spawnChild('git', ['show', base+':TIER.md'])).trim(); } } - //logInfo(`VERSION="${version}"`); + //logInfo(`KEYMAN_VERSION="${version}"`); // // Load and parse history file, looking for our version diff --git a/resources/build/win/environment.inc.sh b/resources/build/win/environment.inc.sh index 71c18f305b..6da5ad039f 100644 --- a/resources/build/win/environment.inc.sh +++ b/resources/build/win/environment.inc.sh @@ -32,7 +32,7 @@ COMMON_ROOT="$KEYMAN_ROOT/common/windows/delphi" OUTLIB="$WINDOWS_ROOT/lib" COMMON_OUTLIB="$KEYMAN_ROOT/common/windows/lib" -if builder_is_debug_build || [[ $VERSION_ENVIRONMENT == local ]] || [[ ! -z ${TEAMCITY_PR_NUMBER+x} ]]; then +if builder_is_debug_build || [[ $KEYMAN_VERSION_ENVIRONMENT == local ]] || [[ ! -z ${TEAMCITY_PR_NUMBER+x} ]]; then # We do a fast build for debug builds, local builds, test PR builds but not for master/beta/stable release builds GO_FAST=1 else @@ -125,8 +125,8 @@ wrap-symstore() { "$ProgramFilesx86/Windows Kits/10/Debuggers/x64/symstore.exe" \ add \ //s "$KEYMAN_SYMSTOREPATH" \ - //v "$VERSION_WIN" \ - //c "Version: $VERSION_WITH_TAG" \ + //v "$KEYMAN_VERSION_WIN" \ + //c "Version: $KEYMAN_VERSION_WITH_TAG" \ //compress //f "$@" } @@ -147,4 +147,4 @@ create-windows-output-folders() { mkdir -p "$WINDOWS_DEBUGPATH_APP" mkdir -p "$WINDOWS_DEBUGPATH_ENGINE" mkdir -p "$WINDOWS_DEBUGPATH_SUPPORT" -} \ No newline at end of file +} diff --git a/resources/build/xcode-utils.sh b/resources/build/xcode-utils.sh index 9476161ae6..b917b5d63f 100755 --- a/resources/build/xcode-utils.sh +++ b/resources/build/xcode-utils.sh @@ -42,10 +42,10 @@ function phaseSetBundleVersions() { TAGGED=false fi - # For command-line builds, VERSION and VERSION_WITH_TAG) are forwarded through xcodebuild. - if [ -z "${VERSION:-}" ]; then + # For command-line builds, KEYMAN_VERSION and KEYMAN_VERSION_WITH_TAG) are forwarded through xcodebuild. + if [ -z "${KEYMAN_VERSION:-}" ]; then # This is likely not a command-line build at the top level; it's been triggered through Xcode. - # The $VERSION-loading code is in build-utils.sh, but we need $THIS_SCRIPT to be set + # The $KEYMAN_VERSION-loading code is in build-utils.sh, but we need $THIS_SCRIPT to be set # (in similar manner to the "standard build header") in order to avoid script errors therein. THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" @@ -53,9 +53,9 @@ function phaseSetBundleVersions() { # local builds triggered through Xcode's UI, which aren't part of our CI processes. . "$KEYMAN_ROOT/resources/build/build-utils.sh" echo "phaseSetBundleVersions: UI build - fetching version from repository:" - echo " Plain: $VERSION" - echo " Tagged: $VERSION_WITH_TAG" - echo " Environment: $VERSION_ENVIRONMENT" + echo " Plain: $KEYMAN_VERSION" + echo " Tagged: $KEYMAN_VERSION_WITH_TAG" + echo " Environment: $KEYMAN_VERSION_ENVIRONMENT" else echo "phaseSetBundleVersions: Command-line build - using provided version parameters" fi @@ -76,48 +76,48 @@ function phaseSetBundleVersions() { APP_PLIST="$TARGET_BUILD_DIR/$INFOPLIST_PATH" echo "phaseSetBundleVersions: Setting CFBundleVersion to $BUILD_NUMBER for $APP_PLIST" /usr/libexec/Plistbuddy -c "Set :CFBundleVersion $BUILD_NUMBER" "$APP_PLIST" - echo "phaseSetBundleVersions: Setting CFBundleShortVersionString to $VERSION for $APP_PLIST" - /usr/libexec/Plistbuddy -c "Set :CFBundleShortVersionString $VERSION" "$APP_PLIST" + echo "phaseSetBundleVersions: Setting CFBundleShortVersionString to $KEYMAN_VERSION for $APP_PLIST" + /usr/libexec/Plistbuddy -c "Set :CFBundleShortVersionString $KEYMAN_VERSION" "$APP_PLIST" /usr/libexec/Plistbuddy -c "Print" "$APP_PLIST" # Only attempt to write this when directly specified (otherwise, generates minor warning) if [ $TAGGED == true ]; then - echo "phaseSetBundleVersions: Setting KeymanVersionWithTag to $VERSION_WITH_TAG for tagged version for $APP_PLIST" - /usr/libexec/Plistbuddy -c "Set :KeymanVersionWithTag $VERSION_WITH_TAG" "$APP_PLIST" - echo "phaseSetBundleVersions: Setting KeymanVersionEnvironment to $VERSION_ENVIRONMENT for $APP_PLIST" - /usr/libexec/Plistbuddy -c "Set :KeymanVersionEnvironment $VERSION_ENVIRONMENT" "$APP_PLIST" + echo "phaseSetBundleVersions: Setting KeymanVersionWithTag to $KEYMAN_VERSION_WITH_TAG for tagged version for $APP_PLIST" + /usr/libexec/Plistbuddy -c "Set :KeymanVersionWithTag $KEYMAN_VERSION_WITH_TAG" "$APP_PLIST" + echo "phaseSetBundleVersions: Setting KeymanVersionEnvironment to $KEYMAN_VERSION_ENVIRONMENT for $APP_PLIST" + /usr/libexec/Plistbuddy -c "Set :KeymanVersionEnvironment $KEYMAN_VERSION_ENVIRONMENT" "$APP_PLIST" fi if [ -f "${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}.dSYM/Contents/Info.plist" ]; then DSYM_PLIST="${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}.dSYM/Contents/Info.plist" echo "phaseSetBundleVersions: Setting CFBundleVersion to $BUILD_NUMBER for $DSYM_PLIST" /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $BUILD_NUMBER" "$DSYM_PLIST" - echo "phaseSetBundleVersions: Setting CFBundleShortVersionString to $VERSION for $DSYM_PLIST" - /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $VERSION" "$DSYM_PLIST" + echo "phaseSetBundleVersions: Setting CFBundleShortVersionString to $KEYMAN_VERSION for $DSYM_PLIST" + /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $KEYMAN_VERSION" "$DSYM_PLIST" fi } # Used by Keyman for iOS to update the human-readable string for its Settings screen. function setSettingsBundleVersion() { - # For command-line builds, VERSION and VERSION_WITH_TAG) are forwarded through xcodebuild. - if [ -z "${VERSION:-}" ]; then + # For command-line builds, KEYMAN_VERSION and KEYMAN_VERSION_WITH_TAG) are forwarded through xcodebuild. + if [ -z "${KEYMAN_VERSION:-}" ]; then # We're not a command-line build... so we'll need to retrieve these values ourselves with ./build-utils.sh. # Note that this script's process will not have access to TC environment variables, but that's fine for # local builds triggered through Xcode's UI, which aren't part of our CI processes. . "$KEYMAN_ROOT/resources/build/build-utils.sh" echo "setSettingsBundleVersion: UI build - fetching version from repository:" - echo " Plain: $VERSION" - echo " Tagged: $VERSION_WITH_TAG" + echo " Plain: $KEYMAN_VERSION" + echo " Tagged: $KEYMAN_VERSION_WITH_TAG" echo " Environment: (not setting, assume 'local')" else echo "setSettingsBundleVersion: Command-line build - using provided version parameters" fi SETTINGS_PLIST="${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Settings.bundle/Root.plist" - echo "setSettingsBundleVersion: Setting $VERSION_WITH_TAG for $SETTINGS_PLIST" + echo "setSettingsBundleVersion: Setting $KEYMAN_VERSION_WITH_TAG for $SETTINGS_PLIST" # We assume that entry 0 = the version "preference" entry. - /usr/libexec/PlistBuddy -c "Set :PreferenceSpecifiers:0:DefaultValue $VERSION_WITH_TAG" "$SETTINGS_PLIST" + /usr/libexec/PlistBuddy -c "Set :PreferenceSpecifiers:0:DefaultValue $KEYMAN_VERSION_WITH_TAG" "$SETTINGS_PLIST" } # Build Phase: Upload dSYM (debug) files to Sentry diff --git a/resources/builder.inc.sh b/resources/builder.inc.sh index 8f273d6b68..7b5d2a199d 100755 --- a/resources/builder.inc.sh +++ b/resources/builder.inc.sh @@ -1511,7 +1511,7 @@ _builder_parse_expanded_parameters() { # Per #11106, local builds use --debug by default. # Second condition prevents the block (and message) from executing when --debug is already specified explicitly. - if [[ $VERSION_ENVIRONMENT == "local" ]] && [[ $builder_debug != --debug ]] && ! $is_release; then + if [[ $KEYMAN_VERSION_ENVIRONMENT == "local" ]] && [[ $builder_debug != --debug ]] && ! $is_release; then builder_echo grey "Local build environment detected: setting --debug" _params+=(--debug) _builder_chosen_options+=(--debug) diff --git a/resources/locate_emscripten.inc.sh b/resources/locate_emscripten.inc.sh index 57ed0cd559..d390e83bd2 100644 --- a/resources/locate_emscripten.inc.sh +++ b/resources/locate_emscripten.inc.sh @@ -44,7 +44,7 @@ locate_emscripten() { # For developers, define KEYMAN_USE_EMSDK to do this on your # build machine. verify_emscripten_version() { - if [[ "$VERSION_ENVIRONMENT" != local || ! -z "${KEYMAN_USE_EMSDK+x}" ]]; then + if [[ "$KEYMAN_VERSION_ENVIRONMENT" != local || ! -z "${KEYMAN_USE_EMSDK+x}" ]]; then _select_emscripten_version_with_emsdk fi } diff --git a/resources/shellHelperFunctions.sh b/resources/shellHelperFunctions.sh index 469e8204fb..802106401b 100755 --- a/resources/shellHelperFunctions.sh +++ b/resources/shellHelperFunctions.sh @@ -170,19 +170,19 @@ write_download_info() { set_version ( ) { PRODUCT_PATH=$1 - if [ $VERSION ]; then + if [ $KEYMAN_VERSION ]; then if [ $2 ]; then # $2 = product name. - echo "Setting version numbers in $2 to $VERSION." + echo "Setting version numbers in $2 to $KEYMAN_VERSION." fi - /usr/libexec/Plistbuddy -c "Set CFBundleVersion $VERSION" "$PRODUCT_PATH/Info.plist" - /usr/libexec/Plistbuddy -c "Set CFBundleShortVersionString $VERSION" "$PRODUCT_PATH/Info.plist" + /usr/libexec/Plistbuddy -c "Set CFBundleVersion $KEYMAN_VERSION" "$PRODUCT_PATH/Info.plist" + /usr/libexec/Plistbuddy -c "Set CFBundleShortVersionString $KEYMAN_VERSION" "$PRODUCT_PATH/Info.plist" fi } # Uses npm to set the current package version (package.json). # -# This sets the version according to the current VERSION_WITH_TAG. +# This sets the version according to the current KEYMAN_VERSION_WITH_TAG. # # Usage: # @@ -194,7 +194,7 @@ set_npm_version () { # release of Keyman Developer -- these two versions should be in sync. Because this # is a large repo with multiple projects and build systems, it's better for us that # individual build systems don't take too much ownership of git tagging. :) - npm version --allow-same-version --no-git-tag-version --no-commit-hooks "$VERSION_WITH_TAG" + npm version --allow-same-version --no-git-tag-version --no-commit-hooks "$KEYMAN_VERSION_WITH_TAG" } # @@ -265,7 +265,7 @@ verify_npm_setup() { # If we are on CI environment, automatically select a node version with nvm # Also, a developer can set KEYMAN_USE_NVM variable to get this behaviour # automatically too (see /docs/build/node.md) - if [[ "$VERSION_ENVIRONMENT" != local || ! -z "${KEYMAN_USE_NVM+x}" ]]; then + if [[ "$KEYMAN_VERSION_ENVIRONMENT" != local || ! -z "${KEYMAN_USE_NVM+x}" ]]; then _select_node_version_with_nvm fi diff --git a/web/ci.sh b/web/ci.sh index e083b41455..f3f70eef93 100755 --- a/web/ci.sh +++ b/web/ci.sh @@ -37,7 +37,7 @@ builder_parse "$@" #### -TIER=$(cat ../TIER.md) +KEYMAN_TIER=$(cat ../TIER.md) BUILD_NUMBER=$(cat ../VERSION.md) function web_sentry_upload () { @@ -50,7 +50,7 @@ function web_sentry_upload () { # --strip-common-prefix does not take an argument, unlike --strip-prefix. It auto-detects # the most common prefix instead. - sentry-cli releases files "${VERSION_GIT_TAG}" upload-sourcemaps --strip-common-prefix "$1" \ + sentry-cli releases files "${KEYMAN_VERSION_GIT_TAG}" upload-sourcemaps --strip-common-prefix "$1" \ --rewrite --ext js --ext map --ext ts echo "Upload successful." } @@ -119,7 +119,7 @@ function prepare_s_keyman_com_action() { # Second phase: copy the artifacts over # The main build products are expected to reside at the root of this folder. - BASE_PUBLISH_FOLDER="${S_KEYMAN_COM}/kmw/engine/${VERSION}" + BASE_PUBLISH_FOLDER="${S_KEYMAN_COM}/kmw/engine/${KEYMAN_VERSION}" echo "FOLDER: ${BASE_PUBLISH_FOLDER}" mkdir -p "${BASE_PUBLISH_FOLDER}" @@ -130,27 +130,27 @@ function prepare_s_keyman_com_action() { # Third phase: tweak the sourcemaps # We can use an alt-mode of Web's sourcemap-root tool for this. for sourcemap in "${BASE_PUBLISH_FOLDER}/"*.map; do - node "${KEYMAN_ROOT}/web/build/tools/building/sourcemap-root/index.js" null "${sourcemap}" --sourceRoot "https://s.keyman.com/kmw/engine/${VERSION}/src" + node "${KEYMAN_ROOT}/web/build/tools/building/sourcemap-root/index.js" null "${sourcemap}" --sourceRoot "https://s.keyman.com/kmw/engine/${KEYMAN_VERSION}/src" done # Construct the PR - echo "Committing and pushing KeymanWeb release ${VERSION} to s.keyman.com" + echo "Committing and pushing KeymanWeb release ${KEYMAN_VERSION} to s.keyman.com" - ci_add_files "${S_KEYMAN_COM}" "kmw/engine/${VERSION}" + ci_add_files "${S_KEYMAN_COM}" "kmw/engine/${KEYMAN_VERSION}" if ! ci_repo_has_cached_changes "${S_KEYMAN_COM}"; then builder_die "No release was added to s.keyman.com, something went wrong" fi - ci_open_pull_request "${S_KEYMAN_COM}" auto/keymanweb/release "auto: KeymanWeb release ${VERSION}" + ci_open_pull_request "${S_KEYMAN_COM}" auto/keymanweb/release "auto: KeymanWeb release ${KEYMAN_VERSION}" } # Note: for now, this command is used to prepare the artifacts used by the download site, but # NOT to actually UPLOAD them via rsync or to produce related .download_info files. function prepare_downloads_keyman_com_action() { - UPLOAD_PATH="${KEYMAN_ROOT}/web/build/upload/${VERSION}" + UPLOAD_PATH="${KEYMAN_ROOT}/web/build/upload/${KEYMAN_VERSION}" # --- First action artifact - the KMW zip file --- - ZIP="${UPLOAD_PATH}/keymanweb-${VERSION}.zip" + ZIP="${UPLOAD_PATH}/keymanweb-${KEYMAN_VERSION}.zip" mkdir -p "${UPLOAD_PATH}" diff --git a/web/src/tools/building/check-build-size.sh b/web/src/tools/building/check-build-size.sh index 7a3a47f900..5b96459035 100755 --- a/web/src/tools/building/check-build-size.sh +++ b/web/src/tools/building/check-build-size.sh @@ -88,15 +88,15 @@ LOCAL_FILE=web/build/publish/release/keymanweb.js LOCAL_FILE_SIZE=`stat --printf="%s" $KEYMAN_ROOT/$LOCAL_FILE` # -# Get the most recent build for $TIER from downloads.keyman.com +# Get the most recent build for $KEYMAN_TIER from downloads.keyman.com # DOWNLOADS_VERSION_API=https://downloads.keyman.com/api/version/web REMOTE_KEYMANWEB_VERSIONS=`curl -s $DOWNLOADS_VERSION_API` -REMOTE_VERSION=`echo $REMOTE_KEYMANWEB_VERSIONS | $JQ -r ".web.$TIER"` +REMOTE_VERSION=`echo $REMOTE_KEYMANWEB_VERSIONS | $JQ -r ".web.$KEYMAN_TIER"` -REMOTE_FILE_NEW=https://downloads.keyman.com/web/$TIER/$REMOTE_VERSION/static/build/app/browser/release/keymanweb.js -REMOTE_FILE_OLD=https://downloads.keyman.com/web/$TIER/$REMOTE_VERSION/static/build/app/web/release/keymanweb.js +REMOTE_FILE_NEW=https://downloads.keyman.com/web/$KEYMAN_TIER/$REMOTE_VERSION/static/build/app/browser/release/keymanweb.js +REMOTE_FILE_OLD=https://downloads.keyman.com/web/$KEYMAN_TIER/$REMOTE_VERSION/static/build/app/web/release/keymanweb.js # If the remote file does not exist at the 'new' location, try the 'old' one instead. # Allows reorganization 'fallback' for the file-size check. diff --git a/windows/src/buildtools/sentry-upload-difs.sh b/windows/src/buildtools/sentry-upload-difs.sh index 8996d55cad..3d6b9faadb 100755 --- a/windows/src/buildtools/sentry-upload-difs.sh +++ b/windows/src/buildtools/sentry-upload-difs.sh @@ -31,7 +31,7 @@ cd "$KEYMAN_ROOT/windows/src" echo "Uploading symbols for desktop/" sentry-cli upload-dif -p keyman-windows -t breakpad -t pdb desktop --include-sources -sentry-cli releases -p keyman-windows files "$VERSION_GIT_TAG" upload-sourcemaps desktop/kmshell/xml +sentry-cli releases -p keyman-windows files "$KEYMAN_VERSION_GIT_TAG" upload-sourcemaps desktop/kmshell/xml echo "Uploading symbols for engine/" sentry-cli upload-dif -p keyman-windows -t breakpad -t pdb engine --include-sources diff --git a/windows/src/desktop/inst/build.sh b/windows/src/desktop/inst/build.sh index be3818b056..bcedcef95c 100755 --- a/windows/src/desktop/inst/build.sh +++ b/windows/src/desktop/inst/build.sh @@ -15,7 +15,7 @@ builder_describe "Installation files for Keyman for Windows" \ # after all other builds complete builder_describe_outputs \ - publish /windows/release/${VERSION}/keyman-${VERSION}.exe + publish /windows/release/${KEYMAN_VERSION}/keyman-${KEYMAN_VERSION}.exe builder_parse "$@" @@ -24,8 +24,8 @@ builder_parse "$@" . "$KEYMAN_ROOT/resources/build/win/zip.inc.sh" # In dev environments, we'll hack the tier to alpha; CI sets this for us in real builds. -if [[ -z ${TIER+x} ]]; then - TIER=alpha +if [[ -z ${KEYMAN_TIER+x} ]]; then + KEYMAN_TIER=alpha fi # We use different directories so that heat generates @@ -101,15 +101,15 @@ function do_publish() { function copy-installer() { builder_heading copy-installer - mkdir -p "$KEYMAN_ROOT/windows/release/${VERSION}" - cp keymandesktop.msi "$KEYMAN_ROOT/windows/release/${VERSION}/keymandesktop.msi" - cp keymandesktop.exe "$KEYMAN_ROOT/windows/release/${VERSION}/keyman-${VERSION}.exe" - cp "$WINDOWS_PROGRAM_APP/setup.exe" "$KEYMAN_ROOT/windows/release/${VERSION}/setup.exe" + mkdir -p "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}" + cp keymandesktop.msi "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}/keymandesktop.msi" + cp keymandesktop.exe "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}/keyman-${KEYMAN_VERSION}.exe" + cp "$WINDOWS_PROGRAM_APP/setup.exe" "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}/setup.exe" verify-installer-signatures # Copy the unsigned setup.exe for use in bundling scenarios; zip it up for clarity - wzzip "$KEYMAN_ROOT/windows/release/${VERSION}/setup-redist.zip" "$WINDOWS_PROGRAM_APP/setup-redist.exe" + wzzip "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}/setup-redist.zip" "$WINDOWS_PROGRAM_APP/setup-redist.exe" } function verify-program-signatures() { @@ -121,12 +121,12 @@ function verify-program-signatures() { function verify-installer-signatures() { builder_heading verify-installer-signatures - verify-all-executable-signatures-in-folder "$KEYMAN_ROOT/windows/release/${VERSION}" + verify-all-executable-signatures-in-folder "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}" } function test-releaseexists() { - if [[ -d "$KEYMAN_ROOT/windows/release/${VERSION}" ]]; then - builder_die "Release ${VERSION} already exists. Delete it or update VERSION.md and try again" + if [[ -d "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}" ]]; then + builder_die "Release ${KEYMAN_VERSION} already exists. Delete it or update VERSION.md and try again" fi } @@ -138,7 +138,7 @@ function do_candle() { local GUID1=$(generate_uuid) "$WIXHEAT" dir ../kmshell/xml -o desktopui.wxs -ag -cg DesktopUI -dr INSTALLDIR -suid -var var.DESKTOPUISOURCE -wx -nologo "$WIXHEAT" dir ../kmshell/locale -o locale.wxs -ag -cg Locale -dr INSTALLDIR -var var.LOCALESOURCE -wx -nologo - "$WIXCANDLE" -dVERSION_WITH_TAG=${VERSION_WITH_TAG} -dVERSION=${VERSION_WIN} -dRELEASE=${VERSION_RELEASE} -dPRODUCTID=$GUID1 \ + "$WIXCANDLE" -dKEYMAN_VERSION_WITH_TAG=${KEYMAN_VERSION_WITH_TAG} -dKEYMAN_VERSION=${KEYMAN_VERSION_WIN} -dRELEASE=${KEYMAN_VERSION_RELEASE} -dPRODUCTID=$GUID1 \ -dDESKTOPUISOURCE=../kmshell/xml -dLOCALESOURCE=../kmshell/locale "-dCefSourceDir=$KEYMAN_CEF4DELPHI_ROOT" \ keymandesktop.wxs desktopui.wxs locale.wxs cef.wxs } @@ -160,7 +160,7 @@ function create-setup-inf() { builder_heading create-setup-inf echo "[Setup]" > setup.inf - echo "Version=${VERSION_WIN}" >> setup.inf + echo "Version=${KEYMAN_VERSION_WIN}" >> setup.inf echo "MSIFileName=keymandesktop.msi" >> setup.inf echo "MSIOptions=" >> setup.inf echo "License=license.html" >> setup.inf diff --git a/windows/src/desktop/inst/keymandesktop.wxs b/windows/src/desktop/inst/keymandesktop.wxs index eaf3ef2516..f1e02adc9b 100644 --- a/windows/src/desktop/inst/keymandesktop.wxs +++ b/windows/src/desktop/inst/keymandesktop.wxs @@ -1,7 +1,7 @@  + Id="*" Name="Keyman $(var.RELEASE)" Version="$(var.KEYMAN_VERSION)" Language="1033"> @@ -44,10 +44,10 @@ - - + Maximum="$(var.KEYMAN_VERSION)" IncludeMaximum="no" MigrateFeatures="yes" Property="VERSION11FOUND" /> + + @@ -150,7 +150,7 @@ - + @@ -314,7 +314,7 @@ - + diff --git a/windows/src/engine/inst/build.sh b/windows/src/engine/inst/build.sh index db6bc2173c..22cd5954a6 100755 --- a/windows/src/engine/inst/build.sh +++ b/windows/src/engine/inst/build.sh @@ -14,7 +14,7 @@ builder_describe "Installation files for Keyman Engine for Windows" \ # after all other builds complete builder_describe_outputs \ - publish /windows/release/${VERSION}/keymanengine-${VERSION}.msm + publish /windows/release/${KEYMAN_VERSION}/keymanengine-${KEYMAN_VERSION}.msm builder_parse "$@" @@ -23,8 +23,8 @@ builder_parse "$@" . "$KEYMAN_ROOT/resources/build/win/zip.inc.sh" # In dev environments, we'll hack the tier to alpha; CI sets this for us in real builds. -if [[ -z ${TIER+x} ]]; then - TIER=alpha +if [[ -z ${KEYMAN_TIER+x} ]]; then + KEYMAN_TIER=alpha fi #------------------------------------------------------------------------------------------------------------------- @@ -35,7 +35,7 @@ function do_publish() { # # Build the installation archive # - "$WIXCANDLE" -dVERSION=$VERSION_WIN -dRELEASE=$VERSION_RELEASE -ext WixUtilExtension keymanengine.wxs components.wxs + "$WIXCANDLE" -dKEYMAN_VERSION=$KEYMAN_VERSION_WIN -dRELEASE=$KEYMAN_VERSION_RELEASE -ext WixUtilExtension keymanengine.wxs components.wxs # warning 1072 relates to Error table defined by WixUtilExtension. Doesn't really affect us. "$WIXLIGHT" -sw1072 -ext WixUtilExtension keymanengine.wixobj components.wixobj -o keymanengine.msm @@ -50,8 +50,8 @@ function do_publish() { function copy-installer() { builder_heading copy-installer - mkdir -p "$KEYMAN_ROOT/windows/release/${VERSION}" - cp keymanengine.msm "$KEYMAN_ROOT/windows/release/${VERSION}/keymanengine-${VERSION}.msm" + mkdir -p "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}" + cp keymanengine.msm "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}/keymanengine-${KEYMAN_VERSION}.msm" } function verify-program-signatures() { @@ -61,8 +61,8 @@ function verify-program-signatures() { } function test-releaseexists() { - if [[ -d "$KEYMAN_ROOT/windows/release/${VERSION}" ]]; then - builder_die "Release ${VERSION} already exists. Delete it or update VERSION.md and try again" + if [[ -d "$KEYMAN_ROOT/windows/release/${KEYMAN_VERSION}" ]]; then + builder_die "Release ${KEYMAN_VERSION} already exists. Delete it or update VERSION.md and try again" fi } diff --git a/windows/src/engine/inst/keymanengine.wxs b/windows/src/engine/inst/keymanengine.wxs index 9f92d97999..2aaaf1de9a 100644 --- a/windows/src/engine/inst/keymanengine.wxs +++ b/windows/src/engine/inst/keymanengine.wxs @@ -1,6 +1,6 @@  - + From 44fb0fe0e927aff5061fef530f2ba529b2834b93 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Wed, 7 May 2025 18:57:31 +0200 Subject: [PATCH 46/57] docs(common): update `builder_echo` documentation for TC blocks --- docs/builder.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/builder.md b/docs/builder.md index f4e3f88313..6c3ffd7c3e 100644 --- a/docs/builder.md +++ b/docs/builder.md @@ -634,6 +634,10 @@ Wraps the `echo` command with color and a script identifier prefix. ```bash builder_echo [mode] message +or +builder_echo start blockname message +or +builder_echo end blockname status message ``` ### Parameters @@ -647,6 +651,12 @@ mode will be `white`. * `warning`: A warning message, represented with yellow text * `error`: An error message, represented with red text (consider [`builder_die`]) * `debug`: A debug string, represented with teal text (consider [`builder_echo_debug`]) + * `start`: The beginning of a foldable block when running on TeamCity. The + blockname will show up as the title of the collapsable block, + the message as heading inside of the block. If not running on TeamCity + the message is output as heading. + * `end`: The end of the foldable block `blockname` when running on TeamCity. + Ignored if not running on TeamCity identical to `builder_echo status message`. Or color identifiers: * `white`: Normal white text, the default if **mode** is omitted @@ -666,6 +676,9 @@ mode will be `white`. * `setmark`: A marker for a section heading, represented with purple text * **message**: a string (surround with quote marks) +* **blockname**: a string with the name of the collapsable block (surround with quote marks) +* **status**: one of the `mode` values representing the result of an action + (`success`, `warning`, or `error`) ### Description From 83256aae415e73b816de03e27215a26257c5fa0d Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Wed, 7 May 2025 14:01:39 -0400 Subject: [PATCH 47/57] auto: increment master version to 19.0.34 --- HISTORY.md | 7 +++++++ VERSION.md | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 96049f2853..914eb5372d 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,12 @@ # Keyman Version History +## 19.0.33 alpha 2025-05-07 + +* maint(common): automatically set --debug option for local-environment builder-script uses (#13827) +* docs(web): add a Web engine keystroke lifecycle internal doc (#13759) +* maint(common): use function to detect if running on TC (#13844) +* docs(common): document new `builder_is_running_on_teamcity` function (#13852) + ## 19.0.32 alpha 2025-05-06 * change(web): replace USVString with string in predictive-text engine (#13785) diff --git a/VERSION.md b/VERSION.md index aec8dab02b..eb5ab30356 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -19.0.33 \ No newline at end of file +19.0.34 \ No newline at end of file From 1fbaf60cb55b9e5e0de69017972cc83f48012376 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 7 May 2025 20:16:50 +0200 Subject: [PATCH 48/57] docs(common): update readme link to builder.md Fixes: #13851 --- resources/build/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/build/README.md b/resources/build/README.md index ead7975b8b..1166c948fa 100644 --- a/resources/build/README.md +++ b/resources/build/README.md @@ -12,9 +12,9 @@ including this file... ## Various tools -### build-utils.sh +### build-utils.sh, builder.inc.sh -See [build-utils.md](build-utils.md) +See [builder.md](builder.md) ### jq-win64 From dd563e8a117096c07f62c0e5a2b2a6cc7403cdfe Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Thu, 8 May 2025 13:56:23 +0700 Subject: [PATCH 49/57] fix(web): sustain active batched-layout mode when keyboard is switched Fixes: #13859 Fixes: KEYMAN-WEB-R4 --- web/src/engine/osk/src/views/oskView.ts | 11 +++++++++-- web/src/engine/osk/src/visualKeyboard.ts | 5 ++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/web/src/engine/osk/src/views/oskView.ts b/web/src/engine/osk/src/views/oskView.ts index 8977125d60..6c8eeb1420 100644 --- a/web/src/engine/osk/src/views/oskView.ts +++ b/web/src/engine/osk/src/views/oskView.ts @@ -625,14 +625,18 @@ export default abstract class OSKView return; } + const vkbd = this.vkbd; try { this.deferLayout = true; - if(this.vkbd) { - this.vkbd.deferLayout = true; + if(vkbd) { + vkbd.deferLayout = true; } closure(); } finally { this.deferLayout = false; + if(vkbd) { + vkbd.deferLayout = false; + } if(this.vkbd) { this.vkbd.deferLayout = false; } @@ -781,6 +785,9 @@ export default abstract class OSKView this.banner.appendStyles(); if(this.vkbd) { + // Layout-deferral mode may be active during a keyboard-swap; the newly-incoming keyboard + // should inherit that value! + this.vkbd.deferLayout = this.deferLayout; // Create the key preview (for phones) this.vkbd.createKeyTip(); diff --git a/web/src/engine/osk/src/visualKeyboard.ts b/web/src/engine/osk/src/visualKeyboard.ts index da9ccb37c3..5ba5a9996c 100644 --- a/web/src/engine/osk/src/visualKeyboard.ts +++ b/web/src/engine/osk/src/visualKeyboard.ts @@ -804,9 +804,12 @@ export default class VisualKeyboard extends EventEmitter implements Ke } get layoutHeight(): ParsedLengthStyle { + // currently: equivalent to if(is touch keyboard) if (this.usesFixedHeightScaling) { - let baseHeight = this.height; + let baseHeight = this.height; // initially undefined! baseHeight -= this._borderWidth * 2; + // For robustness, as there are legal cases where this.height may be undefined. + baseHeight = (isNaN(baseHeight) || baseHeight < 0) ? 0 : baseHeight; return ParsedLengthStyle.inPixels(baseHeight); } else { return ParsedLengthStyle.forScalar(1); From d59291c06228d30040e44dd94f08668a0c98c80e Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 8 May 2025 09:22:26 +0200 Subject: [PATCH 50/57] maint(common): remove obsolete code from docker-images `build.sh` Looks like a merge undid some of the changes from #13537 so that we ended up with duplicate code. This change cleans this up. --- resources/docker-images/build.sh | 55 ++------------------------------ 1 file changed, 3 insertions(+), 52 deletions(-) diff --git a/resources/docker-images/build.sh b/resources/docker-images/build.sh index a5623adaab..1feabe6577 100755 --- a/resources/docker-images/build.sh +++ b/resources/docker-images/build.sh @@ -28,62 +28,13 @@ builder_describe \ builder_parse "$@" -_add_build_args() { - local var=$1 - local default_var=$2 - local name=$3 - local value - - value="${!var:=${!default_var:-}}" - - build_args+=(--build-arg="${var}=${value}") - - if [[ -n "${build_version:-}" ]]; then - build_version="${build_version}-${name:-}${value}" - else - build_version="${name}${value}" - fi -} - -_convert_parameters_to_build_args() { - build_args=() - build_version= - local required_node_version keyman_default_distro - # shellcheck disable=SC2034 - required_node_version="$(_print_expected_node_version)" - # shellcheck disable=SC2034 - keyman_default_distro="ubuntu" - - _add_build_args DISTRO keyman_default_distro "" - _add_build_args DISTRO_VERSION KEYMAN_DEFAULT_VERSION_UBUNTU_CONTAINER "" - _add_build_args JAVA_VERSION KEYMAN_VERSION_JAVA java - _add_build_args REQUIRED_NODE_VERSION required_node_version node - _add_build_args REQUIRED_EMSCRIPTEN_VERSION KEYMAN_MIN_VERSION_EMSCRIPTEN emsdk - - if [[ -n "${BASE_VERSION:-}" ]]; then - build_args+=(--build-arg="BASE_VERSION=${BASE_VERSION}") - fi -} - -_check_for_default_values() { - if [[ -z "${DISTRO_VERSION:-}" ]] && [[ -z "${JAVA_VERSION:-}" ]]; then - is_default_values=true - else - is_default_values=false - fi -} - -_is_default_values() { - ${is_default_values} -} - build_action() { local platform=$1 builder_echo debug "Building image for ${platform}" if [[ "${platform}" == "base" ]]; then - # shellcheck disable=SC2154 # set by _convert_parameters_to_build_args + # shellcheck disable=SC2154 # set by convert_parameters_to_args docker pull "${DISTRO}:${DISTRO_VERSION}" elif [[ "${platform}" == "linux" ]]; then cp "${KEYMAN_ROOT}/linux/debian/control" "${platform}" @@ -116,8 +67,8 @@ test_action() { "${platform}" -- ./build.sh configure,build,test:"${platform}" } -_check_for_default_values -_convert_parameters_to_build_args +check_for_default_values +convert_parameters_to_args if builder_has_action build; then build_action base From 907a16012ca3d834dad188f20f2f8e054e535c1b Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 8 May 2025 16:59:35 +0200 Subject: [PATCH 51/57] maint(common): output start/end messages if not running on TC If we're not running on TC we should output the start/end messages as headings unless it's a child build. This was the previous behavior before we added support for TC blocks. --- resources/build/test/test.sh | 107 ++++++++++++++++++++++++++++------- resources/builder.inc.sh | 4 +- 2 files changed, 89 insertions(+), 22 deletions(-) diff --git a/resources/build/test/test.sh b/resources/build/test/test.sh index 48fad740e4..3379b165f6 100755 --- a/resources/build/test/test.sh +++ b/resources/build/test/test.sh @@ -201,45 +201,110 @@ fi #---------------------------------------------------------------------- function builder_echo_tests() { - echo -e "${COLOR_BLUE}## Testing builder_echo${COLOR_RESET}" - _old_builder_debug_internal=${_builder_debug_internal} - _OLD_TEAMICITY_GIT_PATH=${TEAMCITY_GIT_PATH:-} + echo -e "${COLOR_BLUE}## Testing builder_echo (heading)${COLOR_RESET}" + local _old_builder_debug_internal=${_builder_debug_internal} # regular build, no internal debug - TEAMCITY_GIT_PATH="" _builder_debug_internal=false - expected="" - result=$(builder_echo start "foo" "description") + expected="$(echo -e "${BUILDER_BOLD}${COLOR_BRIGHT_WHITE}[resources/build/test]${COLOR_RESET} ${COLOR_BLUE}description${COLOR_RESET}")" + result=$(builder_echo heading "description") if [[ "${result[*]}" != "${expected}" ]]; then - builder_die "FAIL: Wrong output for 'builder_echo start foo description' (no debug):\n Actual : ${result[*]}\n Expected: ${expected}" - fi - expected="" - result=$(builder_echo end "foo" success "description") - if [[ "${result[*]}" != "${expected}" ]]; then - builder_die "FAIL: Wrong output for 'builder_echo end foo success description' (no debug):\n Actual : ${result[*]}\n Expected: ${expected}" - fi - expected="$(builder_echo error "description")" - result=$(builder_echo end "foo" error "description") - if [[ "${result[*]}" != "${expected}" ]]; then - builder_die "FAIL: Wrong output for 'builder_echo end foo error description' (no debug):\n Actual : ${result[*]}\n Expected: ${expected}" + builder_die "FAIL: Wrong output for 'builder_echo heading description' (no debug):\n Actual : ${result[*]}\n Expected: ${expected}" fi # regular build, with internal debug _builder_debug_internal=true + expected="$(echo -e "${BUILDER_BOLD}${COLOR_BRIGHT_WHITE}[resources/build/test]${COLOR_RESET} ${COLOR_BLUE}description${COLOR_RESET}")" + result=$(builder_echo heading "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo start foo description' (debug):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + _builder_debug_internal=${_old_builder_debug_internal} +} + +#---------------------------------------------------------------------- +function builder_echo_start_end_tests() { + echo -e "${COLOR_BLUE}## Testing builder_echo (start/end)${COLOR_RESET}" + local _old_builder_debug_internal=${_builder_debug_internal} + local _OLD_TEAMICITY_GIT_PATH=${TEAMCITY_GIT_PATH:-} + local _old_builder_is_child=${_builder_is_child} + + # regular build, no internal debug, no child build + TEAMCITY_GIT_PATH="" + _builder_debug_internal=false + _builder_is_child=1 expected="$(builder_echo heading "description")" result=$(builder_echo start "foo" "description") if [[ "${result[*]}" != "${expected}" ]]; then - builder_die "FAIL: Wrong output for 'builder_echo start foo description' (debug):\n Actual : ${result[*]}\n Expected: ${expected}" + builder_die "FAIL: Wrong output for 'builder_echo start foo description' (no debug, no child):\n Actual : ${result[*]}\n Expected: ${expected}" fi expected="$(builder_echo success "description")" result=$(builder_echo end "foo" success "description") if [[ "${result[*]}" != "${expected}" ]]; then - builder_die "FAIL: Wrong output for 'builder_echo end foo success description' (debug):\n Actual : ${result[*]}\n Expected: ${expected}" + builder_die "FAIL: Wrong output for 'builder_echo end foo success description' (no debug, no child):\n Actual : ${result[*]}\n Expected: ${expected}" fi expected="$(builder_echo error "description")" result=$(builder_echo end "foo" error "description") if [[ "${result[*]}" != "${expected}" ]]; then - builder_die "FAIL: Wrong output for 'builder_echo end foo error description' (debug):\n Actual : ${result[*]}\n Expected: ${expected}" + builder_die "FAIL: Wrong output for 'builder_echo end foo error description' (no debug, no child):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + + # regular build, no internal debug, is child build + TEAMCITY_GIT_PATH="" + _builder_debug_internal=false + _builder_is_child=0 + expected="" + result=$(builder_echo start "foo" "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo start foo description' (no debug, is child):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + expected="" + result=$(builder_echo end "foo" success "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo end foo success description' (no debug, is child):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + expected="$(builder_echo error "description")" + result=$(builder_echo end "foo" error "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo end foo error description' (no debug, is child):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + + # regular build, with internal debug, no child build + _builder_debug_internal=true + _builder_is_child=1 + expected="$(builder_echo heading "description")" + result=$(builder_echo start "foo" "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo start foo description' (debug, no child):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + expected="$(builder_echo success "description")" + result=$(builder_echo end "foo" success "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo end foo success description' (debug, no child):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + expected="$(builder_echo error "description")" + result=$(builder_echo end "foo" error "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo end foo error description' (debug, no child):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + + # regular build, with internal debug, is child build + _builder_debug_internal=true + _builder_is_child=0 + expected="$(builder_echo heading "description")" + result=$(builder_echo start "foo" "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo start foo description' (debug, is child):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + expected="$(builder_echo success "description")" + result=$(builder_echo end "foo" success "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo end foo success description' (debug, is child):\n Actual : ${result[*]}\n Expected: ${expected}" + fi + expected="$(builder_echo error "description")" + result=$(builder_echo end "foo" error "description") + if [[ "${result[*]}" != "${expected}" ]]; then + builder_die "FAIL: Wrong output for 'builder_echo end foo error description' (debug, is child):\n Actual : ${result[*]}\n Expected: ${expected}" fi # simulate running on TeamCity @@ -287,8 +352,10 @@ $(builder_echo heading "description")" fi TEAMCITY_GIT_PATH="${_OLD_TEAMICITY_GIT_PATH}" _builder_debug_internal=${_old_builder_debug_internal} + _builder_is_child=${_old_builder_is_child} } builder_echo_tests +builder_echo_start_end_tests # Run tests based in separate scripts to facilitate their operation diff --git a/resources/builder.inc.sh b/resources/builder.inc.sh index 8f273d6b68..bf2235b97d 100755 --- a/resources/builder.inc.sh +++ b/resources/builder.inc.sh @@ -182,7 +182,7 @@ builder_echo() { block="$2" shift 2 color="heading" - if ! builder_is_running_on_teamcity; then + if ! builder_is_running_on_teamcity && builder_is_child_build; then do_output=${_builder_debug_internal:-false} fi elif [[ $1 == "end" ]]; then @@ -191,7 +191,7 @@ builder_echo() { block="$2" color="$3" shift 3 - if [[ "${color}" != "error" ]] && ! builder_is_running_on_teamcity; then + if [[ "${color}" != "error" ]] && ! builder_is_running_on_teamcity && builder_is_child_build; then do_output=${_builder_debug_internal:-false} fi fi From 3634dd170225f8316333cdae46c5f3e365a47992 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 8 May 2025 17:44:40 +0200 Subject: [PATCH 52/57] maint(common): add three more functions to detect if running on CI This adds the three additional functions `builder_is_running_on_ci`, `builder_is_running_on_docker`, and `builder_is_running_on_gha` to be able to detect if the build is running in a CI or CI-like container environment. --- docs/builder.md | 47 ++++++++++++++++++++++++++++++++++++++++ resources/builder.inc.sh | 27 +++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/docs/builder.md b/docs/builder.md index 6c3ffd7c3e..d9ca9e3896 100644 --- a/docs/builder.md +++ b/docs/builder.md @@ -880,6 +880,53 @@ fi -------------------------------------------------------------------------------- +## `builder_is_running_on_ci` function + +Returns `true` (aka 0) if the script runs on TeamCity or as a GitHub action. + +### Usage + +```bash +if builder_is_running_on_ci; then + ... +fi +``` + +-------------------------------------------------------------------------------- + +## `builder_is_running_on_docker` function + +Returns `true` (aka 0) if the script runs in a Docker container (i.e. if +the `DOCKER_RUNNING` environment variable is set). + +**Note** that this environment variable is not set automatically, so you'll have +to set it before starting a build, or set it in the docker image. + +### Usage + +```bash +if builder_is_running_on_docker; then + ... +fi +``` + +-------------------------------------------------------------------------------- + +## `builder_is_running_on_gha` function + +Returns `true` (aka 0) if the script runs as a GitHub action (i.e. if the +`GITHUB_RUN_ID` environment variable is set). + +### Usage + +```bash +if builder_is_running_on_gha; then + ... +fi +``` + +-------------------------------------------------------------------------------- + ## `builder_is_running_on_teamcity` function Returns `true` (aka 0) if the script runs on TeamCity (i.e. if the diff --git a/resources/builder.inc.sh b/resources/builder.inc.sh index 8f273d6b68..8f13fb8746 100755 --- a/resources/builder.inc.sh +++ b/resources/builder.inc.sh @@ -2140,6 +2140,33 @@ builder_is_target_excluded_by_platform() { return 1 } +# Returns 0 if the script is running on a CI server (TeamCity or GitHub Actions) +builder_is_running_on_ci() { + if builder_is_running_on_teamcity || builder_is_running_on_gha; then + return 0 + else + return 1 + fi +} + +# Returns 0 if the script is running in a Docker container +builder_is_running_on_docker() { + if [[ -z ${DOCKER_RUNNING:-} ]]; then + return 1 + else + return 0 + fi +} + +# Returns 0 if the script is running in a GitHub Actions environment +builder_is_running_on_gha() { + if [[ -z ${GITHUB_RUN_ID:-} ]]; then + return 1 + else + return 0 + fi +} + # Returns 0 if the script is running on TeamCity builder_is_running_on_teamcity() { if [[ -z "${TEAMCITY_GIT_PATH:-}" ]]; then From 9428fc3e87091116c1172bc27a05945b946dd309 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Thu, 8 May 2025 14:03:13 -0400 Subject: [PATCH 53/57] auto: increment master version to 19.0.35 --- HISTORY.md | 8 ++++++++ VERSION.md | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 914eb5372d..33c89d3e26 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,13 @@ # Keyman Version History +## 19.0.34 alpha 2025-05-08 + +* docs(common): update `builder_echo` documentation for TC blocks (#13855) +* fix(windows): add breadcrumb to download failures (#13826) +* fix(web): sustain active batched-layout mode when keyboard is switched (#13860) +* maint(common): remove obsolete code from docker-images `build.sh` (#13861) +* maint(common): output start/end messages if not running on TC (#13868) + ## 19.0.33 alpha 2025-05-07 * maint(common): automatically set --debug option for local-environment builder-script uses (#13827) diff --git a/VERSION.md b/VERSION.md index eb5ab30356..d8676f6b6a 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -19.0.34 \ No newline at end of file +19.0.35 \ No newline at end of file From d8e7353553a595cfc35a4193c8109d3a44a36e9f Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 9 May 2025 03:48:07 +0200 Subject: [PATCH 54/57] chore(common): fix docs link --- resources/build/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/build/README.md b/resources/build/README.md index 1166c948fa..edc7a74151 100644 --- a/resources/build/README.md +++ b/resources/build/README.md @@ -14,7 +14,7 @@ including this file... ### build-utils.sh, builder.inc.sh -See [builder.md](builder.md) +See [builder.md](../../docs/builder.md) ### jq-win64 From 7f12f904ebd7dc7d283ac48f1df1d304e3fede75 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Fri, 9 May 2025 11:39:57 +0200 Subject: [PATCH 55/57] maint(common): address code review comments - remove `builder_is_running_on_ci` function since there already is a similar `builder_is_ci_build` function - use `GITHUB_ACTIONS` environment variable instead of `GITHUB_RUN_ID` to detect if we're run be GitHub Actions --- docs/builder.md | 16 +--------------- resources/builder.inc.sh | 11 +---------- 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/docs/builder.md b/docs/builder.md index d9ca9e3896..700567b531 100644 --- a/docs/builder.md +++ b/docs/builder.md @@ -880,20 +880,6 @@ fi -------------------------------------------------------------------------------- -## `builder_is_running_on_ci` function - -Returns `true` (aka 0) if the script runs on TeamCity or as a GitHub action. - -### Usage - -```bash -if builder_is_running_on_ci; then - ... -fi -``` - --------------------------------------------------------------------------------- - ## `builder_is_running_on_docker` function Returns `true` (aka 0) if the script runs in a Docker container (i.e. if @@ -915,7 +901,7 @@ fi ## `builder_is_running_on_gha` function Returns `true` (aka 0) if the script runs as a GitHub action (i.e. if the -`GITHUB_RUN_ID` environment variable is set). +`GITHUB_ACTIONS` environment variable is set). ### Usage diff --git a/resources/builder.inc.sh b/resources/builder.inc.sh index 8f13fb8746..2969141dce 100755 --- a/resources/builder.inc.sh +++ b/resources/builder.inc.sh @@ -2140,15 +2140,6 @@ builder_is_target_excluded_by_platform() { return 1 } -# Returns 0 if the script is running on a CI server (TeamCity or GitHub Actions) -builder_is_running_on_ci() { - if builder_is_running_on_teamcity || builder_is_running_on_gha; then - return 0 - else - return 1 - fi -} - # Returns 0 if the script is running in a Docker container builder_is_running_on_docker() { if [[ -z ${DOCKER_RUNNING:-} ]]; then @@ -2160,7 +2151,7 @@ builder_is_running_on_docker() { # Returns 0 if the script is running in a GitHub Actions environment builder_is_running_on_gha() { - if [[ -z ${GITHUB_RUN_ID:-} ]]; then + if [[ -z ${GITHUB_ACTIONS:-} ]]; then return 1 else return 0 From 4c4d39ef853819c4ef45adf10cf1cd95ba113249 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Fri, 9 May 2025 11:54:39 +0200 Subject: [PATCH 56/57] maint(common): use new `builder_is_running_on_*` functions --- resources/build/build-utils.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/resources/build/build-utils.sh b/resources/build/build-utils.sh index 2cbbcbfba9..60b5db5ab1 100755 --- a/resources/build/build-utils.sh +++ b/resources/build/build-utils.sh @@ -84,7 +84,8 @@ function findVersion() { VERSION_TAG= fi - if [[ -z "${TEAMCITY_VERSION-}" && -z "${GITHUB_ACTIONS-}" && -z "${KEYMAN_PKG_BUILD-}" ]]; then + if ! builder_is_running_on_teamcity && ! builder_is_running_on_gha \ + && [[ -z "${KEYMAN_PKG_BUILD-}" ]]; then # Local dev machine, not TeamCity or GitHub Action and not .deb package build VERSION_TAG="$VERSION_TAG-local" VERSION_ENVIRONMENT=local @@ -98,7 +99,7 @@ function findVersion() { else VERSION_TAG="$VERSION_TAG-test-$TEAMCITY_PR_NUMBER" fi - elif [ -n "${GITHUB_ACTIONS-}" ] && ${GHA_TEST_BUILD-}; then + elif builder_is_running_on_gha && ${GHA_TEST_BUILD-}; then VERSION_ENVIRONMENT="test" # Note GHA_BRANCH can be 'master', 'beta', or 'stable-x.y' # This indicates we are running a Test build. From 48fce24df399da7288a7453ed45c0b52f413635e Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Mon, 12 May 2025 01:54:16 -0400 Subject: [PATCH 57/57] auto: increment stable-18.0 version to 18.0.237 (history cherry-pick to master) --- HISTORY.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 33c89d3e26..53b5c68dcd 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -191,6 +191,23 @@ * refactor(windows): rename `TKeymanMutex.MutexOwned` to `TakeOwnership` and add `ReleaseOwnership` (#13168) * chore: increment to alpha 19.0 (#13187) +## 18.0.236 stable 2025-05-12 + +* chore(linux): Update debian changelog (#13737) +* chore(linux): add a stub unit test to allow successful coverage reporting (#13741) +* fix(android): Use Alert Dialog if keyboard pkg missing languages (#13802) +* maint(web): merge LMLayer CI build config with standard Web CI build config (#13808) +* fix(ios): restore keyboard-scale settings for older, still-supported iOS devices (#13817) +* change(ios): limit reports about devices without predefined scaling entries (#13828) +* chore(ios): Update inuktitut_pirurvik to 1.4.1 (#13841) +* fix(web): add robustness for bad touch-layout fontsize specs (#13838) +* change(linux): add ICU dependency needed to build on Arch Linux (#13843) +* fix(mac): add version metadata after building tests (#13853) +* fix(web): sustain active batched-layout mode when keyboard is switched (#13863) +* fix(developer): remove ngrok binary at build time (#13873) +* maint(common): apply new codeowners from master (#13874) +* chore(mac,windows): Update Crowdin strings for Italian (#13872) + ## 18.0.234 beta 2025-04-22 * fix(android): Require RELEASE_OEM env vars to build FirstVoices Android (#13725)