[neon/ubuntu-core/ago/ci-overhaul] /: Overhaul CI

Antoine Gonzalez null at kde.org
Fri Aug 9 11:14:01 BST 2024


Git commit 42a02e51a1bb62036c5e7d133dbdbc2fe31d62fd by Antoine Gonzalez.
Committed on 09/08/2024 at 10:12.
Pushed by daspood into branch 'ago/ci-overhaul'.

Overhaul CI

- Remove CI dependencies to sysadmin/ci-utilities
- Add job for generating and signing models
- Rework image-building jobs to rely on models present on the repo
- Rework image-building jobs to upload image with Notary service
- Rework Makefile to remove dependency on jsons for models
- Update README to reflect changes to models workflow

M  +10   -9    Makefile
M  +6    -8    README.md
M  +3    -4    debian/.gitlab-ci-neon.yml
A  +46   -0    debian/neon-core-image-dangerous.yml
A  +36   -0    debian/neon-core-image-signed.yml
A  +53   -0    debian/neon-core-models.yml
A  +139  -0    kde-neon-core-dangerous-amd64.model
A  +139  -0    kde-neon-core-signed-amd64.model

https://invent.kde.org/neon/ubuntu-core/-/commit/42a02e51a1bb62036c5e7d133dbdbc2fe31d62fd

diff --git a/Makefile b/Makefile
index 723cde4..3c5837a 100644
--- a/Makefile
+++ b/Makefile
@@ -4,20 +4,21 @@ dangerous: kde-neon-core-dangerous-amd64.tar.gz
 
 signed: kde-neon-core-signed-amd64.tar.gz
 
-kde-neon-core-signed-amd64.json: kde-neon-core-amd64.json
-	./finalize-json.sh signed $< $@
-
-kde-neon-core-dangerous-amd64.json: kde-neon-core-amd64.json
-	./finalize-json.sh dangerous $< $@
-
 kde-neon-core-signed-amd64.snap-list: kde-neon-core-amd64.json
 	./create-snap-list.sh signed $< $@
 
 kde-neon-core-dangerous-amd64.snap-list: kde-neon-core-amd64.json
 	./create-snap-list.sh dangerous $< $@
 
-%.model: %.json
-	snap sign -k kde-neon-core-image-key $< > $@
+kde-neon-core-signed-amd64.model: kde-neon-core-amd64.json
+	./finalize-json.sh signed kde-neon-core-amd64.json model-in.json
+	snap sign -k kde-neon-core-image-key model-in.json > $@
+	rm model-in.json
+
+kde-neon-core-dangerous-amd64.model: kde-neon-core-amd64.json
+	./finalize-json.sh dangerous kde-neon-core-amd64.json model-in.json
+	snap sign -k kde-neon-core-image-key model-in.json > $@
+	rm model-in.json
 
 %.img: %.model %.snap-list
 	$(eval SNAPS = $(shell cat $(basename $@).snap-list))
@@ -30,6 +31,6 @@ kde-neon-core-dangerous-amd64.snap-list: kde-neon-core-amd64.json
 
 clean:
 	rm -rf *.model.build
-	rm -f *.snap-list *.model *.img *.tar.gz *-signed-*.json *-dangerous-*.json
+	rm -f *.snap-list *.img *.tar.gz *-signed-*.json *-dangerous-*.json
 
 .PHONY: all clean dangerous signed
diff --git a/README.md b/README.md
index ae5a951..b668f73 100644
--- a/README.md
+++ b/README.md
@@ -4,21 +4,19 @@ This repository contains all that's needed to build and run images provided the
 
 ## Building images
 
-There are two grades of images: signed and dangerous. Using `make <grade>` to build one of the two images. `make` or `make all` will build both the dangerous and the signed images. They will also be automatically compressed in `tar.gz` format at the end of the process.
+There are two grades of images: signed and dangerous. Using `make <grade>` to build one of the two images. `make` or `make all` will build both the dangerous and the signed images. They will also be automatically compressed in `tar.gz` format at the end of the process. You can also use `make kde-neon-core-<grade>-amd64.img` to build the image without compression and without deleting temporary files.
 
 ### Signatures and keys
 
-Signatures will occur during this process. This requires having an Ubuntu One account as described here:
+In order to build the image, a signed `.model` file needs to exist. Up-to-date models are provided in the repository.
 
-https://ubuntu.com/core/docs/create-ubuntu-one
+After changing the `kde-neon-core-amd64.json` file, you will need to update the `kde-neon-core-<grade>-amd64.model` files. These files are generated by the CI:
 
-This also requires having registered keys, as described in the first two steps of this page:
+Go to https://invent.kde.org/neon/ubuntu-core/-/pipelines/new. On this page, select your branch, and click the "Run pipeline" button. In the pipeline view, you can click the "neon_core_models" job to manually start it.
 
-https://ubuntu.com/core/docs/sign-model-assertion
+Your branch needs to be protected, and its name needs to match the `models.*` pattern for the job to run.
 
-The `Makefile` will handle the rest for you but it assumes your key to be created with the name `kde-neon-core-image-key`.
-
-Also, no build can occur if you're not authenticated in your Ubuntu One account with `snapcraft`. To sanity check this, running `snapcraft whoami` will tell you under which account you are authenticated.
+Once the job is complete, it will upload both `dangerous` and `signed` versions of the model as pipeline artefacts. You can then download them, test them locally, and commit then.
 
 ### dangerous vs signed
 
diff --git a/debian/.gitlab-ci-neon.yml b/debian/.gitlab-ci-neon.yml
index fbdd84c..5695086 100644
--- a/debian/.gitlab-ci-neon.yml
+++ b/debian/.gitlab-ci-neon.yml
@@ -2,7 +2,6 @@
 # SPDX-License-Identifier: CC0-1.0
 
 include:
-  - project: sysadmin/ci-utilities
-    file:
-      - /gitlab-templates/snap-image-dangerous.yml
-#      - /gitlab-templates/snap-image-signed.yml
\ No newline at end of file
+  - local: debian/neon-core-models.yml
+  - local: debian/neon-core-image-dangerous.yml
+  #- local: debian/neon-core-image-signed.yml
diff --git a/debian/neon-core-image-dangerous.yml b/debian/neon-core-image-dangerous.yml
new file mode 100644
index 0000000..5565e6f
--- /dev/null
+++ b/debian/neon-core-image-dangerous.yml
@@ -0,0 +1,46 @@
+neon_core_image_dangerous:
+  rules:
+    # Allow manual trigger on `models.*` branches
+    - if: '$CI_COMMIT_BRANCH =~ /models\..*/'
+      when: manual
+    # Otherwise, only build the image on master
+    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
+      when: always
+    # Only let it run if the required variables are present
+    # These are normally defined on protected branches on our normal repository but we do the logic this way to allow someone else to set this up in their fork if they want
+    - if: '$SNAPCRAFT_STORE_CREDENTIALS == null || $SNAP_GPG_PRIVATE_KEY == null || $SNAP_GPG_OWNER_TRUST == null'
+      when: never
+  variables:
+    SNAPCRAFT_BUILD_ENVIRONMENT: "host"
+    SNAPCRAFT_MANAGED_MODE: "y"
+  tags:
+    - Snap
+  interruptible: true
+  script:
+    # get the missing plasma-desktop-session snap from the latest build...
+    - mkdir workspace/ && cd workspace/
+    - wget -O Snap_artifacts.zip "https://invent.kde.org/api/v4/projects/neon%2fsnap-packaging%2fplasma-desktop-session/jobs/artifacts/master/download?job=snap_snapcraft_lxd"
+    - unzip -e Snap_artifacts.zip
+    - mv .kde-ci-packages/plasma-desktop-session*.snap $CI_PROJECT_DIR/local-snaps/plasma-desktop-session.snap
+    - cd $CI_PROJECT_DIR
+
+    # build the image with the project's tooling
+    - echo building kde-neon-core in dangerous mode ...
+    - make dangerous 2>&1 | tee task.log
+
+    # Create a folder to publish the files...
+    - mkdir -p $CI_PROJECT_DIR/.kde-ci-packages/
+    - mv -vf *.tar.gz $CI_PROJECT_DIR/.kde-ci-packages/
+    # Bring in the Notary Service tooling and ask it to publish for us please
+    - git clone https://invent.kde.org/sysadmin/ci-notary-service
+    - git clone https://invent.kde.org/sysadmin/ci-utilities
+    - python3 -u ci-notary-service/publishbuild.py --config ci-utilities/signing/publishbuild.ini --platform snap-image "$CI_PROJECT_DIR/.kde-ci-packages/"
+  after_script:
+    # Cleanup local state
+    - git clean -dfx .
+  artifacts:
+    name: Dangerous image
+    when: always
+    paths:
+      - "task.log"
+    expire_in: 28 days
diff --git a/debian/neon-core-image-signed.yml b/debian/neon-core-image-signed.yml
new file mode 100644
index 0000000..b2a28f3
--- /dev/null
+++ b/debian/neon-core-image-signed.yml
@@ -0,0 +1,36 @@
+neon_core_image_signed:
+  rules:
+    # Only build the image on master
+    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
+      when: always
+    # Only let it run if the required variables are present
+    # These are normally defined on protected branches on our normal repository but we do the logic this way to allow someone else to set this up in their fork if they want
+    - if: '$SNAPCRAFT_STORE_CREDENTIALS == null || $SNAP_GPG_PRIVATE_KEY == null || $SNAP_GPG_OWNER_TRUST == null'
+      when: never
+  variables:
+    SNAPCRAFT_BUILD_ENVIRONMENT: "host"
+    SNAPCRAFT_MANAGED_MODE: "y"
+  tags:
+    - Snap
+  interruptible: true
+  script:
+    # build the image with the project's tooling
+    - echo building kde-neon-core in signed mode ...
+    - make signed 2>&1 | tee task.log
+
+    # Create a folder to publish the files...
+    - mkdir -p $CI_PROJECT_DIR/.kde-ci-packages/
+    - mv -vf *.tar.gz $CI_PROJECT_DIR/.kde-ci-packages/
+    # Bring in the Notary Service tooling and ask it to publish for us please
+    - git clone https://invent.kde.org/sysadmin/ci-notary-service
+    - git clone https://invent.kde.org/sysadmin/ci-utilities
+    - python3 -u ci-notary-service/publishbuild.py --config ci-utilities/signing/publishbuild.ini --platform snap-image "$CI_PROJECT_DIR/.kde-ci-packages/"
+  after_script:
+    # Cleanup local state
+    - git clean -dfx .
+  artifacts:
+    name: Signed image
+    when: always
+    paths:
+      - "task.log"
+    expire_in: 28 days
diff --git a/debian/neon-core-models.yml b/debian/neon-core-models.yml
new file mode 100644
index 0000000..b1d5647
--- /dev/null
+++ b/debian/neon-core-models.yml
@@ -0,0 +1,53 @@
+neon_core_models:
+  rules:
+    # Only allow manual trigger on `models.*` branches
+    - if: '$CI_COMMIT_BRANCH =~ /models\..*/'
+      when: manual
+    # Only let it run if the required variables are present
+    # These are normally defined on protected branches on our normal repository but we do the logic this way to allow someone else to set this up in their fork if they want
+    - if: '$SNAPCRAFT_STORE_CREDENTIALS == null || $SNAP_GPG_PRIVATE_KEY == null || $SNAP_GPG_OWNER_TRUST == null'
+      when: never
+  variables:
+    SNAPCRAFT_BUILD_ENVIRONMENT: "host"
+    SNAPCRAFT_MANAGED_MODE: "y"
+  tags:
+    - Snap
+  interruptible: true
+  script:
+    # prepare the Snap specific GnuPG workspace
+    - rm -rf $HOME/.snap/gnupg/
+    - mkdir -p -m 0700 $HOME/.snap/gnupg/
+    - mkdir -p -m 0700 $HOME/.snap/gnupg/private-keys-v1.d/
+    # export it as a env var so the import commands below work on it...
+    - export GNUPGHOME=$HOME/.snap/gnupg/
+    # feed snap's gpg the required key
+    - echo $SNAP_GPG_PRIVATE_KEY | base64 --decode | gpg --batch --import
+    # make sure the key is trusted
+    - gpg --import-ownertrust <(echo "$SNAP_GPG_OWNER_TRUST")
+    # test the keys
+    - gpg --list-keys
+    # test the login
+    - snapcraft whoami
+
+    # change the Makefile to use the correct key name for signing models
+    - sed -i 's/kde-neon-core-image-key/kde-snapcraft-key/g' Makefile
+
+    # build the model with the project's tooling
+    - echo re-generating models for $CI_PROJECT_NAME ...
+    - make -B kde-neon-core-dangerous-amd64.model 2>&1 | tee task.log
+    - make -B kde-neon-core-signed-amd64.model 2>&1 | tee task.log
+
+    # make the artifacts dir
+    - mkdir -p $CI_PROJECT_DIR/.kde-ci-packages/
+    # copy the new models to the artifacts dir
+    - cp -vf ./*.model  $CI_PROJECT_DIR/.kde-ci-packages/
+  after_script:
+    # cleanup local state, including the GPG workspace and the Snapcraft authentication credentials
+    - rm -rf $HOME/.snap/gnupg/
+  artifacts:
+    name: Signed models
+    when: always
+    paths:
+      - "*.model"
+      - "task.log"
+    expire_in: 28 days
diff --git a/kde-neon-core-dangerous-amd64.model b/kde-neon-core-dangerous-amd64.model
new file mode 100644
index 0000000..ed897c0
--- /dev/null
+++ b/kde-neon-core-dangerous-amd64.model
@@ -0,0 +1,139 @@
+type: model
+authority-id: 2rsYZu6kqYVFsSejExu4YENdXQEO40Xb
+series: 16
+brand-id: 2rsYZu6kqYVFsSejExu4YENdXQEO40Xb
+model: kde-neon-core-22-amd64
+architecture: amd64
+base: plasma-core22-desktop
+display-name: KDE Neon Core 22 (amd64), dangerous
+grade: dangerous
+snaps:
+  -
+    default-channel: latest/edge
+    id: 9TJUGzZ1Vt503ZXdjOQmVfF6k4pAVrAO
+    name: pc-plasma-desktop
+    type: gadget
+  -
+    default-channel: 23.10/stable
+    id: pYVQrBcKmBa0mZ4CCN7ExT6jH8rY1hza
+    name: pc-kernel
+    type: kernel
+  -
+    default-channel: latest/edge/ubuntu-core-desktop
+    id: PMrrV4ml8uWuEUDBT8dSGnKUYbevVhc4
+    name: snapd
+    type: snapd
+  -
+    default-channel: latest/edge
+    id: X9TwqMA7C0ENRxpA7Y4DzwPZvbDc20sR
+    name: plasma-core22-desktop
+    type: base
+  -
+    default-channel: latest/edge
+    id: shFM21t3gsBQnlceeTRrWEdNoaLD88my
+    name: plasma-desktop-session
+    type: app
+  -
+    default-channel: latest/stable
+    id: amcUKQILKXHHTlmSa7NMdnXSx02dNeeT
+    name: core22
+    type: base
+  -
+    default-channel: 22/stable
+    id: RmBXKl6HO6YOC2DE4G2q1JzWImC04EUy
+    name: network-manager
+    type: app
+  -
+    default-channel: latest/stable
+    id: EISPgh06mRh1vordZY9OZ34QHdd7OrdR
+    name: bare
+    type: base
+  -
+    default-channel: latest/stable
+    id: jZLfBRzf1cYlYysIjD2bwSzNtngY0qit
+    name: gtk-common-themes
+    type: app
+  -
+    default-channel: latest/stable
+    id: lATO8HzwVvrAPrlZRAWpfyrJKlAJrZS3
+    name: gnome-42-2204
+    type: app
+  -
+    default-channel: latest/stable
+    id: m1eQacDdXCthEwWQrESei3Zao3d5gfJF
+    name: cups
+    type: app
+  -
+    default-channel: latest/stable
+    id: WJKWBUuCDufOFw2p24tvkbbw02plGkbd
+    name: ipp-usb
+    type: app
+  -
+    default-channel: 22/stable
+    id: dVK2PZeOLKA7vf1WPCap9F8luxTk9Oll
+    name: avahi
+    type: app
+  -
+    default-channel: 22/stable
+    id: JmzJi9kQvHUWddZ32PDJpBRXUpGRxvNS
+    name: bluez
+    type: app
+  -
+    default-channel: latest/stable
+    id: J60k4JY0HppjwOjW8dZdYc8obXKxujRu
+    name: lxd
+    type: app
+  -
+    default-channel: latest/edge
+    id: xODwiAdjx9KGChvI1z9Xx2JWJE7oLFF6
+    name: ubuntu-core-desktop-init
+    type: app
+  -
+    default-channel: latest/stable
+    id: 3wdHCAVyZEmYsCMFDE9qt92UV8rC8Wdk
+    name: firefox
+    presence: optional
+    type: app
+  -
+    default-channel: latest/stable
+    id: DlAIkaMJ1XMsnQRKcn0EjE2nc1S37X4r
+    name: kf6-core22
+    type: app
+  -
+    default-channel: latest/stable
+    id: SfUqQ280Y4bJ0k64qtBKTTXq5ml46tvQ
+    name: okular
+    presence: optional
+    type: app
+  -
+    default-channel: latest/stable
+    id: exqoWOIGvIl1u4gzKvpjLCZ9cvI6UTbP
+    name: gwenview
+    presence: optional
+    type: app
+  -
+    default-channel: latest/stable
+    id: CwdMAZoScOw1AcaGwtwtJYiOov9gZwyL
+    name: elisa
+    presence: optional
+    type: app
+  -
+    default-channel: latest/stable
+    id: kDq3GCXn1MxmDShWY2WZCsJ0uV1mgGOa
+    name: kwrite
+    presence: optional
+    type: app
+storage-safety: prefer-encrypted
+timestamp: 2024-08-09T09:29:51+00:00
+sign-key-sha3-384: 3euluygUnLeUKLKaWsPve6O9rb9sMFrjTokZgbI74LfLAn-eyi0JwxOVdd1QQ_Vp
+
+AcLBcwQAAQoAHRYhBPtpKo5I2PSFB0DBRsXyZbcusBCQBQJmteGPAAoJEMXyZbcusBCQdTsQALei
+BPnfvofYC54yJkpoZy9A1l1KoRoYrKcyCVX7eZFUdNO07uPDAX6TLEqE2nvJWE400R3tlEmORyMY
+sr2AWT0us+GHS9tItUTkh6vuq/mlYnt+TiUG30Yb7R/m0FcPcAvS3W3ZdS6HE1B+GmD43R4cI6Yh
+tcpQMXPIYr40ddDvTNJjwEeSQ8BguVKEyZK4wLbmnRyFMNRaEb2g+F0OdQXicEBFn993tle/Mvpl
+Ynko+tm68RihkdF8+SYh87/kqoEnWsPTzylwu+7ZVuYgNMztSh2EE0NpWPu7/bgPbThBT7vyY/qh
+F6JvTqNRyOzWW6vqH2ib2PNbPYPaadEc7BIbDludNJuI+LWviyg5K/nn4ssxsQGfE30JhJfXjaVw
+BM9q31mxhwgEaBpKB5gDWNOxQR8EbDpqXbuypnXoQtY8Dfeg6oIaSoGUxfA513PMo2oALH9iOXuk
+KQV57LvlzOlRcz+LNNJuScSIhz8XgfZOjUCDSdC2kiBBVdW96tfwNYCWWiGl1Z4VuBCoUjU6+SUO
+OMSBwyWFzsfatcIoEaBIevMHRfavgpz+0FuLgBPD+bjX2Wpfr6h8XQW2GL11ueh2wWesVsCrSo/w
+mJagAvHjP3pXPZTcfGFlnDM84tWCFV0dkmCd+lUAAV1bLMd4UUdXTl/PPOpam27iBcCW9hkZ
diff --git a/kde-neon-core-signed-amd64.model b/kde-neon-core-signed-amd64.model
new file mode 100644
index 0000000..25050e2
--- /dev/null
+++ b/kde-neon-core-signed-amd64.model
@@ -0,0 +1,139 @@
+type: model
+authority-id: 2rsYZu6kqYVFsSejExu4YENdXQEO40Xb
+series: 16
+brand-id: 2rsYZu6kqYVFsSejExu4YENdXQEO40Xb
+model: kde-neon-core-22-amd64
+architecture: amd64
+base: plasma-core22-desktop
+display-name: KDE Neon Core 22 (amd64), signed
+grade: signed
+snaps:
+  -
+    default-channel: latest/edge
+    id: 9TJUGzZ1Vt503ZXdjOQmVfF6k4pAVrAO
+    name: pc-plasma-desktop
+    type: gadget
+  -
+    default-channel: 23.10/stable
+    id: pYVQrBcKmBa0mZ4CCN7ExT6jH8rY1hza
+    name: pc-kernel
+    type: kernel
+  -
+    default-channel: latest/edge/ubuntu-core-desktop
+    id: PMrrV4ml8uWuEUDBT8dSGnKUYbevVhc4
+    name: snapd
+    type: snapd
+  -
+    default-channel: latest/edge
+    id: X9TwqMA7C0ENRxpA7Y4DzwPZvbDc20sR
+    name: plasma-core22-desktop
+    type: base
+  -
+    default-channel: latest/edge
+    id: shFM21t3gsBQnlceeTRrWEdNoaLD88my
+    name: plasma-desktop-session
+    type: app
+  -
+    default-channel: latest/stable
+    id: amcUKQILKXHHTlmSa7NMdnXSx02dNeeT
+    name: core22
+    type: base
+  -
+    default-channel: 22/stable
+    id: RmBXKl6HO6YOC2DE4G2q1JzWImC04EUy
+    name: network-manager
+    type: app
+  -
+    default-channel: latest/stable
+    id: EISPgh06mRh1vordZY9OZ34QHdd7OrdR
+    name: bare
+    type: base
+  -
+    default-channel: latest/stable
+    id: jZLfBRzf1cYlYysIjD2bwSzNtngY0qit
+    name: gtk-common-themes
+    type: app
+  -
+    default-channel: latest/stable
+    id: lATO8HzwVvrAPrlZRAWpfyrJKlAJrZS3
+    name: gnome-42-2204
+    type: app
+  -
+    default-channel: latest/stable
+    id: m1eQacDdXCthEwWQrESei3Zao3d5gfJF
+    name: cups
+    type: app
+  -
+    default-channel: latest/stable
+    id: WJKWBUuCDufOFw2p24tvkbbw02plGkbd
+    name: ipp-usb
+    type: app
+  -
+    default-channel: 22/stable
+    id: dVK2PZeOLKA7vf1WPCap9F8luxTk9Oll
+    name: avahi
+    type: app
+  -
+    default-channel: 22/stable
+    id: JmzJi9kQvHUWddZ32PDJpBRXUpGRxvNS
+    name: bluez
+    type: app
+  -
+    default-channel: latest/stable
+    id: J60k4JY0HppjwOjW8dZdYc8obXKxujRu
+    name: lxd
+    type: app
+  -
+    default-channel: latest/edge
+    id: xODwiAdjx9KGChvI1z9Xx2JWJE7oLFF6
+    name: ubuntu-core-desktop-init
+    type: app
+  -
+    default-channel: latest/stable
+    id: 3wdHCAVyZEmYsCMFDE9qt92UV8rC8Wdk
+    name: firefox
+    presence: optional
+    type: app
+  -
+    default-channel: latest/stable
+    id: DlAIkaMJ1XMsnQRKcn0EjE2nc1S37X4r
+    name: kf6-core22
+    type: app
+  -
+    default-channel: latest/stable
+    id: SfUqQ280Y4bJ0k64qtBKTTXq5ml46tvQ
+    name: okular
+    presence: optional
+    type: app
+  -
+    default-channel: latest/stable
+    id: exqoWOIGvIl1u4gzKvpjLCZ9cvI6UTbP
+    name: gwenview
+    presence: optional
+    type: app
+  -
+    default-channel: latest/stable
+    id: CwdMAZoScOw1AcaGwtwtJYiOov9gZwyL
+    name: elisa
+    presence: optional
+    type: app
+  -
+    default-channel: latest/stable
+    id: kDq3GCXn1MxmDShWY2WZCsJ0uV1mgGOa
+    name: kwrite
+    presence: optional
+    type: app
+storage-safety: prefer-encrypted
+timestamp: 2024-08-09T09:29:54+00:00
+sign-key-sha3-384: 3euluygUnLeUKLKaWsPve6O9rb9sMFrjTokZgbI74LfLAn-eyi0JwxOVdd1QQ_Vp
+
+AcLBcwQAAQoAHRYhBPtpKo5I2PSFB0DBRsXyZbcusBCQBQJmteGSAAoJEMXyZbcusBCQYuwQALx3
+wbL/0KMscT4sOM4HSrNClLpPJIPdnk/Yk+mEd0oQJ5RcgsF2B4UDBbAd3usGkCEzuNIzhnC1mU94
+WBCzloyOcrCHVZClthYMQ5QJok5o/mGk+5C2u1ncNVGBXpKyY2i/7McBffKcLR4kwl+22wSF+uSX
+i3XLiwBnQxNfHF+7TQ4U8SMFdGzClMl3fLIdrXlfidNp6s+wEXtr/m0cCXYh3rRWDcylZkducGIz
+dA9+aQCEdjjToQ7t6Sn2Whjj26BaqQPA8lIyjpE+ZwGXEbKvCYQLvYVJY6RCc4BcZ2RskHXZXBGh
+QnIjCQrvdZojqem6ykbRxTk4IL4/7mS+Lg0G73vehh488cONC5x0iMg/GS+OlFBfmiEtqtQLM+Li
+AG3w09PJWcIy/jSpDycsYIYyD410zcUrSc3kLTbycQgx45WLV0Xj+pznKa90RJ5wLZgN1EUNkc95
+xbHArx6u1jR5+BF5N1qE5/QOihrbMAv3SjsdWrWhNu7Nrs3gEQ2enrgmtusc9tumj5OmncdoWnS0
+obBto+GyUfgstd85Ymar7VonMd0WG75iZz6b29IjB5/Ne8QWc7loVtuu5dZDPQ9Mi8P2UMTfnkKt
+LeGySK6djVNTWGFLfZh3rfxVMrKYYfmkUL76wafDY4uoxkq8KP288KHNBHH4M/kH+yA/hhrF


More information about the Neon-commits mailing list