Skip to content

Commit

Permalink
Merge pull request #9867 from keymanapp/chore/linux/9801_coreversion
Browse files Browse the repository at this point in the history
chore(core): Add additional API checks 🎬
  • Loading branch information
ermshiperete authored Nov 14, 2023
2 parents 00414ca + 5badb17 commit 039e859
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 31 deletions.
21 changes: 20 additions & 1 deletion .github/workflows/deb-packaging.README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,28 @@ You can manually trigger a deb-packaging action on GitHub, e.g. to test changes:
--data "{ \"event_type\": \"deb-pr-packaging: master\", \
\"client_payload\": { \
\"buildSha\": \"$(git rev-parse refs/heads/master)\", \
\"headSha\": \"$(git rev-parse refs/heads/master)\", \
\"branch\": \"master\", \
\"baseBranch\": \"master\",
\"baseRef\": \"$(git rev-parse refs/heads/master^)\",
\"user\": \"${USER}\",
\"isTestBuild\": \"true\"}" \
https://api.github.com/repos/<yourgithubname>/keyman/dispatches
```

To trigger a build for PR #1234 in a branch `pr-1234` this would look similar
to this:

```bash
curl --write-out '\n' --request POST \
--header "Accept: application/vnd.github+json" \
--header "Authorization: token $GITHUB_TOKEN" \
--data "{ \"event_type\": \"deb-pr-packaging: PR #1234\", \
\"client_payload\": { \
\"buildSha\": \"$(git rev-parse refs/heads/pr-1234)\", \
\"branch\": \"pr-1234\", \
\"baseBranch\": \"master\",
\"baseRef\": \"$(git rev-parse refs/heads/master)\",
\"user\": \"${USER}\",
\"isTestBuild\": \"true\"}" \
https://api.github.com/repos/<yourgithubname>/keyman/dispatches
```
24 changes: 14 additions & 10 deletions .github/workflows/deb-packaging.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
name: "Ubuntu packaging"
run-name: "Ubuntu packaging - ${{ github.event.client_payload.branch }} (branch ${{ github.head_ref }}), by @${{ github.actor }}"
run-name: "Ubuntu packaging - ${{ github.event.client_payload.branch }} (branch ${{ github.event.client_payload.baseBranch }}), by @${{ github.event.client_payload.user }}"
on:
repository_dispatch:
types: ['deb-release-packaging:*', 'deb-pr-packaging:*']

# Input:
# buildSha: The SHA of the commit to build, e.g. of the branch or
# refs/pull/1234/merge for PR
# headSha: The SHA of the branch head. Same as buildSha for regular
# builds, SHA of refs/pull/1234/head for PRs
# refs/pull/1234/head for PR
# branch: The branch to build, for a PR in the form `PR-1234`
# baseBranch: For a PR the base branch, otherwise the same as `branch`
# baseRef: The ref of the previous commit. For a PR the same as `baseBranch`.
# user: The user that triggered the build or created the PR
# isTestBuild: false for Releases, otherwise true

env:
Expand Down Expand Up @@ -40,7 +41,7 @@ jobs:
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
/repos/$GITHUB_REPOSITORY/statuses/${{ github.event.client_payload.headSha }} \
/repos/$GITHUB_REPOSITORY/statuses/${{ github.event.client_payload.buildSha }} \
-f state='pending' \
-f target_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" \
-f description='Debian packaging started' \
Expand Down Expand Up @@ -236,6 +237,7 @@ jobs:
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c #v3.3.0
with:
ref: '${{ github.event.client_payload.buildSha }}'
fetch-depth: 0

- name: Download Artifacts
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
Expand All @@ -251,10 +253,12 @@ jobs:
run: |
cd linux
PKG_NAME=libkeymancore
SRC_PKG="${GITHUB_WORKSPACE}/artifacts/keyman-srcpkg/keyman_${{ needs.sourcepackage.outputs.VERSION }}-1.debian.tar.xz" \
BIN_PKG="${GITHUB_WORKSPACE}/artifacts/keyman-binarypkgs/${PKG_NAME}_${{ needs.sourcepackage.outputs.VERSION }}-1${{ needs.sourcepackage.outputs.PRERELEASE_TAG }}+jammy1_amd64.deb" \
PKG_VERSION="${{ needs.sourcepackage.outputs.VERSION }}" \
./scripts/deb-packaging.sh --gha verify 2>> $GITHUB_STEP_SUMMARY
./scripts/deb-packaging.sh \
--gha \
--bin-pkg "${GITHUB_WORKSPACE}/artifacts/keyman-binarypkgs/${PKG_NAME}_${{ needs.sourcepackage.outputs.VERSION }}-1${{ needs.sourcepackage.outputs.PRERELEASE_TAG }}+jammy1_amd64.deb" \
--git-sha "${{ github.event.client_payload.buildSha }}" \
--git-base "${{ github.event.client_payload.baseRef }}" \
verify 2>> $GITHUB_STEP_SUMMARY
- name: Archive .symbols file
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
Expand Down Expand Up @@ -292,7 +296,7 @@ jobs:
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
/repos/$GITHUB_REPOSITORY/statuses/${{ github.event.client_payload.headSha }} \
/repos/$GITHUB_REPOSITORY/statuses/${{ github.event.client_payload.buildSha }} \
-f state="$RESULT" \
-f target_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" \
-f description="$MSG" \
Expand Down
2 changes: 1 addition & 1 deletion docs/linux/ibus-keyman.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Source code for Keyman engine for IBus is in [linux/ibus-keyman](../../linux/ibu

## Requirements

meson (>= 0.53)
meson (>= 0.57)

## Building

Expand Down
176 changes: 162 additions & 14 deletions linux/scripts/deb-packaging.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#!/usr/bin/env bash
# shellcheck disable=SC2154 # (variables are set in build-utils.sh)
# Actions for creating a Debian source package. Used by deb-packaging.yml GHA.

set -eu
shopt -s inherit_errexit

## START STANDARD BUILD SCRIPT INCLUDE
# adjust relative paths as necessary
Expand All @@ -11,14 +13,18 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"

builder_describe \
"Helper for building Debian packages." \
"dependencies Install dependencies as found in debian/control" \
"source+ Build source package" \
"verify Verify API" \
"--gha Build from GitHub Action"
"dependencies Install dependencies as found in debian/control" \
"source+ Build source package" \
"verify Verify API" \
"--gha Build from GitHub Action" \
"--bin-pkg=BIN_PKG Path and name of binary Debian package (for verify action)" \
"--git-sha=GIT_SHA The SHA of the HEAD commit, e.g. of the PR branch (for verify action)" \
"--git-base=GIT_BASE The ref of the base commit, e.g. usually the name of the base" \
" branch, e.g. master, stable-16.0 (for verify action)"

builder_parse "$@"

cd "$REPO_ROOT/linux"
cd "${REPO_ROOT}/linux"

if builder_has_option --gha; then
START_STEP="::group::${COLOR_GREEN}"
Expand Down Expand Up @@ -50,19 +56,161 @@ source_action() {
mv builddebs/* "${OUTPUT_PATH:-..}"
}

output_log() {
echo "$1" >&2
builder_echo "$1"
}

output_ok() {
echo ":heavy_check_mark: $1" >&2
builder_echo green "OK: $1"
}

output_warning() {
echo ":warning: $1" >&2
builder_echo warning "WARNING: $1"
}

output_error() {
echo ":x: $1" >&2
builder_echo error "ERROR: $1"
}

check_api_not_changed() {
# Checks that the API did not change compared to what's documented in the .symbols file
tmpDir=$(mktemp -d)
# shellcheck disable=SC2064
trap "rm -rf \"${tmpDir}\"" ERR
dpkg -x "${BIN_PKG}" "${tmpDir}"
cd debian
dpkg-gensymbols -v"${VERSION}" -p"${PKG_NAME}" -e"${tmpDir}"/usr/lib/x86_64-linux-gnu/"${LIB_NAME}".so* -O"${PKG_NAME}.symbols" -c4
output_ok "${LIB_NAME} API didn't change"
cd "${REPO_ROOT}/linux"
rm -rf "${tmpDir}"
trap ERR
}

#
# Compare the SHA of the base and head commits for changes to the .symbols file
#
is_symbols_file_changed() {
local CHANGED_REF CHANGED_BASE
CHANGED_REF=$(git rev-parse "${GIT_SHA}":"linux/debian/${PKG_NAME}.symbols")
CHANGED_BASE=$(git rev-parse "${GIT_BASE}":"linux/debian/${PKG_NAME}.symbols")
if [[ "${CHANGED_REF}" == "${CHANGED_BASE}" ]]; then
return 1
fi
return 0
}

check_updated_version_number() {
# Checks that the package version number got updated in the .symbols file if it got changed
# shellcheck disable=SC2310
if is_symbols_file_changed; then
# .symbols file changed, now check if the package version got updated as well
# Note: We don't check that ALL changes in that file have an updated package version -
# we hope this gets flagged in code review.
# Note: This version number check may not match the actual released version, if the branch
# is out of date when it is merged to the release branch (master/beta/stable-x.y). If this
# is considered important, then make sure the branch is up to date, and wait for test
# builds to complete, before merging.
if ! git log -p -1 -- "debian/${PKG_NAME}.symbols" | grep -q "${VERSION}"; then
output_error "${PKG_NAME}.symbols file got changed without changing the package version number of the symbol"
EXIT_CODE=1
else
output_ok "${PKG_NAME}.symbols file got updated with package version number"
fi
else
output_ok "${PKG_NAME}.symbols file didn't change"
fi
}

get_api_version_in_symbols_file() {
# Extract 1 from "libkeymancore.so.1 libkeymancore #MINVER#"
local firstline
firstline="$(head -1 "debian/${PKG_NAME}.symbols")"
firstline="${firstline#"${PKG_NAME}".so.}"
firstline="${firstline%% *}"
echo "${firstline}"
}

is_api_version_updated() {
local NEW_VERSION OLD_VERSION
git checkout "${GIT_BASE}" -- "debian/${PKG_NAME}.symbols"
OLD_VERSION=$(get_api_version_in_symbols_file)
git checkout "${GIT_SHA}" -- "debian/${PKG_NAME}.symbols"
NEW_VERSION=$(get_api_version_in_symbols_file)
if (( NEW_VERSION > OLD_VERSION )); then
return 0
fi
return 1
}

check_for_major_api_changes() {
# Checks that API version number gets updated if API changes
local WHAT_CHANGED CHANGES INSERTED DELETED MODIFIED

# shellcheck disable=2310
if ! is_symbols_file_changed; then
output_ok "No major API change"
return
fi

WHAT_CHANGED=$(git diff "${GIT_BASE}".."${GIT_SHA}" -- "debian/${PKG_NAME}.symbols" | diffstat -m -t | tail -1)

IFS=',' read -r -a CHANGES <<< "${WHAT_CHANGED}"
INSERTED="${CHANGES[0]}"
DELETED="${CHANGES[1]}"
MODIFIED="${CHANGES[2]}"

if (( DELETED > 0 )) || (( MODIFIED > 0 )); then
builder_echo "Major API change: ${DELETED} lines deleted and ${MODIFIED} lines modified"
# shellcheck disable=2310
if ! is_api_version_updated; then
output_error "Major API change without updating API version number in ${PKG_NAME}.symbols file"
EXIT_CODE=2
else
output_ok "API version number got updated in ${PKG_NAME}.symbols file after major API change"
fi
elif (( INSERTED > 0 )); then
output_ok "Minor API change: ${INSERTED} lines added"
# We currently don't check version number for minor API changes
else
output_ok "No major API change"
fi
}

check_for_api_version_consistency() {
# Checks that the (major) API version number in the .symbols file and
# in CORE_API_VERSION.md are the same
local symbols_version api_version
symbols_version=$(get_api_version_in_symbols_file)
api_version=$(cat ../core/CORE_API_VERSION.md)
# Extract major version number from "1.0.0"
api_version=${api_version%%.*}

if (( symbols_version == api_version )); then
output_ok "API version in .symbols file and in CORE_API_VERSION.md is the same"
else
output_error "API version in .symbols file and in CORE_API_VERSION.md is different"
EXIT_CODE=3
fi
}

verify_action() {
tar xf "${SRC_PKG}"
PKG_NAME=libkeymancore
LIB_NAME=libkeymancore
if [ ! -f debian/${PKG_NAME}.symbols ]; then
echo ":warning: Missing ${PKG_NAME}.symbols file" >&2
else
tmpDir=$(mktemp -d)
dpkg -x "${BIN_PKG}" "$tmpDir"
cd debian
dpkg-gensymbols -v"${PKG_VERSION}" -p${PKG_NAME} -e"${tmpDir}"/usr/lib/x86_64-linux-gnu/${LIB_NAME}.so* -O${PKG_NAME}.symbols -c4
echo ":heavy_check_mark: ${LIB_NAME} API didn't change" >&2
if [[ ! -f debian/${PKG_NAME}.symbols ]]; then
output_warning "Missing ${PKG_NAME}.symbols file"
exit 0
fi

EXIT_CODE=0
check_api_not_changed
check_updated_version_number
check_for_major_api_changes
check_for_api_version_consistency
exit "${EXIT_CODE}"
}

builder_run_action dependencies dependencies_action
Expand Down
17 changes: 12 additions & 5 deletions resources/build/trigger-builds.inc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -69,32 +69,39 @@ function triggerGitHubActionsBuild() {
local IS_TEST_BUILD="$1"
local GITHUB_ACTION="$2"
local GIT_BRANCH="${3:-master}"
local GIT_BUILD_SHA GIT_HEAD_SHA
local GIT_BASE_BRANCH="${GIT_BRANCH}"
local GIT_USER="keyman-server"
local GIT_BUILD_SHA GIT_BASE_REF JSON

local GITHUB_SERVER=https://api.github.com/repos/keymanapp/keyman

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_HEAD_SHA="${GIT_BUILD_SHA}"
GIT_BASE_REF="$(git rev-parse "${GIT_BUILD_SHA}^")"
GIT_EVENT_TYPE="${GITHUB_ACTION}: release@${VERSION_WITH_TAG}"
elif [[ $GIT_BRANCH != stable-* ]] && [[ $GIT_BRANCH =~ [0-9]+ ]]; then
GIT_BUILD_SHA="$(git rev-parse "refs/pull/${GIT_BRANCH}/head")"
GIT_HEAD_SHA="$(git rev-parse "refs/pull/${GIT_BRANCH}/head")"
GIT_EVENT_TYPE="${GITHUB_ACTION}: PR #${GIT_BRANCH}"
JSON=$(curl -s "${GITHUB_SERVER}/pulls/${GIT_BRANCH}")
GIT_USER="$(echo "$JSON" | $JQ -r '.user.login')"
GIT_BASE_REF="$(echo "$JSON" | $JQ -r '.base.ref')"
GIT_BASE_BRANCH="${GIT_BASE_REF}"
GIT_BRANCH="PR-${GIT_BRANCH}"
else
GIT_BUILD_SHA="$(git rev-parse "refs/heads/${GIT_BRANCH}")"
GIT_HEAD_SHA="${GIT_BUILD_SHA}"
GIT_BASE_REF="$(git rev-parse "${GIT_BUILD_SHA}^")"
GIT_EVENT_TYPE="${GITHUB_ACTION}: ${GIT_BRANCH}"
fi

local DATA="{
\"event_type\": \"$GIT_EVENT_TYPE\", \
\"client_payload\": { \
\"buildSha\": \"$GIT_BUILD_SHA\", \
\"headSha\": \"$GIT_HEAD_SHA\", \
\"branch\": \"$GIT_BRANCH\", \
\"baseBranch\": \"$GIT_BASE_BRANCH\", \
\"baseRef\": \"$GIT_BASE_REF\", \
\"user\": \"$GIT_USER\", \
\"isTestBuild\": \"$IS_TEST_BUILD\" \
}}"

Expand Down

0 comments on commit 039e859

Please sign in to comment.