Automatización de versiones¶
Resumen¶
Esta página explica cómo automatizar con GitHub Actions la compilación, la firma y la subida de una nueva versión de una app a la tienda de apps, incluidos los secretos que necesita el workflow y los cambios en el Makefile para la firma de código. Está dirigida a quienes publican apps.
Fuente: documentación de Nextcloud, «developer_manual/app_publishing_maintenance/release_automation», versión 3ad9158, licencia CC BY 3.0; traducida y adaptada para APS Conecta Gestión.
La automatización es algo estupendo: evita errores y facilita la vida, lo que deja más tiempo para trabajar en todas esas funciones que se querían implementar.
GitHub Actions¶
Si el repositorio de la aplicación está en GitHub, como ocurre con muchas aplicaciones de APS Conecta Gestión, GitHub Actions es una excelente forma de automatizar la publicación de la app desde el repositorio git en la tienda de apps de Nextcloud.
Una forma sencilla de empezar es usar https://github.com/R0Wi/nextcloud-appstore-push-action en el repositorio junto con algunas otras acciones. Así se puede compilar automáticamente la app y publicarla en la tienda de apps. Admite versiones preliminares y firma de código.
Para empezar, crear un nuevo archivo yaml en el directorio .github/workflows.
name: Build and publish app release
on:
release:
types: [published]
env:
APP_NAME: news
jobs:
build_and_publish:
environment: release
runs-on: ubuntu-latest
name: "Release: build, sign and upload the app"
strategy:
matrix:
php-versions: ['7.4']
nextcloud: ['stable21']
database: ['sqlite']
steps:
- name: Checkout
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
- name: Setup PHP
uses: shivammathur/setup-php@afefcaf556d98dc7896cca380e181decb609ca44
with:
php-version: ${{ matrix.php-versions }}
extensions: pdo_sqlite,pdo_mysql,pdo_pgsql,gd,zip
coverage: none
- name: Set up server non MySQL
uses: SMillerDev/nextcloud-actions/setup-nextcloud@fae87e29aa7cdf1ea0b8033c67f60e75b10be2cd
with:
cron: false
version: ${{ matrix.nextcloud }}
database-type: ${{ matrix.database }}
- name: Prime app build
run: make
- name: Configure server with app
uses: SMillerDev/nextcloud-actions/setup-nextcloud-app@fae87e29aa7cdf1ea0b8033c67f60e75b10be2cd
with:
app: ${{ env.APP_NAME }}
check-code: false
- name: Create signed release archive
run: |
cd ../server/apps/${{ env.APP_NAME }} && make appstore
env:
app_private_key: ${{ secrets.APP_PRIVATE_KEY }}
app_public_crt: ${{ secrets.APP_PUBLIC_CRT }}
- name: Upload app tarball to release
uses: svenstaro/upload-release-action@483c1e56f95e88835747b1c7c60581215016cbf2
id: attach_to_release
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ../server/apps/${{ env.APP_NAME }}/build/artifacts/appstore/${{ env.APP_NAME }}.tar.gz
asset_name: ${{ env.APP_NAME }}.tar.gz
tag: ${{ github.ref }}
overwrite: true
- name: Upload app to Nextcloud appstore
uses: R0Wi/nextcloud-appstore-push-action@a011fe619bcf6e77ddebc96f9908e1af4071b9c1
with:
app_name: ${{ env.APP_NAME }}
appstore_token: ${{ secrets.APPSTORE_TOKEN }}
download_url: ${{ steps.attach_to_release.outputs.browser_download_url }}
app_private_key: ${{ secrets.APP_PRIVATE_KEY }}
nightly: ${{ github.event.release.prerelease }}
- name: Delete crt and key from local storage
run: rm -f ~/.nextcloud/certificates/*
Asegurarse de revisar si las acciones usadas tienen actualizaciones útiles, ya que están fijadas a un sha1 concreto para evitar cambios dañinos que pasen inadvertidos.
Para que este workflow funcione hay que proporcionar algunas variables.
APP_NAMEestablece el nombre de la app, directamente en el yaml
Luego hay algunos secretos; hay que manejarlos con cuidado. Si el repositorio está dentro de la organización nextcloud, hay que usar un entorno (environment).
jobs:
build_and_publish:
environment: release
runs-on: ubuntu-latest
En este ejemplo se usa el entorno «release»: abrir los ajustes del repositorio y la pestaña «Environments», añadir un nuevo entorno con el nombre «release», asegurarse de activar «Required reviewers» y añadir solo a las personas de confianza, que podrán aprobar una versión. Guardar las reglas y, al final, añadir los siguientes secretos del entorno.
APP_PRIVATE_KEYla clave privada de la appAPP_PUBLIC_CRTel certificado de la app; este podría ser público, pero para facilitar su uso se añade como secretoAPPSTORE_TOKENse obtiene en la tienda de apps como desarrollador registrado https://apps.nextcloud.com/account/token
Si la app no está en la organización de Nextcloud, también se pueden añadir los secretos anteriores en la sección «Secrets», pero con cuidado: cualquiera con acceso de escritura al repositorio podrá crear versiones. Asegurarse también de eliminar la declaración del entorno.
Si no se usa firma de código para la app, se puede eliminar la siguiente sección del yaml.
env:
app_private_key: ${{ secrets.APP_PRIVATE_KEY }}
app_public_cert: ${{ secrets.APP_PUBLIC_CERT }}
Asegurarse también de eliminar environment: release.
Cambios en el Makefile para la firma de código¶
Como el certificado y la clave privada ahora se guardan en variables de entorno, hay que convertirlos de algún modo en un archivo. Un ejemplo que puede usarse lo proporciona la app News.
#!/usr/bin/env php
<?php
/**
* Nextcloud - News
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Benjamin Brahmer <info@b-brahmer.de>
* @copyright Benjamin Brahmer 2020
*/
if ($argc < 2) {
echo "This script expects two parameters:\n";
echo "./file_from_env.php ENV_VAR PATH_TO_FILE\n";
exit(1);
}
# Read environment variable
$content = getenv($argv[1]);
if (!$content){
echo "Variable was empty\n";
exit(1);
}
file_put_contents($argv[2], $content);
echo "Done...\n";
Es un script php muy sencillo que recibe una variable de entorno y una ruta de archivo, y vuelca en el archivo lo que encuentre en la variable. Después de guardar el script en algún lugar del repositorio, se puede usar en el Makefile.
cert_dir=$(HOME)/.nextcloud/certificates
[...]
appstore:
[...]
# export the key and cert to a file
mkdir -p $(cert_dir)
php ./bin/tools/file_from_env.php "app_private_key" "$(cert_dir)/$(app_name).key"
php ./bin/tools/file_from_env.php "app_public_crt" "$(cert_dir)/$(app_name).crt"
[...]
Asegurarse también de que estos archivos se usen al firmar la app, en el Makefile.
@if [ -f $(cert_dir)/$(app_name).key ]; then \
echo "Signing app files…"; \
php ../../occ integrity:sign-app \
--privateKey=$(cert_dir)/$(app_name).key\
--certificate=$(cert_dir)/$(app_name).crt\
--path=$(appstore_sign_dir)/$(app_name); \
echo "Signing app files ... done"; \
fi
Y eso es básicamente todo lo que hay que hacer: se pueden usar la clave y el certificado al firmar la app.
El proceso¶
Crear una nueva versión (release) en GitHub, con la información que se suela incluir.
Decidir si debe ser una versión normal o una versión preliminar; las versiones preliminares se subirán a la tienda de apps como versión nightly.
Al terminar, publicar la versión y esperar unos minutos; aparecerá una solicitud para aprobar la versión, en Actions o en las notificaciones.
Si todo funcionó, se encontrará un
appname.tar.gzcomo adjunto de la versión.Comprobar la versión recién publicada en la tienda de apps; enhorabuena por la primera app publicada automáticamente.