OneBot: Leantime 改造版源码(BOM/Univer 表格/AI 接管/品牌替换等)
This commit is contained in:
30
.github/workflows/acceptancetests.yml
vendored
Normal file
30
.github/workflows/acceptancetests.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: Acceptance Tests (Selenium)
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ "master", "*.*-dev" ]
|
||||
pull_request:
|
||||
branches: [ "master", "*.*-dev" ]
|
||||
|
||||
jobs:
|
||||
acceptance:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.3'
|
||||
extensions: redis, gd, ldap, mbstring, pdo_mysql, zip, bcmath, exif, pcntl
|
||||
|
||||
- name: Run Acceptance Tests
|
||||
run: make acceptance-test-ci
|
||||
|
||||
- name: Store screenshots
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: acceptance-test
|
||||
path: tests/_output
|
||||
36
.github/workflows/api-bearer-tests.yml
vendored
Normal file
36
.github/workflows/api-bearer-tests.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name: API Tests (Bearer auth)
|
||||
|
||||
# Sibling to acceptancetests.yml. Exists because the JSON-RPC endpoint
|
||||
# accepts three auth modes (session, x-api-key, Bearer) and ApiCest only
|
||||
# exercises x-api-key. Bearer is the mode mobile + AdvancedAuth integrators
|
||||
# hit, and a 2026-06 permission-engine deploy silently broke it for every
|
||||
# gated read with no CI signal. This workflow closes that gap.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ "master", "*.*-dev" ]
|
||||
pull_request:
|
||||
branches: [ "master", "*.*-dev" ]
|
||||
|
||||
jobs:
|
||||
bearer-api:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.3'
|
||||
extensions: redis, gd, ldap, mbstring, pdo_mysql, zip, bcmath, exif, pcntl
|
||||
|
||||
- name: Run Bearer API Tests
|
||||
run: make bearer-api-test-ci
|
||||
|
||||
- name: Store screenshots
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: bearer-api-test
|
||||
path: tests/_output
|
||||
28
.github/workflows/codeStyleAnalysis.yml
vendored
Normal file
28
.github/workflows/codeStyleAnalysis.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: Code Style Analysis
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ "master", "*.*-dev" ]
|
||||
pull_request:
|
||||
branches: [ "master", "*.*-dev" ]
|
||||
|
||||
jobs:
|
||||
pint:
|
||||
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.3'
|
||||
extensions: redis, gd, ldap, mbstring, pdo_mysql, zip, bcmath, exif, pcntl
|
||||
|
||||
- name: Install Dependencies
|
||||
run: make build-dev
|
||||
|
||||
- name: Run Laravel Pint Analysis
|
||||
run: make test-code-style
|
||||
28
.github/workflows/makefile.yml
vendored
Normal file
28
.github/workflows/makefile.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: Makefile CI
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ "master", "*.*-dev" ]
|
||||
pull_request:
|
||||
branches: [ "master", "*.*-dev" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.3'
|
||||
extensions: redis, gd, ldap, mbstring, pdo_mysql, zip, bcmath, exif, pcntl
|
||||
|
||||
- name: Install dependencies
|
||||
run: make build
|
||||
|
||||
- name: Run distcheck
|
||||
run: make clean
|
||||
174
.github/workflows/release-prepare.yml
vendored
Normal file
174
.github/workflows/release-prepare.yml
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
name: Prepare Release
|
||||
|
||||
# Dispatch with a version number to open a "Release vX.Y.Z" PR containing the
|
||||
# version bump (package.json, package-lock.json, AppSettings.php) and an
|
||||
# AI-drafted CHANGELOG.md section. The regular CI suite runs on the PR as the
|
||||
# final test gate; merging the PR triggers the Create Release workflow which
|
||||
# tags, packages, and publishes.
|
||||
#
|
||||
# Requires two repo secrets:
|
||||
# - RELEASE_TOKEN: fine-grained PAT with Contents + Pull requests read/write.
|
||||
# PRs opened with the default GITHUB_TOKEN would not trigger CI workflows.
|
||||
# - ANTHROPIC_API_KEY: Claude API key used to draft the changelog section.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'New version number (e.g. 3.8.1)'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
# Least privilege: branch push + PR creation use the RELEASE_TOKEN PAT, so the
|
||||
# default token only needs read access (checkout, changelog).
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
VERSION: ${{ inputs.version }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Validate version
|
||||
run: |
|
||||
if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "::error::Version '$VERSION' is not a valid X.Y.Z version number"
|
||||
exit 1
|
||||
fi
|
||||
CURRENT=$(make get-version)
|
||||
if [ "$VERSION" = "$CURRENT" ]; then
|
||||
echo "::error::Version $VERSION is already the current version"
|
||||
exit 1
|
||||
fi
|
||||
if git rev-parse -q --verify "refs/tags/v$VERSION" > /dev/null; then
|
||||
echo "::error::Tag v$VERSION already exists"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Bump version files
|
||||
run: |
|
||||
npm version "$VERSION" --no-git-tag-version
|
||||
sed -i "s/appVersion = '[^']*'/appVersion = '$VERSION'/" app/Core/Configuration/AppSettings.php
|
||||
echo "Bumped to $(make get-version)"
|
||||
|
||||
- name: Collect history since last release
|
||||
run: |
|
||||
LAST_TAG=$(git describe --tags --abbrev=0 --match 'v*')
|
||||
echo "Generating changelog for $LAST_TAG..HEAD"
|
||||
git log "$LAST_TAG"..HEAD --no-merges --pretty='- %s' > "$RUNNER_TEMP/commits.md"
|
||||
wc -l "$RUNNER_TEMP/commits.md"
|
||||
|
||||
- name: Build changelog prompt
|
||||
run: |
|
||||
# Most recent CHANGELOG section doubles as the style example
|
||||
awk '/^# Version:/{n++} n==1' CHANGELOG.md > "$RUNNER_TEMP/style-example.md"
|
||||
|
||||
cat > "$RUNNER_TEMP/system-prompt.md" << 'SYSEOF'
|
||||
You are the release manager for Leantime, an open source project management
|
||||
system. You write the CHANGELOG.md section for a new release based on the
|
||||
git commit subjects since the last release.
|
||||
|
||||
Format rules:
|
||||
- Start with exactly: # Version: <version>
|
||||
- Use these sections, in this order, and ONLY if they have content:
|
||||
## Highlights, ## New Features, ## Bug Fixes, ## Improvements, ## Security, ## Localization, ## Dependency Updates
|
||||
- Highlights: at most 1-3 entries, only for genuinely notable user-facing
|
||||
features (### subheading + a short paragraph). Most releases have none -
|
||||
omit the section rather than inflate minor work.
|
||||
- All other entries are single bullets: **Short Title** - one-sentence
|
||||
user-facing description ending with the PR reference(s), e.g. (#1234)
|
||||
- Rewrite commit subjects into user-facing language; never copy
|
||||
conventional-commit prefixes like fix(scope): into the output.
|
||||
- Merge multiple commits about the same change into one bullet with all
|
||||
PR references.
|
||||
- Group dependency bumps into ## Dependency Updates as terse bullets.
|
||||
- Skip pure chores with no user impact (CI tweaks, code style, review
|
||||
follow-up commits that have no PR reference).
|
||||
- Output raw markdown only - no surrounding code fences, no commentary.
|
||||
|
||||
Here is the previous release's section as a style example:
|
||||
|
||||
SYSEOF
|
||||
cat "$RUNNER_TEMP/style-example.md" >> "$RUNNER_TEMP/system-prompt.md"
|
||||
|
||||
{
|
||||
echo "Write the CHANGELOG section for version $VERSION based on these commits:"
|
||||
echo
|
||||
cat "$RUNNER_TEMP/commits.md"
|
||||
} > "$RUNNER_TEMP/prompt.md"
|
||||
|
||||
- name: Generate changelog section
|
||||
env:
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
run: |
|
||||
if [ -z "$ANTHROPIC_API_KEY" ]; then
|
||||
echo "::error::ANTHROPIC_API_KEY secret is not set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
jq -n \
|
||||
--rawfile system "$RUNNER_TEMP/system-prompt.md" \
|
||||
--rawfile prompt "$RUNNER_TEMP/prompt.md" \
|
||||
'{
|
||||
model: "claude-opus-4-8",
|
||||
max_tokens: 8000,
|
||||
thinking: {type: "adaptive"},
|
||||
system: $system,
|
||||
messages: [{role: "user", content: $prompt}]
|
||||
}' > "$RUNNER_TEMP/request.json"
|
||||
|
||||
if ! curl -sS --fail-with-body --max-time 600 https://api.anthropic.com/v1/messages \
|
||||
-H "x-api-key: $ANTHROPIC_API_KEY" \
|
||||
-H "anthropic-version: 2023-06-01" \
|
||||
-H "content-type: application/json" \
|
||||
-d @"$RUNNER_TEMP/request.json" > "$RUNNER_TEMP/response.json"; then
|
||||
echo "::error::Anthropic API request failed"
|
||||
cat "$RUNNER_TEMP/response.json"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Adaptive thinking responses interleave thinking blocks - keep text blocks only
|
||||
jq -r '[.content[] | select(.type == "text") | .text] | join("\n")' \
|
||||
"$RUNNER_TEMP/response.json" > "$RUNNER_TEMP/ai-response.md"
|
||||
|
||||
if ! [ -s "$RUNNER_TEMP/ai-response.md" ]; then
|
||||
echo "::error::Empty changelog from the API (stop_reason: $(jq -r '.stop_reason' "$RUNNER_TEMP/response.json"))"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Prepend section to CHANGELOG.md
|
||||
run: |
|
||||
sed '/^```/d' "$RUNNER_TEMP/ai-response.md" > "$RUNNER_TEMP/new-section.md"
|
||||
if ! head -1 "$RUNNER_TEMP/new-section.md" | grep -q "^# Version: $VERSION"; then
|
||||
printf '# Version: %s\n\n' "$VERSION" | cat - "$RUNNER_TEMP/new-section.md" > "$RUNNER_TEMP/new-section.tmp"
|
||||
mv "$RUNNER_TEMP/new-section.tmp" "$RUNNER_TEMP/new-section.md"
|
||||
fi
|
||||
{ cat "$RUNNER_TEMP/new-section.md"; echo; echo '---'; echo; cat CHANGELOG.md; } > "$RUNNER_TEMP/changelog.md"
|
||||
mv "$RUNNER_TEMP/changelog.md" CHANGELOG.md
|
||||
|
||||
{
|
||||
echo "Automated release PR. Review and edit the changelog below (it ships as CHANGELOG.md and as the GitHub release notes), wait for CI, then merge - the release publishes automatically."
|
||||
echo
|
||||
echo '---'
|
||||
echo
|
||||
cat "$RUNNER_TEMP/new-section.md"
|
||||
} > "$RUNNER_TEMP/pr-body.md"
|
||||
|
||||
- name: Open release PR
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
commit-message: 'release: bump version to ${{ inputs.version }} + changelog'
|
||||
branch: release/v${{ inputs.version }}
|
||||
delete-branch: true
|
||||
base: master
|
||||
title: 'Release v${{ inputs.version }}'
|
||||
labels: release
|
||||
body-path: ${{ runner.temp }}/pr-body.md
|
||||
81
.github/workflows/release.yml
vendored
Normal file
81
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
name: Create Release
|
||||
|
||||
# Runs automatically when a release/vX.Y.Z PR (opened by the Prepare Release
|
||||
# workflow) is merged into master. Manual escape hatches: dispatch directly or
|
||||
# push a version tag - both release whatever version AppSettings.php declares.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
pull_request:
|
||||
types: [closed]
|
||||
branches:
|
||||
- master
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build_release:
|
||||
name: build_release
|
||||
if: github.event_name != 'pull_request' || (github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/'))
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
# On pull_request events github.sha points at a transient PR merge ref,
|
||||
# not the commit that landed on master - build and tag merge_commit_sha.
|
||||
- name: checkout
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.merge_commit_sha || github.ref }}
|
||||
|
||||
# Same PHP setup as Makefile CI - the runner's stock ext-redis (5.3.7)
|
||||
# conflicts with symfony/cache >= 7.4, which requires ext-redis >= 6.1.
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.3'
|
||||
extensions: redis, gd, ldap, mbstring, pdo_mysql, zip, bcmath, exif, pcntl
|
||||
|
||||
- name: version
|
||||
run: echo "version=$(make get-version)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
# COMPOSER_AUTH prevents GitHub API rate-limiting; without it composer silently
|
||||
# falls back to source (git clone) installs, shipping .git dirs and package build/
|
||||
# test artifacts that ballooned release archives (#3330).
|
||||
- name: build artifacts
|
||||
run: make package
|
||||
env:
|
||||
COMPOSER_AUTH: '{"github-oauth": {"github.com": "${{ github.token }}"}}'
|
||||
|
||||
- name: Extract changelog section
|
||||
run: |
|
||||
awk '/^# Version:/{n++} n==1' CHANGELOG.md > "$RUNNER_TEMP/release-body.md"
|
||||
if ! grep -q "Version: ${{ steps.version.outputs.version }}" "$RUNNER_TEMP/release-body.md"; then
|
||||
echo "::warning::Top CHANGELOG.md section does not match v${{ steps.version.outputs.version }}; falling back to auto-generated notes only"
|
||||
: > "$RUNNER_TEMP/release-body.md"
|
||||
fi
|
||||
|
||||
- name: release
|
||||
uses: ncipollo/release-action@v1
|
||||
id: create_release
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
name: Leantime v${{ steps.version.outputs.version }}
|
||||
tag: v${{ steps.version.outputs.version }}
|
||||
commit: ${{ github.event_name == 'pull_request' && github.event.pull_request.merge_commit_sha || github.sha }}
|
||||
generateReleaseNotes: true
|
||||
makeLatest: true
|
||||
bodyFile: ${{ runner.temp }}/release-body.md
|
||||
artifacts: './target/Leantime-v${{ steps.version.outputs.version }}.zip,./target/Leantime-v${{ steps.version.outputs.version }}.tar.gz'
|
||||
|
||||
- name: Run latest-tag
|
||||
uses: EndBug/latest-tag@latest
|
||||
with:
|
||||
ref: latest
|
||||
description: Latest Release of Leantime.
|
||||
63
.github/workflows/security.yml
vendored
Normal file
63
.github/workflows/security.yml
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
name: Security Audit
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ "master", "*.*-dev" ]
|
||||
pull_request:
|
||||
branches: [ "master", "*.*-dev" ]
|
||||
schedule:
|
||||
- cron: '0 8 * * 1' # Weekly on Monday at 8am UTC
|
||||
|
||||
jobs:
|
||||
composer-audit:
|
||||
name: Composer Security Audit
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.3'
|
||||
extensions: redis, gd, ldap, mbstring, pdo_mysql, zip, bcmath, exif, pcntl
|
||||
|
||||
- name: Install Composer Dependencies
|
||||
run: composer install --no-dev --no-interaction --prefer-dist
|
||||
|
||||
- name: Run Composer Audit
|
||||
run: composer audit --format=summary
|
||||
continue-on-error: true
|
||||
|
||||
npm-audit:
|
||||
name: NPM Security Audit
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Install NPM Dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run NPM Audit
|
||||
run: npm audit --audit-level=high
|
||||
|
||||
codeql:
|
||||
name: CodeQL Analysis
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
security-events: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: javascript
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
26
.github/workflows/staticAnalysis.yml
vendored
Normal file
26
.github/workflows/staticAnalysis.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
name: Static Analysis
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ "master", "*.*-dev" ]
|
||||
pull_request:
|
||||
branches: [ "master", "*.*-dev" ]
|
||||
|
||||
jobs:
|
||||
phpstan:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.3'
|
||||
extensions: redis, gd, ldap, mbstring, pdo_mysql, zip, bcmath, exif, pcntl
|
||||
|
||||
- name: Install Dependencies
|
||||
run: make build-dev
|
||||
|
||||
- name: Run PHPStan Analysis
|
||||
run: make phpstan
|
||||
30
.github/workflows/unittests.yml
vendored
Normal file
30
.github/workflows/unittests.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: Unit Tests
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ "master", "*.*-dev" ]
|
||||
pull_request:
|
||||
branches: [ "master", "*.*-dev" ]
|
||||
|
||||
jobs:
|
||||
unit:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.3'
|
||||
extensions: redis, gd, ldap, mbstring, pdo_mysql, zip, bcmath, exif, pcntl
|
||||
|
||||
- name: Run Unit Tests
|
||||
run: make unit-test
|
||||
|
||||
- name: Store screenshots
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: unit-test
|
||||
path: tests/_output
|
||||
32
.github/workflows/update-latest-tag.yml
vendored
Normal file
32
.github/workflows/update-latest-tag.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: Updated Latest Tag
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build_release:
|
||||
name: build_release
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Run latest-tag
|
||||
uses: EndBug/latest-tag@latest
|
||||
with:
|
||||
# You can change the name of the tag or branch with this input.
|
||||
# Default: 'latest'
|
||||
ref: latest
|
||||
|
||||
# If a description is provided, the action will use it to create an annotated tag. If none is given, the action will create a lightweight tag.
|
||||
# Default: ''
|
||||
description: Latest Release of Leantime.
|
||||
|
||||
# Force-update a branch instead of using a tag.
|
||||
# Default: false
|
||||
# force-branch: true
|
||||
|
||||
# Directory to use when executing git commands
|
||||
# Default: '${{ github.workspace }}'
|
||||
# git-directory: 'path/to/repo/dir'
|
||||
Reference in New Issue
Block a user