mirror of
https://kolaente.dev/vikunja/vikunja.git
synced 2025-12-06 01:25:58 -06:00
feat: use GitHub actions for build and release
This commit is contained in:
23
.github/workflows/ci.yml
vendored
Normal file
23
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: ci
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test
|
||||
uses: ./.github/workflows/test.yml
|
||||
secrets: inherit
|
||||
|
||||
release:
|
||||
name: Release
|
||||
if: ${{ github.ref_type == 'tag' || github.ref_name == 'main' }}
|
||||
uses: ./.github/workflows/release.yml
|
||||
needs:
|
||||
- test
|
||||
secrets: inherit
|
||||
30
.github/workflows/crowdin.yml
vendored
Normal file
30
.github/workflows/crowdin.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: Crowdin Sync
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
jobs:
|
||||
synchronize-with-crowdin:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: crowdin action
|
||||
uses: crowdin/github-action@v2
|
||||
with:
|
||||
crowdin_branch_name: main
|
||||
dryrun_action: true
|
||||
upload_sources: true
|
||||
download_translations: true
|
||||
export_only_approved: true
|
||||
push_translations: true
|
||||
localization_branch_name: main
|
||||
create_pull_request: false
|
||||
commit_message: 'chore(i18n): update translations via Crowdin'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.CROWDIN_GH_TOKEN }}
|
||||
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
|
||||
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
||||
23
.github/workflows/lockdown.yml
vendored
23
.github/workflows/lockdown.yml
vendored
@@ -1,23 +0,0 @@
|
||||
name: 'Repo Lockdown'
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: opened
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
action:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/repo-lockdown@v4
|
||||
with:
|
||||
pr-comment: 'Hi! Thank you for your contribution.
|
||||
|
||||
This repo is only a mirror and unfortunately we can''t accept PRs made here. Please re-submit your changes to [our Gitea instance](https://kolaente.dev/vikunja/vikunja/pulls).
|
||||
|
||||
Also check out the [contribution guidelines](https://vikunja.io/docs/development/#pull-requests).
|
||||
|
||||
Thank you for your understanding.'
|
||||
292
.github/workflows/release.yml
vendored
292
.github/workflows/release.yml
vendored
@@ -1,11 +1,37 @@
|
||||
name: release
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
mage:
|
||||
runs-on: ubuntu-latest
|
||||
name: prepare-mage
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: stable
|
||||
- name: Cache Mage
|
||||
id: cache-mage
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: ${{ runner.os }}-build-mage-${{ hashFiles('magefile.go') }}
|
||||
path: |
|
||||
./mage-static
|
||||
- name: Compile Mage
|
||||
if: ${{ steps.cache-mage.outputs.cache-hit != 'true' }}
|
||||
uses: magefile/mage-action@v3
|
||||
with:
|
||||
version: latest
|
||||
args: -compile ./mage-static
|
||||
- name: Store Mage Binary
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: mage_bin
|
||||
path: ./mage-static
|
||||
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -15,22 +41,220 @@ jobs:
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Build and push
|
||||
- name: Docker meta version
|
||||
if: ${{ github.ref_type == 'tag' }}
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
vikunja/vikunja
|
||||
tags: |
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=raw,value=latest
|
||||
- name: Build and push unstable
|
||||
if: ${{ github.ref_type != 'tag' }}
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8
|
||||
push: true
|
||||
tags: ghcr.io/go-vikunja/vikunja:unstable
|
||||
tags: vikunja/vikunja:unstable
|
||||
build-args: |
|
||||
RELEASE_VERSION=${{ steps.ghd.outputs.describe }}
|
||||
- name: Build and push version
|
||||
if: ${{ github.ref_type == 'tag' }}
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
RELEASE_VERSION=${{ steps.ghd.outputs.describe }}
|
||||
|
||||
frontend:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
name: Install pnpm
|
||||
with:
|
||||
run_install: false
|
||||
package_json_file: frontend/package.json
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: frontend/pnpm-lock.yaml
|
||||
- name: Install dependencies
|
||||
working-directory: frontend
|
||||
run: |
|
||||
pnpm install
|
||||
pnpm build
|
||||
- name: Store frontend dist
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: frontend_dist
|
||||
path: ./frontend/dist/**/*
|
||||
|
||||
binaries:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- mage
|
||||
- frontend
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Git describe
|
||||
id: ghd
|
||||
uses: proudust/gh-describe@v2
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: stable
|
||||
- name: Download Mage Binary
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: mage_bin
|
||||
- name: get frontend
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: frontend_dist
|
||||
path: frontend/dist
|
||||
- run: chmod +x ./mage-static
|
||||
- name: install upx
|
||||
run: |
|
||||
wget https://github.com/upx/upx/releases/download/v5.0.0/upx-5.0.0-amd64_linux.tar.xz
|
||||
echo 'b32abf118d721358a50f1aa60eacdbf3298df379c431c3a86f139173ab8289a1 upx-5.0.0-amd64_linux.tar.xz' > upx-5.0.0-amd64_linux.tar.xz.sha256
|
||||
sha256sum -c upx-5.0.0-amd64_linux.tar.xz.sha256
|
||||
tar xf upx-5.0.0-amd64_linux.tar.xz
|
||||
mv upx-5.0.0-amd64_linux/upx /usr/local/bin
|
||||
- name: GPG setup
|
||||
uses: kolaente/action-gpg@main
|
||||
with:
|
||||
gpg-passphrase: "${{ secrets.RELEASE_GPG_PASSPHRASE }}"
|
||||
gpg-sign-key: "${{ secrets.RELEASE_GPG_SIGN_KEY }}"
|
||||
- name: build and release
|
||||
env:
|
||||
RELEASE_VERSION: ${{ steps.ghd.outputs.describe }}
|
||||
XGO_OUT_NAME: vikunja-${{ github.ref_type == 'tag' && steps.ghd.outputs.describe || 'unstable' }}
|
||||
run: |
|
||||
export PATH=$PATH:$GOPATH/bin
|
||||
./mage-static release
|
||||
- name: sign
|
||||
run: |
|
||||
ls -hal dist/zip/*
|
||||
for file in dist/zip/*; do
|
||||
gpg -v --default-key 7D061A4AA61436B40713D42EFF054DACD908493A -b --batch --yes --passphrase "${{ secrets.RELEASE_GPG_PASSPHRASE }}" --pinentry-mode loopback --sign "$file"
|
||||
done
|
||||
- name: Upload
|
||||
uses: kolaente/s3-action@v1.0.1
|
||||
with:
|
||||
s3-access-key-id: ${{ secrets.HETZNER_S3_ACCESS_KEY }}
|
||||
s3-secret-access-key: ${{ secrets.HETZNER_S3_SECRET_KEY }}
|
||||
s3-endpoint: 'https://fsn1.your-objectstorage.com'
|
||||
s3-bucket: 'vikunja'
|
||||
s3-region: 'fsn1'
|
||||
target-path: /vikunja/${{ github.ref_type == 'tag' && steps.ghd.outputs.describe || 'unstable' }}
|
||||
files: 'dist/zip/*'
|
||||
strip-path-prefix: dist/zip/
|
||||
- name: Store Binaries
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: vikunja_bins
|
||||
path: ./dist/binaries/*
|
||||
|
||||
os-package:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- binaries
|
||||
strategy:
|
||||
matrix:
|
||||
package:
|
||||
- rpm
|
||||
- deb
|
||||
- apk
|
||||
- archlinux
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Download Vikunja Binary
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: vikunja_bins
|
||||
pattern: vikunja-*-linux-amd64
|
||||
- name: Git describe
|
||||
id: ghd
|
||||
uses: proudust/gh-describe@v2
|
||||
- name: Download Mage Binary
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: mage_bin
|
||||
- name: Prepare
|
||||
env:
|
||||
RELEASE_VERSION: ${{ steps.ghd.outputs.describe }}
|
||||
run: |
|
||||
chmod +x ./mage-static
|
||||
./mage-static release:prepare-nfpm-config
|
||||
mkdir -p ./dist/os-packages
|
||||
mv ./vikunja-*-linux-amd64 ./vikunja
|
||||
chmod +x ./vikunja
|
||||
- name: Create package
|
||||
id: nfpm
|
||||
uses: kolaente/action-gh-nfpm@master
|
||||
with:
|
||||
packager: ${{ matrix.package }}
|
||||
target: ./dist/os-packages/vikunja-${{ github.ref_type == 'tag' && steps.ghd.outputs.describe || 'unstable' }}-x86_64.${{ matrix.package }}
|
||||
config: ./nfpm.yaml
|
||||
- name: Upload
|
||||
uses: kolaente/s3-action@v1.0.1
|
||||
with:
|
||||
s3-access-key-id: ${{ secrets.HETZNER_S3_ACCESS_KEY }}
|
||||
s3-secret-access-key: ${{ secrets.HETZNER_S3_SECRET_KEY }}
|
||||
s3-endpoint: 'https://fsn1.your-objectstorage.com'
|
||||
s3-bucket: 'vikunja'
|
||||
s3-region: 'fsn1'
|
||||
target-path: /vikunja/${{ github.ref_type == 'tag' && steps.ghd.outputs.describe || 'unstable' }}
|
||||
files: 'dist/os-packages/*'
|
||||
strip-path-prefix: dist/os-packages/
|
||||
|
||||
config-yaml:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- mage
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Git describe
|
||||
id: ghd
|
||||
uses: proudust/gh-describe@v2
|
||||
- name: Download Mage Binary
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: mage_bin
|
||||
- name: generate
|
||||
run: |
|
||||
chmod +x ./mage-static
|
||||
./mage-static generate:config-yaml 1
|
||||
- name: Upload to S3
|
||||
uses: kolaente/s3-action@v1.0.1
|
||||
with:
|
||||
s3-access-key-id: ${{ secrets.HETZNER_S3_ACCESS_KEY }}
|
||||
s3-secret-access-key: ${{ secrets.HETZNER_S3_SECRET_KEY }}
|
||||
s3-endpoint: 'https://fsn1.your-objectstorage.com'
|
||||
s3-bucket: 'vikunja'
|
||||
s3-region: 'fsn1'
|
||||
target-path: /vikunja/${{ github.ref_type == 'tag' && steps.ghd.outputs.describe || 'unstable' }}
|
||||
files: 'config.yml.sample'
|
||||
|
||||
desktop:
|
||||
needs:
|
||||
- frontend
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
@@ -40,7 +264,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Git describe
|
||||
id: ghd
|
||||
uses: proudust/gh-describe@v2
|
||||
@@ -57,11 +281,15 @@ jobs:
|
||||
- name: Install Linux dependencies
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
run: sudo apt-get install --no-install-recommends -y libopenjp2-tools rpm libarchive-tools
|
||||
- name: get frontend
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: frontend_dist
|
||||
path: frontend/dist
|
||||
- name: Build desktop app
|
||||
working-directory: desktop
|
||||
run: |
|
||||
pnpm install --fetch-timeout 100000
|
||||
# TODO use the built output from a previous frontend build step
|
||||
node build.js "${{ steps.ghd.outputs.describe }}" ${{ github.ref_type == 'tag' }}
|
||||
- name: Upload to S3
|
||||
uses: kolaente/s3-action@v1.0.1
|
||||
@@ -70,8 +298,48 @@ jobs:
|
||||
s3-secret-access-key: ${{ secrets.HETZNER_S3_SECRET_KEY }}
|
||||
s3-endpoint: 'https://fsn1.your-objectstorage.com'
|
||||
s3-bucket: 'vikunja'
|
||||
s3-region: 'fsn1'
|
||||
files: 'desktop/dist/Vikunja*'
|
||||
target-path: /desktop/${{ github.ref_type == 'tag' && steps.ghd.outputs.describe || 'unstable' }}
|
||||
s3-region: 'fsn1'
|
||||
strip-path-prefix: desktop/dist/
|
||||
exclude: 'desktop/dist/*.blockmap'
|
||||
|
||||
generate-swagger-docs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
needs:
|
||||
- mage
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Download Mage Binary
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: mage_bin
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: stable
|
||||
- name: generate
|
||||
run: |
|
||||
export PATH=$PATH:$GOPATH/bin
|
||||
go install github.com/swaggo/swag/cmd/swag
|
||||
chmod +x ./mage-static
|
||||
./mage-static generate:swagger-docs
|
||||
- name: Check for changes
|
||||
id: check_changes
|
||||
run: |
|
||||
git diff --quiet
|
||||
echo "changes_exist=$?" >> "$GITHUB_OUTPUT"
|
||||
- name: Commit files
|
||||
if: steps.check_changes.outputs.changes_exist != '0'
|
||||
run: |
|
||||
git config --local user.email "frederik@vikunja.io"
|
||||
git config --local user.name "Frederick [Bot]"
|
||||
git commit -am "[skip ci] Updated swagger docs"
|
||||
- name: Push changes
|
||||
if: steps.check_changes.outputs.changes_exist != '0'
|
||||
uses: ad-m/github-push-action@master
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: ${{ github.ref }}
|
||||
|
||||
344
.github/workflows/test.yml
vendored
Normal file
344
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,344 @@
|
||||
name: Test
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
mage:
|
||||
runs-on: ubuntu-latest
|
||||
name: prepare-mage
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: stable
|
||||
- name: Cache Mage
|
||||
id: cache-mage
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: ${{ runner.os }}-build-mage-${{ hashFiles('magefile.go') }}
|
||||
path: |
|
||||
./mage-static
|
||||
- name: Compile Mage
|
||||
if: ${{ steps.cache-mage.outputs.cache-hit != 'true' }}
|
||||
uses: magefile/mage-action@v3
|
||||
with:
|
||||
version: latest
|
||||
args: -compile ./mage-static
|
||||
- name: Store Mage Binary
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: mage_bin
|
||||
path: ./mage-static
|
||||
|
||||
api-build:
|
||||
runs-on: ubuntu-latest
|
||||
needs: mage
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Download Mage Binary
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: mage_bin
|
||||
- name: Git describe
|
||||
id: ghd
|
||||
uses: proudust/gh-describe@v2
|
||||
- name: Build
|
||||
env:
|
||||
RELEASE_VERSION: ${{ steps.ghd.outputs.describe }}
|
||||
run: |
|
||||
mkdir -p frontend/dist
|
||||
touch frontend/dist/index.html
|
||||
chmod +x ./mage-static
|
||||
./mage-static build
|
||||
- name: Store Vikunja Binary
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: vikunja_bin
|
||||
path: ./vikunja
|
||||
|
||||
api-lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: stable
|
||||
- name: prepare frontend files
|
||||
run: |
|
||||
mkdir -p frontend/dist
|
||||
touch frontend/dist/index.html
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v6
|
||||
with:
|
||||
version: v1.64.5
|
||||
|
||||
api-check-translations:
|
||||
runs-on: ubuntu-latest
|
||||
needs: mage
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Download Mage Binary
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: mage_bin
|
||||
- name: Check
|
||||
run: |
|
||||
chmod +x ./mage-static
|
||||
./mage-static check:translations
|
||||
|
||||
test-migration-smoke:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- api-build
|
||||
strategy:
|
||||
matrix:
|
||||
db:
|
||||
- sqlite
|
||||
- postgres
|
||||
- mysql
|
||||
services:
|
||||
migration-smoke-db-mysql:
|
||||
image: mariadb:11
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: vikunjatest
|
||||
MYSQL_DATABASE: vikunjatest
|
||||
ports:
|
||||
- 3307:3306
|
||||
migration-smoke-db-postgres:
|
||||
image: postgres:16
|
||||
env:
|
||||
POSTGRES_PASSWORD: vikunjatest
|
||||
POSTGRES_DB: vikunjatest
|
||||
ports:
|
||||
- 5433:5432
|
||||
steps:
|
||||
- name: Download Unstable
|
||||
run: |
|
||||
wget https://dl.vikunja.io/api/unstable/vikunja-unstable-linux-amd64-full.zip -q -O vikunja-latest.zip
|
||||
unzip vikunja-latest.zip vikunja-unstable-linux-amd64
|
||||
- name: Download Vikunja Binary
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: vikunja_bin
|
||||
- name: run migration
|
||||
env:
|
||||
VIKUNJA_DATABASE_TYPE: ${{ matrix.db }}
|
||||
VIKUNJA_DATABASE_PATH: ./vikunja-migration-test.db
|
||||
VIKUNJA_DATABASE_USER: ${{ matrix.db == 'postgres' && 'postgres' || 'root' }}
|
||||
VIKUNJA_DATABASE_PASSWORD: vikunjatest
|
||||
VIKUNJA_DATABASE_DATABASE: vikunjatest
|
||||
VIKUNJA_DATABASE_SSLMODE: disable
|
||||
VIKUNJA_DATABASE_PORT: ${{ matrix.db == 'postgres' && 5433 || 3307 }}
|
||||
VIKUNJA_LOG_DATABASE: stdout
|
||||
VIKUNJA_LOG_DATABASELEVEL: debug
|
||||
run: |
|
||||
./vikunja-unstable-linux-amd64 migrate
|
||||
# Run the migrations from the binary built in the step before
|
||||
chmod +x vikunja
|
||||
./vikunja migrate
|
||||
|
||||
test-api:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- mage
|
||||
strategy:
|
||||
matrix:
|
||||
db:
|
||||
- sqlite-in-memory
|
||||
- sqlite
|
||||
- postgres
|
||||
- mysql
|
||||
test:
|
||||
- unit
|
||||
- integration
|
||||
services:
|
||||
db-mysql:
|
||||
image: mariadb:11
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: vikunjatest
|
||||
MYSQL_DATABASE: vikunjatest
|
||||
ports:
|
||||
- 3306:3306
|
||||
db-postgres:
|
||||
image: postgres:16
|
||||
env:
|
||||
POSTGRES_PASSWORD: vikunjatest
|
||||
POSTGRES_DB: vikunjatest
|
||||
ports:
|
||||
- 5432:5432
|
||||
test-ldap:
|
||||
image: gitea/test-openldap
|
||||
ports:
|
||||
- 389:389
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Download Mage Binary
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: mage_bin
|
||||
- name: test
|
||||
env:
|
||||
VIKUNJA_TESTS_USE_CONFIG: ${{ matrix.db != 'sqlite-in-memory' && 1 || 0 }}
|
||||
VIKUNJA_DATABASE_TYPE: ${{ matrix.db }}
|
||||
VIKUNJA_DATABASE_USER: ${{ matrix.db == 'postgres' && 'postgres' || 'root' }}
|
||||
VIKUNJA_DATABASE_PASSWORD: vikunjatest
|
||||
VIKUNJA_DATABASE_DATABASE: vikunjatest
|
||||
VIKUNJA_DATABASE_SSLMODE: disable
|
||||
VIKUNJA_AUTH_LDAP_ENABLED: 1
|
||||
VIKUNJA_AUTH_LDAP_HOST: localhost
|
||||
VIKUNJA_AUTH_LDAP_USETLS: 0
|
||||
VIKUNJA_AUTH_LDAP_BASEDN: dc=planetexpress,dc=com
|
||||
VIKUNJA_AUTH_LDAP_BINDDN: uid=gitea,ou=service,dc=planetexpress,dc=com
|
||||
VIKUNJA_AUTH_LDAP_BINDPASSWORD: password
|
||||
VIKUNJA_AUTH_LDAP_USERFILTER: '(&(objectclass=inetorgperson)(uid=%s))'
|
||||
run: |
|
||||
mkdir -p frontend/dist
|
||||
touch frontend/dist/index.html
|
||||
chmod +x mage-static
|
||||
./mage-static test:${{ matrix.test }}
|
||||
|
||||
frontend-dependencies:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
name: Install pnpm
|
||||
with:
|
||||
run_install: false
|
||||
package_json_file: frontend/package.json
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: frontend/pnpm-lock.yaml
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
cd frontend
|
||||
pnpm install
|
||||
|
||||
frontend-lint:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- frontend-dependencies
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
name: Install pnpm
|
||||
with:
|
||||
run_install: false
|
||||
package_json_file: frontend/package.json
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: frontend/pnpm-lock.yaml
|
||||
- name: Lint
|
||||
run: |
|
||||
cd frontend
|
||||
pnpm install
|
||||
pnpm lint
|
||||
|
||||
frontend-typecheck:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- frontend-dependencies
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
name: Install pnpm
|
||||
with:
|
||||
run_install: false
|
||||
package_json_file: frontend/package.json
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: frontend/pnpm-lock.yaml
|
||||
- name: Typecheck
|
||||
continue-on-error: true
|
||||
run: |
|
||||
cd frontend
|
||||
pnpm install
|
||||
pnpm typecheck
|
||||
|
||||
test-frontend-unit:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- frontend-dependencies
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
name: Install pnpm
|
||||
with:
|
||||
run_install: false
|
||||
package_json_file: frontend/package.json
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: frontend/pnpm-lock.yaml
|
||||
- name: Run unit tests
|
||||
run: |
|
||||
cd frontend
|
||||
pnpm install
|
||||
pnpm test:unit
|
||||
|
||||
test-frontend-e2e:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- frontend-dependencies
|
||||
- api-build
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
name: Install pnpm
|
||||
with:
|
||||
run_install: false
|
||||
package_json_file: frontend/package.json
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: frontend/pnpm-lock.yaml
|
||||
- name: Download Vikunja Binary
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: vikunja_bin
|
||||
- name: Build frontend for test
|
||||
run: |
|
||||
cd frontend
|
||||
pnpm install
|
||||
pnpm cypress install
|
||||
pnpm build:test
|
||||
- name: Run api
|
||||
env:
|
||||
VIKUNJA_SERVICE_TESTINGTOKEN: averyLongSecretToSe33dtheDB
|
||||
VIKUNJA_LOG_LEVEL: DEBUG
|
||||
VIKUNJA_CORS_ENABLE: 1
|
||||
VIKUNJA_DATABASE_PATH: memory
|
||||
VIKUNJA_DATABASE_TYPE: sqlite
|
||||
run: |
|
||||
chmod +x ./vikunja
|
||||
./vikunja &
|
||||
- uses: cypress-io/github-action@v6
|
||||
with:
|
||||
working-directory: frontend
|
||||
browser: chrome
|
||||
record: true
|
||||
start: |
|
||||
pnpm preview:test
|
||||
wait-on: http://127.0.0.1:4173,http://127.0.0.1:3456/api/v1/info
|
||||
wait-on-timeout: 10
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||
CYPRESS_API_URL: http://127.0.0.1:3456/api/v1
|
||||
CYPRESS_TEST_SECRET: averyLongSecretToSe33dtheDB
|
||||
CYPRESS_DEFAULT_COMMAND_TIMEOUT: 60000
|
||||
21
crowdin.yml
Normal file
21
crowdin.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
"project_id": "462614"
|
||||
"api_token_env": "CROWDIN_PERSONAL_TOKEN"
|
||||
"base_path": "."
|
||||
"base_url": "https://api.crowdin.com"
|
||||
|
||||
"preserve_hierarchy": true
|
||||
|
||||
files: [
|
||||
{
|
||||
"source": "pkg/i18n/lang/en.json",
|
||||
"translation": "pkg/i18n/lang/%locale%.json",
|
||||
"dest": "en-api.json",
|
||||
"type": "json",
|
||||
},
|
||||
{
|
||||
"source": "frontend/src/i18n/lang/en.json",
|
||||
"translation": "frontend/src/i18n/lang/%locale%.json",
|
||||
"dest": "en.json",
|
||||
"type": "json",
|
||||
},
|
||||
]
|
||||
@@ -16,33 +16,30 @@
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const https = require('https')
|
||||
const {execSync} = require('child_process')
|
||||
const unzipper = require('unzipper')
|
||||
|
||||
// Helper function to download a file
|
||||
async function downloadFile(url, dest) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const file = fs.createWriteStream(dest)
|
||||
https.get(url, (response) => {
|
||||
if (response.statusCode !== 200) {
|
||||
return reject(new Error(`Failed to download file: ${response.statusCode}`))
|
||||
}
|
||||
response.pipe(file)
|
||||
file.on('finish', () => {
|
||||
file.close(resolve)
|
||||
})
|
||||
}).on('error', (err) => {
|
||||
fs.unlink(dest, () => reject(err))
|
||||
})
|
||||
})
|
||||
}
|
||||
// Helper function to copy directory recursively
|
||||
async function copyDir(src, dest) {
|
||||
// Create destination directory if it doesn't exist
|
||||
if (!fs.existsSync(dest)) {
|
||||
await fs.promises.mkdir(dest, { recursive: true })
|
||||
}
|
||||
|
||||
// Helper function to unzip a file to a directory
|
||||
async function unzipFile(zipPath, destDir) {
|
||||
return fs.createReadStream(zipPath)
|
||||
.pipe(unzipper.Extract({path: destDir}))
|
||||
.promise()
|
||||
// Get all files in source directory
|
||||
const entries = await fs.promises.readdir(src, { withFileTypes: true })
|
||||
|
||||
for (const entry of entries) {
|
||||
const srcPath = path.join(src, entry.name)
|
||||
const destPath = path.join(dest, entry.name)
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
// Recursively copy subdirectories
|
||||
await copyDir(srcPath, destPath)
|
||||
} else {
|
||||
// Copy files
|
||||
await fs.promises.copyFile(srcPath, destPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to replace text in a file
|
||||
@@ -78,8 +75,7 @@ async function main() {
|
||||
|
||||
const versionPlaceholder = args[0]
|
||||
const renameDistFiles = args[1] || false
|
||||
const frontendZipUrl = 'https://dl.vikunja.io/frontend/vikunja-frontend-unstable.zip'
|
||||
const zipFilePath = path.resolve(__dirname, 'vikunja-frontend-unstable.zip')
|
||||
const frontendSourceDir = path.resolve(__dirname, '../frontend/dist')
|
||||
const frontendDir = path.resolve(__dirname, 'frontend')
|
||||
const indexFilePath = path.join(frontendDir, 'index.html')
|
||||
const packageJsonPath = path.join(__dirname, 'package.json')
|
||||
@@ -87,16 +83,19 @@ async function main() {
|
||||
console.log(`Building version ${versionPlaceholder}`)
|
||||
|
||||
try {
|
||||
console.log('Step 1: Downloading frontend zip...')
|
||||
await downloadFile(frontendZipUrl, zipFilePath)
|
||||
console.log('Step 1: Copying frontend files...')
|
||||
if (fs.existsSync(frontendDir)) {
|
||||
console.log('Removing existing frontend directory...')
|
||||
await fs.promises.rm(frontendDir, { recursive: true, force: true })
|
||||
}
|
||||
await fs.promises.mkdir(frontendDir, { recursive: true })
|
||||
|
||||
await copyDir(frontendSourceDir, frontendDir)
|
||||
|
||||
console.log('Step 2: Unzipping frontend package...')
|
||||
await unzipFile(zipFilePath, frontendDir)
|
||||
|
||||
console.log('Step 3: Modifying index.html...')
|
||||
console.log('Step 2: Modifying index.html...')
|
||||
await replaceTextInFile(indexFilePath, /\/api\/v1/g, '')
|
||||
|
||||
console.log('Step 4: Updating version in package.json...')
|
||||
console.log('Step 3: Updating version in package.json...')
|
||||
await replaceTextInFile(packageJsonPath, /\${version}/g, versionPlaceholder)
|
||||
await replaceTextInFile(
|
||||
packageJsonPath,
|
||||
@@ -104,11 +103,11 @@ async function main() {
|
||||
`"version": "${versionPlaceholder}"`,
|
||||
)
|
||||
|
||||
console.log('Step 5: Installing dependencies and building...')
|
||||
console.log('Step 4: Installing dependencies and building...')
|
||||
execSync('pnpm dist', {stdio: 'inherit'})
|
||||
|
||||
if (renameDistFiles) {
|
||||
console.log('Step 6: Renaming release files...')
|
||||
console.log('Step 5: Renaming release files...')
|
||||
await renameDistFilesToUnstable(versionPlaceholder)
|
||||
}
|
||||
|
||||
@@ -116,11 +115,6 @@ async function main() {
|
||||
} catch (err) {
|
||||
console.error('An error occurred:', err.message)
|
||||
process.exit(1)
|
||||
} finally {
|
||||
// Cleanup the zip file
|
||||
if (fs.existsSync(zipFilePath)) {
|
||||
fs.unlinkSync(zipFilePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ in {
|
||||
# General tools
|
||||
git-cliff
|
||||
actionlint
|
||||
crowdin-cli
|
||||
# API tools
|
||||
golangci-lint mage
|
||||
# Desktop
|
||||
|
||||
85
magefile.go
85
magefile.go
@@ -64,18 +64,19 @@ var (
|
||||
|
||||
// Aliases are mage aliases of targets
|
||||
Aliases = map[string]interface{}{
|
||||
"build": Build.Build,
|
||||
"check:got-swag": Check.GotSwag,
|
||||
"release": Release.Release,
|
||||
"release:os-package": Release.OsPackage,
|
||||
"dev:make-migration": Dev.MakeMigration,
|
||||
"dev:make-event": Dev.MakeEvent,
|
||||
"dev:make-listener": Dev.MakeListener,
|
||||
"dev:make-notification": Dev.MakeNotification,
|
||||
"lint": Check.Golangci,
|
||||
"lint:fix": Check.GolangciFix,
|
||||
"generate:config-yaml": Generate.ConfigYAML,
|
||||
"generate:swagger-docs": Generate.SwaggerDocs,
|
||||
"build": Build.Build,
|
||||
"check:got-swag": Check.GotSwag,
|
||||
"release": Release.Release,
|
||||
"release:os-package": Release.OsPackage,
|
||||
"release:prepare-nfpm-config": Release.PrepareNFPMConfig,
|
||||
"dev:make-migration": Dev.MakeMigration,
|
||||
"dev:make-event": Dev.MakeEvent,
|
||||
"dev:make-listener": Dev.MakeListener,
|
||||
"dev:make-notification": Dev.MakeNotification,
|
||||
"lint": Check.Golangci,
|
||||
"lint:fix": Check.GolangciFix,
|
||||
"generate:config-yaml": Generate.ConfigYAML,
|
||||
"generate:swagger-docs": Generate.SwaggerDocs,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -717,13 +718,17 @@ func runXgo(targets string) error {
|
||||
if strings.HasPrefix(targets, "darwin") {
|
||||
extraLdflags = ""
|
||||
}
|
||||
outName := os.Getenv("XGO_OUT_NAME")
|
||||
if outName == "" {
|
||||
outName = Executable + "-" + Version
|
||||
}
|
||||
|
||||
runAndStreamOutput("xgo",
|
||||
"-dest", RootPath+"/"+DIST+"/binaries",
|
||||
"-tags", "netgo "+Tags,
|
||||
"-ldflags", extraLdflags+Ldflags,
|
||||
"-targets", targets,
|
||||
"-out", Executable+"-"+Version,
|
||||
"-out", outName,
|
||||
RootPath)
|
||||
if os.Getenv("DRONE_WORKSPACE") != "" {
|
||||
return filepath.Walk("/build/", func(path string, info os.FileInfo, err error) error {
|
||||
@@ -790,10 +795,11 @@ func (Release) Compress(ctx context.Context) error {
|
||||
if !strings.Contains(info.Name(), Executable) {
|
||||
return nil
|
||||
}
|
||||
// No mips or s390x for you today
|
||||
if strings.Contains(info.Name(), "mips") ||
|
||||
strings.Contains(info.Name(), "s390x") ||
|
||||
strings.Contains(info.Name(), "riscv64") { // not supported by upx
|
||||
strings.Contains(info.Name(), "riscv64") ||
|
||||
strings.Contains(info.Name(), "darwin") {
|
||||
// not supported by upx
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -917,21 +923,10 @@ func (Release) Reprepro() {
|
||||
runAndStreamOutput("reprepro_expect", "debian", "includedeb", "buster", RootPath+"/"+DIST+"/os-packages/"+Executable+"_"+strings.ReplaceAll(VersionNumber, "v0", "0")+"_amd64.deb")
|
||||
}
|
||||
|
||||
// Creates deb, rpm and apk packages
|
||||
func (Release) Packages() error {
|
||||
// Prepares the nfpm config
|
||||
func (Release) PrepareNFPMConfig() error {
|
||||
mg.Deps(initVars)
|
||||
var err error
|
||||
binpath := "nfpm"
|
||||
err = exec.Command(binpath).Run()
|
||||
if err != nil && strings.Contains(err.Error(), "executable file not found") {
|
||||
binpath = "/usr/bin/nfpm"
|
||||
err = exec.Command(binpath).Run()
|
||||
}
|
||||
if err != nil && strings.Contains(err.Error(), "executable file not found") {
|
||||
fmt.Println("Please manually install nfpm by running")
|
||||
fmt.Println("curl -sfL https://install.goreleaser.com/github.com/goreleaser/nfpm.sh | sh -s -- -b $(go env GOPATH)/bin")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Because nfpm does not support templating, we replace the values in the config file and restore it after running
|
||||
nfpmConfigPath := RootPath + "/nfpm.yaml"
|
||||
@@ -946,18 +941,46 @@ func (Release) Packages() error {
|
||||
return err
|
||||
}
|
||||
|
||||
generateConfigYAMLFromJSON(DefaultConfigYAMLSamplePath, true)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Creates deb, rpm and apk packages
|
||||
func (Release) Packages() error {
|
||||
mg.Deps(initVars)
|
||||
|
||||
var err error
|
||||
binpath := os.Getenv("NFPM_BIN_PATH")
|
||||
if binpath == "" {
|
||||
binpath = "nfpm"
|
||||
}
|
||||
err = exec.Command(binpath).Run()
|
||||
if err != nil && strings.Contains(err.Error(), "executable file not found") {
|
||||
binpath = "/usr/bin/nfpm"
|
||||
err = exec.Command(binpath).Run()
|
||||
}
|
||||
if err != nil && strings.Contains(err.Error(), "executable file not found") {
|
||||
fmt.Println("Please manually install nfpm by running")
|
||||
fmt.Println("curl -sfL https://install.goreleaser.com/github.com/goreleaser/nfpm.sh | sh -s -- -b $(go env GOPATH)/bin")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = (Release{}).PrepareNFPMConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
releasePath := RootPath + "/" + DIST + "/os-packages/"
|
||||
if err := os.MkdirAll(releasePath, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
generateConfigYAMLFromJSON(DefaultConfigYAMLSamplePath, true)
|
||||
|
||||
runAndStreamOutput(binpath, "pkg", "--packager", "deb", "--target", releasePath)
|
||||
runAndStreamOutput(binpath, "pkg", "--packager", "rpm", "--target", releasePath)
|
||||
runAndStreamOutput(binpath, "pkg", "--packager", "apk", "--target", releasePath)
|
||||
|
||||
return os.WriteFile(nfpmConfigPath, nfpmconfig, 0)
|
||||
return nil
|
||||
}
|
||||
|
||||
type Dev mg.Namespace
|
||||
|
||||
Reference in New Issue
Block a user