はじまりの大地

このコミットが含まれているのは:
2024-07-15 09:14:04 +09:00
コミット 6632905f32
3501個のファイルの変更1439465行の追加0行の削除
+323
ファイルの表示
@@ -0,0 +1,323 @@
import autocannon, { printResult } from 'autocannon'
import { program } from 'commander'
import { writeJson } from 'fs-extra/esm'
import { Video, VideoPrivacy } from '@peertube/peertube-models'
import {
createMultipleServers,
doubleFollow,
killallServers,
PeerTubeServer,
setAccessTokensToServers
} from '@peertube/peertube-server-commands'
let servers: PeerTubeServer[]
// First server
let server: PeerTubeServer
let video: Video
let threadId: number
program
.option('-o, --outfile [outfile]', 'Outfile')
.option('--grep [string]', 'Filter tests you want to execute')
.description('Run API REST benchmark')
.parse(process.argv)
const options = program.opts()
const outfile = options.outfile
run()
.catch(err => console.error(err))
.finally(() => {
if (servers) return killallServers(servers)
})
function buildAuthorizationHeader () {
return {
Authorization: 'Bearer ' + server.accessToken
}
}
function buildAPHeader () {
return {
Accept: 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'
}
}
function buildJSONHeader () {
return {
'Content-Type': 'application/json'
}
}
async function run () {
console.log('Preparing server...')
await prepare()
const tests = [
{
title: 'AP - account peertube',
path: '/accounts/peertube',
headers: buildAPHeader(),
expecter: (body, status) => {
return status === 200 && body.startsWith('{"@context":')
}
},
{
title: 'AP - video',
path: '/videos/watch/' + video.uuid,
headers: buildAPHeader(),
expecter: (body, status) => {
return status === 200 && body.startsWith('{"@context":')
}
},
{
title: 'Misc - webfinger peertube',
path: '/.well-known/webfinger?resource=acct:peertube@' + server.host,
expecter: (body, status) => {
return status === 200 && body.startsWith('{"subject":')
}
},
{
title: 'API - unread notifications',
path: '/api/v1/users/me/notifications?start=0&count=0&unread=true',
headers: buildAuthorizationHeader(),
expecter: (_body, status) => {
return status === 200
}
},
{
title: 'API - me',
path: '/api/v1/users/me',
headers: buildAuthorizationHeader(),
expecter: (body, status) => {
return status === 200 && body.startsWith('{"id":')
}
},
{
title: 'API - videos list',
path: '/api/v1/videos',
expecter: (body, status) => {
return status === 200 && body.startsWith('{"total":10')
}
},
{
title: 'API - video get',
path: '/api/v1/videos/' + video.uuid,
expecter: (body, status) => {
return status === 200 && body.startsWith('{"id":')
}
},
{
title: 'API - video captions',
path: '/api/v1/videos/' + video.uuid + '/captions',
expecter: (body, status) => {
return status === 200 && body.startsWith('{"total":4')
}
},
{
title: 'API - video threads',
path: '/api/v1/videos/' + video.uuid + '/comment-threads',
expecter: (body, status) => {
return status === 200 && body.startsWith('{"total":10')
}
},
{
title: 'API - video replies',
path: '/api/v1/videos/' + video.uuid + '/comment-threads/' + threadId,
expecter: (body, status) => {
return status === 200 && body.startsWith('{"comment":{')
}
},
{
title: 'HTML - video watch',
path: '/videos/watch/' + video.uuid,
expecter: (body, status) => {
return status === 200 && body.includes('<title>my super')
}
},
{
title: 'HTML - video embed',
path: '/videos/embed/' + video.uuid,
expecter: (body, status) => {
return status === 200 && body.includes('embed')
}
},
{
title: 'HTML - homepage',
path: '/',
expecter: (_body, status) => {
return status === 200
}
},
{
title: 'API - config',
path: '/api/v1/config',
expecter: (body, status) => {
return status === 200 && body.startsWith('{"client":')
}
},
{
title: 'API - views with token',
method: 'PUT',
headers: {
...buildAuthorizationHeader(),
...buildJSONHeader()
},
body: JSON.stringify({ currentTime: 2 }),
path: '/api/v1/videos/' + video.uuid + '/views',
expecter: (body, status) => {
return status === 204
}
},
{
title: 'API - views without token',
method: 'POST',
headers: buildJSONHeader(),
body: JSON.stringify({ currentTime: 2 }),
path: '/api/v1/videos/' + video.uuid + '/views',
expecter: (body, status) => {
return status === 204
}
}
].filter(t => {
if (!options.grep) return true
return t.title.includes(options.grep)
})
const finalResult: any[] = []
for (const test of tests) {
console.log('Running against %s.', test.path)
const testResult = await runBenchmark(test)
Object.assign(testResult, { title: test.title, path: test.path })
finalResult.push(testResult)
console.log(printResult(testResult))
}
if (outfile) await writeJson(outfile, finalResult)
}
function runBenchmark (options: {
path: string
method?: string
body?: string
headers?: { [ id: string ]: string }
expecter: Function
}) {
const { method = 'GET', path, body, expecter, headers } = options
return new Promise((res, rej) => {
autocannon({
url: server.url + path,
method,
body,
connections: 20,
headers,
pipelining: 1,
duration: 10,
requests: [
{
onResponse: (status, body) => {
if (expecter(body, status) !== true) {
console.error('Expected result failed.', { body, status })
throw new Error('Invalid expectation')
}
}
}
]
}, (err, result) => {
if (err) return rej(err)
return res(result)
})
})
}
async function prepare () {
servers = await createMultipleServers(3, {
rates_limit: {
api: {
max: 5_000_000
},
login: {
max: 5_000_000
},
signup: {
max: 5_000_000
},
ask_send_email: {
max: 5_000_000
},
receive_client_log: {
max: 5_000_000
},
plugins: {
max: 5_000_000
},
well_known: {
max: 5_000_000
},
feeds: {
max: 5_000_000
},
activity_pub: {
max: 5_000_000
},
client: {
max: 5_000_000
}
}
}, { nodeArgs: [ '--inspect' ] })
server = servers[0]
await setAccessTokensToServers(servers)
await doubleFollow(servers[0], servers[1])
await doubleFollow(servers[0], servers[2])
const attributes = {
name: 'my super video',
category: 2,
nsfw: true,
licence: 6,
language: 'fr',
privacy: VideoPrivacy.PUBLIC,
support: 'please give me a coffee',
description: 'my super description\n'.repeat(10) + ' * list1\n * list 2\n * list 3',
tags: [ 'tag1', 'tag2', 'tag3' ]
}
for (let i = 0; i < 10; i++) {
await server.videos.upload({ attributes: { ...attributes, name: 'my super video ' + i } })
}
const { data } = await server.videos.list()
video = data.find(v => v.name === 'my super video 1')
for (let i = 0; i < 10; i++) {
const text = 'my super first comment'
const created = await server.comments.createThread({ videoId: video.id, text })
threadId = created.id
const text1 = 'my super answer to thread 1'
const child = await server.comments.addReply({ videoId: video.id, toCommentId: threadId, text: text1 })
const text2 = 'my super answer to answer of thread 1'
await server.comments.addReply({ videoId: video.id, toCommentId: child.id, text: text2 })
const text3 = 'my second answer to thread 1'
await server.comments.addReply({ videoId: video.id, toCommentId: threadId, text: text3 })
}
for (const caption of [ 'ar', 'fr', 'en', 'zh' ]) {
await server.captions.add({
language: caption,
videoId: video.id,
fixture: 'subtitle-good2.vtt'
})
}
}
実行可能ファイル
+93
ファイルの表示
@@ -0,0 +1,93 @@
#!/bin/bash
set -eu
declare -A languages
defaultLanguage="en-US"
# Supported languages
languages=(
["ar"]="ar"
["is"]="is"
["tr"]="tr-TR"
["fa"]="fa-IR"
["en"]="en-US"
["vi"]="vi-VN"
["hu"]="hu-HU"
["th"]="th-TH"
["fi"]="fi-FI"
["nl"]="nl-NL"
["gd"]="gd"
["el"]="el-GR"
["es"]="es-ES"
["oc"]="oc"
["pt"]="pt-BR"
["pt-PT"]="pt-PT"
["sv"]="sv-SE"
["pl"]="pl-PL"
["ru"]="ru-RU"
["zh-Hans"]="zh-Hans-CN"
["zh-Hant"]="zh-Hant-TW"
["fr"]="fr-FR"
["ja"]="ja-JP"
["eu"]="eu-ES"
["ca"]="ca-ES"
["gl"]="gl-ES"
["cs"]="cs-CZ"
["hr"]="hr"
["eo"]="eo"
["de"]="de-DE"
["it"]="it-IT"
["uk"]="uk-UA"
["sq"]="sq"
["tok"]="tok"
["nn"]="nn"
["nb"]="nb-NO"
["kab"]="kab"
)
cd client
rm -rf ./dist
# Don't build other languages if --light arg is provided
if [ -z ${1+x} ] || ([ "$1" != "--light" ] && [ "$1" != "--analyze-bundle" ]); then
additionalParams=""
if [ ! -z ${1+x} ] && [ "$1" == "--source-map" ]; then
additionalParams="--source-map=true"
fi
node --max_old_space_size=8192 node_modules/.bin/ng build --configuration production --output-path "dist/build" $additionalParams
for key in "${!languages[@]}"; do
lang=${languages[$key]}
mv "dist/build/browser/$key" "dist/$lang"
if [ "$lang" != "en-US" ]; then
# Do not duplicate assets
rm -r "./dist/$lang/assets"
fi
done
mv "./dist/$defaultLanguage/assets" "./dist"
rm -r "dist/build"
cp "./dist/$defaultLanguage/manifest.webmanifest" "./dist/manifest.webmanifest"
else
additionalParams=""
if [ ! -z ${1+x} ] && [ "$1" == "--analyze-bundle" ]; then
additionalParams="--named-chunks=true --output-hashing=none"
# For Vite
export ANALYZE_BUNDLE=true
fi
node --max_old_space_size=8192 node_modules/.bin/ng build --localize=false --output-path "dist/$defaultLanguage/" \
--configuration production --stats-json $additionalParams
fi
cd ../ && npm run build:embed && cd client/
# Copy runtime locales
cp -r "./src/locale" "./dist/locale"
実行可能ファイル
+5
ファイルの表示
@@ -0,0 +1,5 @@
#!/bin/bash
set -eu
cd client && ./node_modules/.bin/vite -c ./src/standalone/videos/vite.config.mjs build --mode=production
実行可能ファイル
+12
ファイルの表示
@@ -0,0 +1,12 @@
#!/bin/bash
set -eu
npm run build:server
# Angular does not support project references, it's the reason why we can't builds concurrently
if [ ! -z ${1+x} ]; then
npm run build:client -- $1
else
npm run build:client
fi
+12
ファイルの表示
@@ -0,0 +1,12 @@
#!/bin/bash
set -eu
cd ./apps/peertube-cli
rm -rf ./dist
../../node_modules/.bin/tsc -b --verbose
rm -rf ./dist
mkdir ./dist
node ./scripts/build.js
実行可能ファイル
+12
ファイルの表示
@@ -0,0 +1,12 @@
#!/bin/bash
set -eu
cd ./apps/peertube-runner
rm -rf ./dist
../../node_modules/.bin/tsc -b --verbose
rm -rf ./dist
mkdir ./dist
node ./scripts/build.js
実行可能ファイル
+11
ファイルの表示
@@ -0,0 +1,11 @@
#!/bin/bash
set -eu
rm -rf ./dist ./packages/*/dist
npm run tsc -- -b --verbose server/tsconfig.json
npm run resolve-tspaths:server
cp -r "./server/core/static" "./server/core/assets" ./dist/core
cp "./server/scripts/upgrade.sh" "./dist/scripts"
実行可能ファイル
+9
ファイルの表示
@@ -0,0 +1,9 @@
#!/bin/bash
set -eu
rm -rf ./packages/tests/dist
npm run tsc -- -b --verbose ./packages/tests/tsconfig.json
npm run resolve-tspaths:server-lib
npm run resolve-tspaths:tests
実行可能ファイル
+161
ファイルの表示
@@ -0,0 +1,161 @@
#!/bin/bash
set -eu
if [ $# -eq 0 ]; then
echo "Need test suite argument."
exit -1
fi
retries=3
speedFactor="${2:-1}"
runJSTest () {
jobname=$1
shift
jobs=$1
shift
files=$@
echo $files
joblog="$jobname-ci.log"
parallel -j $jobs --retries $retries \
"echo Trying {} >> $joblog; npm run mocha -- --timeout 30000 --no-config -c --exit --bail {}" \
::: $files
cat "$joblog" | sort | uniq -c
rm "$joblog"
}
findTestFiles () {
exception="-not -name index.js -not -name index.ts -not -name *.d.ts"
if [ ! -z ${2+x} ]; then
exception="$exception -not -name $2"
fi
find $1 -type f \( -name "*.js" -o -name "*.ts" \) $exception | xargs echo
}
if [ "$1" = "types-package" ]; then
npm run generate-types-package 0.0.0
# Test on in independent directory
rm -fr /tmp/types-generator
mkdir -p /tmp/types-generator
cp -r packages/types-generator/tests /tmp/types-generator/tests
cp -r packages/types-generator/dist /tmp/types-generator/dist
(cd /tmp/types-generator/dist && npm install)
npm run tsc -- --noEmit --esModuleInterop --moduleResolution node16 --module Node16 /tmp/types-generator/tests/test.ts
rm -r /tmp/types-generator
elif [ "$1" = "client" ]; then
npm run build
npm run build:tests
feedsFiles=$(findTestFiles ./packages/tests/dist/feeds)
clientFiles=$(findTestFiles ./packages/tests/dist/client)
miscFiles="./packages/tests/dist/misc-endpoints.js ./packages/tests/dist/nginx.js"
# Not in their own task, they need an index.html
pluginFiles="./packages/tests/dist/plugins/html-injection.js ./packages/tests/dist/api/server/plugins.js"
MOCHA_PARALLEL=true runJSTest "$1" $((2*$speedFactor)) $feedsFiles $miscFiles $pluginFiles $clientFiles
# Use TS tests directly because we import server files
helperFiles=$(findTestFiles ./packages/tests/src/server-helpers)
libFiles=$(findTestFiles ./packages/tests/src/server-lib)
npm run mocha -- --timeout 30000 -c --exit --bail $libFiles $helperFiles
elif [ "$1" = "cli-plugin" ]; then
# Simulate HTML
mkdir -p "./client/dist/en-US/"
cp "./client/src/index.html" "./client/dist/en-US/index.html"
npm run build:server
npm run build:tests
npm run build:peertube-cli
# html-injection test needs an HTML file
pluginsFiles=$(findTestFiles ./packages/tests/dist/plugins html-injection.js)
cliFiles=$(findTestFiles ./packages/tests/dist/cli)
MOCHA_PARALLEL=true runJSTest "$1" $((2*$speedFactor)) $pluginsFiles
runJSTest "$1" 1 $cliFiles
elif [ "$1" = "api-1" ]; then
npm run build:server
npm run build:tests
checkParamFiles=$(findTestFiles ./packages/tests/dist/api/check-params)
notificationsFiles=$(findTestFiles ./packages/tests/dist/api/notifications)
searchFiles=$(findTestFiles ./packages/tests/dist/api/search)
MOCHA_PARALLEL=true runJSTest "$1" $((3*$speedFactor)) $notificationsFiles $searchFiles $checkParamFiles
elif [ "$1" = "api-2" ]; then
npm run build:server
npm run build:tests
liveFiles=$(findTestFiles ./packages/tests/dist/api/live)
# plugins test needs an HTML file
serverFiles=$(findTestFiles ./packages/tests/dist/api/server plugins.js)
usersFiles=$(findTestFiles ./packages/tests/dist/api/users)
MOCHA_PARALLEL=true runJSTest "$1" $((3*$speedFactor)) $liveFiles $serverFiles $usersFiles
elif [ "$1" = "api-3" ]; then
npm run build:server
npm run build:tests
videosFiles=$(findTestFiles ./packages/tests/dist/api/videos)
viewsFiles=$(findTestFiles ./packages/tests/dist/api/views)
MOCHA_PARALLEL=true runJSTest "$1" $((3*$speedFactor)) $viewsFiles $videosFiles
elif [ "$1" = "api-4" ]; then
npm run build:server
npm run build:tests
moderationFiles=$(findTestFiles ./packages/tests/dist/api/moderation)
redundancyFiles=$(findTestFiles ./packages/tests/dist/api/redundancy)
objectStorageFiles=$(findTestFiles ./packages/tests/dist/api/object-storage)
activitypubFiles=$(findTestFiles ./packages/tests/dist/api/activitypub)
MOCHA_PARALLEL=true runJSTest "$1" $((2*$speedFactor)) $moderationFiles $redundancyFiles $activitypubFiles $objectStorageFiles
elif [ "$1" = "api-5" ]; then
npm run build:server
npm run build:tests
transcodingFiles=$(findTestFiles ./packages/tests/dist/api/transcoding)
runnersFiles=$(findTestFiles ./packages/tests/dist/api/runners)
MOCHA_PARALLEL=true runJSTest "$1" $((2*$speedFactor)) $transcodingFiles $runnersFiles
elif [ "$1" = "external-plugins" ]; then
npm run install-dependencies:transcription --workspace=@peertube/tests
npm run build:server
npm run build:tests
npm run build:peertube-runner
externalPluginsFiles=$(findTestFiles ./packages/tests/dist/external-plugins)
peertubeRunnerFiles=$(findTestFiles ./packages/tests/dist/peertube-runner)
runJSTest "$1" 1 $externalPluginsFiles
MOCHA_PARALLEL=true runJSTest "$1" $((2*$speedFactor)) $peertubeRunnerFiles
elif [ "$1" = "lint" ]; then
npm run eslint -- --ext .ts "server/**/*.ts" "scripts/**/*.ts" "packages/**/*.ts" "apps/**/*.ts"
npm run swagger-cli -- validate support/doc/api/openapi.yaml
( cd client && npm run lint )
elif [ "$1" = "transcription" ]; then
npm run install-dependencies:transcription --workspace=@peertube/tests
npm run build:server
npm run build:tests
transcriptionFiles=$(findTestFiles ./packages/tests/dist/transcription)
transcriptionDevToolsFiles=$(findTestFiles ./packages/tests/dist/transcription-devtools)
MOCHA_PARALLEL=true runJSTest "$1" $((3*$speedFactor)) $transcriptionFiles $transcriptionDevToolsFiles
fi
実行可能ファイル
+6
ファイルの表示
@@ -0,0 +1,6 @@
#!/bin/sh
set -eu
cd client
rm -rf compiled/ dist/ dll/
実行可能ファイル
+41
ファイルの表示
@@ -0,0 +1,41 @@
#!/bin/sh
set -eu
recreateDB () {
dbname="peertube_test$1"
dropdb --if-exists "$dbname" 2>&1
createdb -O peertube "$dbname"
psql -c "CREATE EXTENSION pg_trgm;" "$dbname" &
psql -c "CREATE EXTENSION unaccent;" "$dbname" &
}
removeFiles () {
rm -rf "./test$1" "./config/local-test.json" "./config/local-test-$1.json" ~/.config/PeerTube/CLI-$1
}
dropRedis () {
port=$((9000+$1))
host="127.0.0.1"
redis-cli -h "$host" KEYS "bull-127.0.0.1:$port*" | grep -v empty | xargs -r redis-cli -h "$host" DEL
redis-cli -h "$host" KEYS "redis-127.0.0.1:$port*" | grep -v empty | xargs -r redis-cli -h "$host" DEL
redis-cli -h "$host" KEYS "*redis-127.0.0.1:$port-" | grep -v empty | xargs -r redis-cli -h "$host" DEL
}
seq=$(seq 1 6)
if [ ! -z ${1+x} ]; then
seq=$1
fi
for i in $seq; do
recreateDB "$i" &
dropRedis "$i" &
removeFiles "$i" &
done
wait
+37
ファイルの表示
@@ -0,0 +1,37 @@
import { root } from '@peertube/peertube-node-utils'
import { readdir, stat } from 'fs/promises'
import { join } from 'path'
async function run () {
const result = {
app: await buildResult(join(root(), 'client', 'dist', 'en-US')),
embed: await buildResult(join(root(), 'client', 'dist', 'standalone', 'videos'))
}
console.log(JSON.stringify(result))
}
run()
.catch(err => console.error(err))
async function buildResult (path: string, root = path) {
const distFiles = await readdir(path)
let files: { name: string, size: number }[] = []
for (const file of distFiles) {
const filePath = join(path, file)
const statsResult = await stat(filePath)
if (statsResult.isDirectory()) {
files = files.concat(await buildResult(filePath, root))
}
files.push({
name: filePath.replace(new RegExp(`^${root}/`), ''),
size: statsResult.size
})
}
return files
}
実行可能ファイル
+7
ファイルの表示
@@ -0,0 +1,7 @@
#!/bin/sh
set -eu
npm run concurrently -- -k \
"cd client/src/standalone/videos/ && npx vite-bundle-visualizer" \
"cd client && npx esbuild-visualizer --metadata ./dist/en-US/stats.json"
実行可能ファイル
+22
ファイルの表示
@@ -0,0 +1,22 @@
#!/bin/bash
set -eu
clientConfiguration="hmr"
if [ ! -z ${2+x} ] && [ "$2" = "--ar-locale" ]; then
clientConfiguration="ar-locale"
fi
clientCommand="cd client && node --max_old_space_size=4096 node_modules/.bin/ng serve --proxy-config proxy.config.json --hmr --configuration $clientConfiguration --host 0.0.0.0 --port 3000"
serverCommand="NODE_ENV=dev node dist/server"
if [ ! -z ${1+x} ] && [ "$1" = "--skip-server" ]; then
eval $clientCommand
else
npm run build:server
node node_modules/.bin/concurrently -k \
"$clientCommand" \
"$serverCommand"
fi
実行可能ファイル
+9
ファイルの表示
@@ -0,0 +1,9 @@
#!/bin/bash
set -eu
npm run build:server
npm run concurrently -- -k \
"cd client && ./node_modules/.bin/vite -c ./src/standalone/videos/vite.config.mjs build -w --mode=development" \
"NODE_ENV=dev npm start"
実行可能ファイル
+7
ファイルの表示
@@ -0,0 +1,7 @@
#!/bin/bash
set -eu
npm run concurrently -- -k \
"sh scripts/dev/client.sh --skip-server ${1:-}" \
"sh scripts/dev/server.sh --skip-client"
実行可能ファイル
+11
ファイルの表示
@@ -0,0 +1,11 @@
#!/bin/bash
set -eu
rm -rf ./apps/peertube-cli/dist
cd ./apps/peertube-cli
../../node_modules/.bin/concurrently -k \
"../../node_modules/.bin/tsc -w --noEmit" \
"node ./scripts/watch.js"
実行可能ファイル
+13
ファイルの表示
@@ -0,0 +1,13 @@
#!/bin/bash
set -eu
rm -rf ./apps/peertube-runner/dist
cd ./apps/peertube-runner
../../node_modules/.bin/tsc -b --verbose
../../node_modules/.bin/concurrently -k \
"../../node_modules/.bin/tsc -w --noEmit" \
"node ./scripts/watch.js"
実行可能ファイル
+24
ファイルの表示
@@ -0,0 +1,24 @@
#!/bin/bash
set -eu
if [ ! -f "./client/dist/en-US/index.html" ]; then
if [ -z ${1+x} ] || [ "$1" != "--skip-client" ]; then
echo "client/dist/en-US/index.html does not exist, compile client files..."
npm run build:client
fi
fi
# Copy locales
mkdir -p "./client/dist"
rm -rf "./client/dist/locale"
cp -r "./client/src/locale" "./client/dist/locale"
mkdir -p "./dist/core/lib"
npm run tsc -- -b -v --incremental server/tsconfig.json
npm run resolve-tspaths:server
cp -r ./server/core/static ./server/core/assets ./dist/core
./node_modules/.bin/tsc-watch --build --preserveWatchOutput --verbose --onSuccess 'sh -c "npm run resolve-tspaths:server && NODE_ENV=dev node dist/server"' server/tsconfig.json
実行可能ファイル
+5
ファイルの表示
@@ -0,0 +1,5 @@
#!/bin/sh
set -eu
cd client/e2e && ../node_modules/.bin/wdio run ./wdio.browserstack.conf.ts
実行可能ファイル
+7
ファイルの表示
@@ -0,0 +1,7 @@
#!/bin/sh
set -eu
cd client/e2e
../node_modules/.bin/wdio run ./wdio.local.conf.ts
+201
ファイルの表示
@@ -0,0 +1,201 @@
import { CLICommand } from '@peertube/peertube-server-commands'
run()
.then(() => process.exit(0))
.catch(err => {
console.error(err)
process.exit(-1)
})
async function run () {
const excludeList = getContributorsExcludeList()
{
let contributors = await getGitContributors()
contributors = contributors.concat(getZanataContributors())
contributors = contributors.filter(c => !excludeList.has(c.username))
console.log('# Code & Translators contributors\n')
for (const contributor of contributors) {
console.log(` * ${contributor.username}`)
}
}
{
console.log('\n\n# Design\n')
console.log(' * [Olivier Massain](https://dribbble.com/omassain)')
console.log(' * [Marie-Cécile Godwin Paccard](https://mcgodwin.com/)')
console.log('\n\n# Icons\n')
console.log(' * [Feather Icons](https://feathericons.com) (MIT)')
console.log(' * `playlist add`, `history`, `subscriptions`, `miscellaneous-services.svg`, `tip` by Material UI (Apache 2.0)')
console.log(' * `support` by Chocobozzz (CC-BY)')
console.log(' * `language` by Aaron Jin (CC-BY)')
console.log(' * `video-language` by Rigel Kent (CC-BY)')
console.log(' * `peertube-x` by Solen DP (CC-BY)')
console.log(' * `flame` by Freepik (Flaticon License)')
console.log(' * `local` by Larea (CC-BY)')
}
{
console.log('\n\n# Contributors to our 2020 crowdfunding :heart:\n')
console.log(
`*We ran [a crowdfunding campaign](https://joinpeertube.org/roadmap) in 2020 to implement live streaming to the version ` +
`3.0.0 of PeerTube. Thanks to everyone who pitched in and shared the news!*\n\n`
)
}
{
console.log('\n\n# Contributors to our 2018 crowdfunding :heart:')
console.log(
`\n*We ran [a crowdfunding campaign](https://www.kisskissbankbank.com/en/projects/peertube-a-free-and-federated-video-platform) ` +
`in 2018 to pave the road to the version 1.0.0 of PeerTube, with 1,379 backers. ` +
`Thanks to everyone who pitched in and shared the news!*\n\n`
)
}
}
async function getGitContributors () {
const output = await CLICommand.exec(`git --no-pager shortlog -sn < /dev/tty | sed 's/^\\s\\+[0-9]\\+\\s\\+//g'`)
return output.split('\n')
.filter(l => !!l)
.map(l => ({ username: l }))
}
// Zanata is dead, don't loose the contributors name
function getZanataContributors () {
return [
{ username: 'abdhessuk', name: 'Abd Hessuk' },
{ username: 'abidin24', name: 'abidin toumi' },
{ username: 'aditoo', name: 'Lorem Ipsum' },
{ username: 'alice', name: 'Alice' },
{ username: 'anastasia', name: 'Anastasia' },
{ username: 'autom', name: 'Filip Bengtsson' },
{ username: 'balaji', name: 'Balaji' },
{ username: 'bristow', name: 'Cédric F.' },
{ username: 'butterflyoffire', name: 'ButterflyOfFire' },
{ username: 'chocobozzz', name: 'Chocobozzz' },
{ username: 'claichou', name: 'Claire Mohin' },
{ username: 'degrange', name: 'Degrange Mathieu' },
{ username: 'dibek', name: 'Giuseppe Di Bella' },
{ username: 'edu', name: 'eduardo' },
{ username: 'ehsaan', name: 'ehsaan' },
{ username: 'esoforte', name: 'Ondřej Kotas' },
{ username: 'fkohrt', name: 'Florian Kohrt' },
{ username: 'giqtaqisi', name: 'Ian Townsend' },
{ username: 'goofy', name: 'goofy' },
{ username: 'gorkaazk', name: 'Gorka Azkarate Zubiaur' },
{ username: 'gwendald', name: 'GwendalD' },
{ username: 'h3zjp', name: 'h3zjp' },
{ username: 'jfblanc', name: 'Joan Francés Blanc' },
{ username: 'jhertel', name: 'Jean Hertel' },
{ username: 'jmf', name: 'Jan-Michael Franz' },
{ username: 'jorropo', name: 'Jorropo' },
{ username: 'kairozen', name: 'Geoffrey Baudelet' },
{ username: 'kedemferre', name: 'Kédem Ferré' },
{ username: 'kousha', name: 'Kousha Zanjani' },
{ username: 'krkk', name: 'Karol Kosek' },
{ username: 'landrok', name: 'Landrok' },
{ username: 'leeroyepold48', name: 'Leeroy Epold' },
{ username: 'm4sk1n', name: 'marcin mikołajczak' },
{ username: 'matograine', name: 'tom ngr' },
{ username: 'medow', name: 'Mahir Ahmed' },
{ username: 'mhu', name: 'Max Hübner' },
{ username: 'midgard', name: 'Midgard' },
{ username: 'nbrucy', name: 'N. B.' },
{ username: 'nitai', name: 'nitai bezerra' },
{ username: 'noncommutativegeo', name: 'Andrea Panontin' },
{ username: 'nopsidy', name: 'McFlat' },
{ username: 'nvivant', name: 'Nicolas Vivant' },
{ username: 'osoitz', name: 'Osoitz' },
{ username: 'outloudvi', name: 'Outvi V' },
{ username: 'quentin', name: 'Quentí' },
{ username: 'quentind', name: 'Quentin Dupont' },
{ username: 'rafaelff', name: 'Rafael Fontenelle' },
{ username: 'rigelk', name: 'Rigel Kent' },
{ username: 's8321414', name: 'Jeff Huang' },
{ username: 'sato_ss', name: 'Satoshi Shirosaka' },
{ username: 'sercom_kc', name: 'SerCom_KC' },
{ username: 'severo', name: 'Sylvain Lesage' },
{ username: 'silkevicious', name: 'Sylke Vicious' },
{ username: 'sosha', name: 'Sosha' },
{ username: 'spla', name: 'spla' },
{ username: 'strubbl', name: 'Sven' },
{ username: 'swedneck', name: 'Tim Stahel' },
{ username: 'tagomago', name: 'Tagomago' },
{ username: 'talone', name: 'TitiAlone' },
{ username: 'thibaultmartin', name: 'Thibault Martin' },
{ username: 'tirifto', name: 'Tirifto' },
{ username: 'tuxayo', name: 'Victor Grousset/tuxayo' },
{ username: 'unextro', name: 'Ondřej Pokorný' },
{ username: 'unzarida', name: 'unzarida' },
{ username: 'vincent', name: 'Vincent Laporte' },
{ username: 'wanhua', name: 'wanhua' },
{ username: 'xinayder', name: 'Alexandre' },
{ username: 'xosem', name: 'Xosé M.' },
{ username: 'zveryok', name: 'Nikitin Stanislav' },
{ username: '6543', name: '6543' },
{ username: 'aasami', name: 'Miroslav Ďurian' },
{ username: 'alidemirtas', name: 'Ali Demirtas' },
{ username: 'alpha', name: 'Alpha' },
{ username: 'ariasuni', name: 'Mélanie Chauvel' },
{ username: 'bfonton', name: 'Baptiste Fonton' },
{ username: 'c0dr', name: 'c0dr lnx' },
{ username: 'canony', name: 'canony' },
{ username: 'cat', name: 'Cat' },
{ username: 'clerie', name: 'Clemens Riese' },
{ username: 'curupira', name: 'Curupira' },
{ username: 'dhsets', name: 'djsets' },
{ username: 'digitalkiller', name: 'Digital Killer' },
{ username: 'dwsage', name: 'd.w. sage' },
{ username: 'flauta', name: 'Andrea Primiani' },
{ username: 'frankstrater', name: 'Frank Sträter' },
{ username: 'gillux', name: 'gillux' },
{ username: 'gunchleoc', name: 'GunChleoc' },
{ username: 'jaidedtd', name: 'Jenga Phoenix' },
{ username: 'joss2lyon', name: 'Josselin' },
{ username: 'kekkotranslates', name: 'Francesco' },
{ username: 'kingu', name: 'Allan Nordhøy' },
{ username: 'kittybecca', name: 'Rivka bat Tsvi' },
{ username: 'knuxify', name: 'knuxify' },
{ username: 'lapor', name: 'Kristijan Tkalec' },
{ username: 'laufor', name: 'Lau For' },
{ username: 'lstamellos', name: 'Loukas Stamellos' },
{ username: 'lw1', name: 'Lukas Winkler' },
{ username: 'mablr', name: 'Mablr' },
{ username: 'marcinmalecki', name: 'Marcin Małecki' },
{ username: 'mayana', name: 'Mayana' },
{ username: 'mikeorlov', name: 'Michael Orlov' },
{ username: 'nin', name: 'nz' },
{ username: 'norbipeti', name: 'NorbiPeti' },
{ username: 'ppnplus', name: 'Phongpanot Phairat' },
{ username: 'predatorix', name: 'Predatorix' },
{ username: 'robin', name: 'Robin Lahtinen' },
{ username: 'rond', name: 'rondnelly nunes' },
{ username: 'secreet', name: 'Secreet' },
{ username: 'sftblw', name: 'sftblw' },
{ username: 'sporiff', name: 'Ciarán Ainsworth' },
{ username: 'tekuteku', name: 'tekuteku' },
{ username: 'thecatjustmeow', name: 'Nguyen Huynh Hung' },
{ username: 'tmota', name: 'Tiago Mota' },
{ username: 'uranix', name: 'Michal Mauser' },
{ username: 'wakutiteo', name: 'Markel' },
{ username: 'wonderingdane', name: 'Nicolai Ireneo-Larsen' },
{ username: 'zeynepeliacik', name: 'Zeynep Can' }
]
}
function getContributorsExcludeList () {
return new Set([
'Bigard Florian',
'chocobozzz',
'Rigel',
// Requested by the contributor
'Marcel Cramm',
'Chris Sakura 佐倉くりす on Youtube',
'Chris Sakura 佐倉くりす on Youtube - 日本語は第二言語やけ、間違っとったら思いっきり叩いてくださいw つたない日本語ばっかりやけど頑張りまーす♪',
'chris@famichiki.tube'
])
}
実行可能ファイル
+154
ファイルの表示
@@ -0,0 +1,154 @@
import { readJsonSync, writeJSON } from 'fs-extra/esm'
import { join } from 'path'
import { I18N_LOCALES, USER_ROLE_LABELS } from '@peertube/peertube-core-utils'
import { root } from '@peertube/peertube-node-utils'
import {
ABUSE_STATES,
buildLanguages,
RUNNER_JOB_STATES,
USER_EXPORT_STATES,
USER_REGISTRATION_STATES,
VIDEO_CATEGORIES,
VIDEO_CHANNEL_SYNC_STATE,
VIDEO_IMPORT_STATES,
VIDEO_LICENCES,
VIDEO_PLAYLIST_PRIVACIES,
VIDEO_PLAYLIST_TYPES,
VIDEO_PRIVACIES,
USER_IMPORT_STATES,
VIDEO_STATES
} from '@peertube/peertube-server/core/initializers/constants.js'
const videojs = readJsonSync(join(root(), 'client', 'src', 'locale', 'videojs.en-US.json'))
const playerKeys = {
'Quality': 'Quality',
'Auto': 'Auto',
'Speed': 'Speed',
'Subtitles/CC': 'Subtitles/CC',
'peers': 'peers',
'peer': 'peer',
'Go to the video page': 'Go to the video page',
'Settings': 'Settings',
'Watching this video may reveal your IP address to others.': 'Watching this video may reveal your IP address to others.',
'Copy the video URL': 'Copy the video URL',
'Copy the video URL at the current time': 'Copy the video URL at the current time',
'Copy embed code': 'Copy embed code',
'Copy magnet URI': 'Copy magnet URI',
'Total downloaded: ': 'Total downloaded: ',
'Total uploaded: ': 'Total uploaded: ',
'From servers: ': 'From servers: ',
'From peers: ': 'From peers: ',
'Normal mode': 'Normal mode',
'Stats for nerds': 'Stats for nerds',
'Theater mode': 'Theater mode',
'Video UUID': 'Video UUID',
'Viewport / Frames': 'Viewport / Frames',
'Resolution': 'Resolution',
'Volume': 'Volume',
'Codecs': 'Codecs',
'Color': 'Color',
'Go back to the live': 'Go back to the live',
'Connection Speed': 'Connection Speed',
'Network Activity': 'Network Activity',
'Total Transfered': 'Total Transfered',
'Download Breakdown': 'Download Breakdown',
'Buffer Progress': 'Buffer Progress',
'Buffer State': 'Buffer State',
'Live Latency': 'Live Latency',
'P2P': 'P2P',
'{1} seconds': '{1} seconds',
'enabled': 'enabled',
'Playlist: {1}': 'Playlist: {1}',
'disabled': 'disabled',
' off': ' off',
'Player mode': 'Player mode',
'Play in loop': 'Play in loop',
'This live has not started yet.': 'This live has not started yet.',
'This live has ended.': 'This live has ended.',
'The video failed to play, will try to fast forward.': 'The video failed to play, will try to fast forward.',
'{1} / {2} dropped of {3}': '{1} / {2} dropped of {3}',
' (muted)': ' (muted)',
'{1} from servers · {2} from peers': '{1} from servers · {2} from peers',
'Previous video': 'Previous video',
'Video page (new window)': 'Video page (new window)',
'Next video': 'Next video',
'This video is password protected': 'This video is password protected',
'You need a password to watch this video.': 'You need a password to watch this video.',
'Incorrect password, please enter a correct password': 'Incorrect password, please enter a correct password',
'Cancel': 'Cancel',
'Up Next': 'Up Next',
'Autoplay is suspended': 'Autoplay is suspended',
'{1} (from edge: {2})': '{1} (from edge: {2})',
'Disable subtitles': 'Disable subtitles',
'Enable {1} subtitle': 'Enable {1} subtitle',
'{1} (auto-generated)': '{1} (auto-generated)',
'Go back': 'Go back'
}
Object.assign(playerKeys, videojs)
// Server keys
const serverKeys: any = {}
Object.values(VIDEO_CATEGORIES)
.concat(Object.values(VIDEO_LICENCES))
.concat(Object.values(VIDEO_PRIVACIES))
.concat(Object.values(VIDEO_STATES))
.concat(Object.values(VIDEO_IMPORT_STATES))
.concat(Object.values(VIDEO_PLAYLIST_PRIVACIES))
.concat(Object.values(VIDEO_PLAYLIST_TYPES))
.concat(Object.values(USER_ROLE_LABELS))
.concat(Object.values(VIDEO_CHANNEL_SYNC_STATE))
.concat(Object.values(ABUSE_STATES))
.concat(Object.values(USER_REGISTRATION_STATES))
.concat(Object.values(RUNNER_JOB_STATES))
.concat(Object.values(USER_EXPORT_STATES))
.concat(Object.values(USER_IMPORT_STATES))
.concat([
'This video does not exist.',
'We cannot fetch the video. Please try again later.',
'Sorry',
'This video is not available because the remote instance is not responding.',
'This playlist does not exist',
'We cannot fetch the playlist. Please try again later.',
'Playlist: {1}',
'By {1}',
'Unavailable video'
])
.forEach(v => { serverKeys[v] = v })
// More keys
Object.assign(serverKeys, {
Unknown: 'Unknown'
})
// ISO 639 keys
const languageKeys: any = {}
const languages = buildLanguages()
Object.keys(languages).forEach(k => { languageKeys[languages[k]] = languages[k] })
Object.assign(serverKeys, languageKeys)
writeAll().catch(err => {
console.error(err)
process.exit(-1)
})
async function writeAll () {
const localePath = join(root(), 'client', 'src', 'locale')
await writeJSON(join(localePath, 'player.en-US.json'), playerKeys, { spaces: 4 })
await writeJSON(join(localePath, 'server.en-US.json'), serverKeys, { spaces: 4 })
for (const key of Object.keys(I18N_LOCALES)) {
const playerJsonPath = join(localePath, `player.${key}.json`)
const translatedPlayer = readJsonSync(playerJsonPath)
const newTranslatedPlayer = Object.assign({}, playerKeys, translatedPlayer)
await writeJSON(playerJsonPath, newTranslatedPlayer, { spaces: 4 })
const serverJsonPath = join(localePath, `server.${key}.json`)
const translatedServer = readJsonSync(serverJsonPath)
const newTranslatedServer = Object.assign({}, serverKeys, translatedServer)
await writeJSON(serverJsonPath, newTranslatedServer, { spaces: 4 })
}
}
実行可能ファイル
+15
ファイルの表示
@@ -0,0 +1,15 @@
#!/bin/sh
set -eu
git fetch weblate && git merge weblate/develop
cd client
npm run ng -- extract-i18n --out-file src/locale/angular.xlf
# Merge new translations in other language files
node ./node_modules/.bin/xliffmerge -p ./.xliffmerge.json "ar" "is" "hr" "ca-ES" "gl-ES" "cs-CZ" "da-DK" "de-DE" "el-GR" "en-GB" "en-US" "eo" "es-ES" "eu-ES" "fa-IR" "fi-FI" "fr-FR" "gd" "gl-ES" "hu-HU" "it-IT" "ja-JP" "jbo" "kab" "ko-KR" "lt-LT" "nb-NO" "nl-NL" "oc" "pl-PL" "pt-BR" "pt-PT" "ru-RU" "sk-SK" "sl-SI" "sv-SE" "ta" "th-TH" "tr-TR" "uk-UA" "vi-VN" "zh-Hans-CN" "zh-Hant-TW" "nn" "nb-NO" "tok"
# Add our strings too
cd ../
npm run i18n:create-custom-files
実行可能ファイル
+59
ファイルの表示
@@ -0,0 +1,59 @@
#!/bin/bash
set -eu
shutdown() {
# Get our process group id
# shellcheck disable=SC2009
PGID=$(ps -o pgid= $$ | grep -o "[0-9]*")
# Kill it in a new new process group
setsid kill -- -"$PGID"
exit 0
}
trap "shutdown" SIGINT SIGTERM
today=$(date '+%F')
directory_name="peertube-nightly-$today"
tar_name="peertube-nightly-$today.tar.xz"
npm run build -- --source-map
# Clean up declaration files
find dist/ packages/core-utils/dist/ \
packages/ffmpeg/dist/ \
packages/node-utils/dist/ \
packages/models/dist/ \
\( -name '*.d.ts' -o -name '*.d.ts.map' \) -type f -delete
nightly_version="nightly-$today"
sed -i 's/"version": "\([^"]\+\)"/"version": "\1-'"$nightly_version"'"/' ./package.json
# Creating the archives
(
# local variables
directories_to_archive=("$directory_name/CREDITS.md" "$directory_name/FAQ.md" \
"$directory_name/LICENSE" "$directory_name/README.md" \
"$directory_name/packages/core-utils/dist/" "$directory_name/packages/core-utils/package.json" \
"$directory_name/packages/ffmpeg/dist/" "$directory_name/packages/ffmpeg/package.json" \
"$directory_name/packages/node-utils/dist/" "$directory_name/packages/node-utils/package.json" \
"$directory_name/packages/models/dist/" "$directory_name/packages/models/package.json" \
"$directory_name/packages/transcription/dist/" "$directory_name/packages/transcription/package.json" \
"$directory_name/client/dist/" "$directory_name/client/yarn.lock" \
"$directory_name/client/package.json" "$directory_name/config" \
"$directory_name/dist" "$directory_name/package.json" \
"$directory_name/scripts/upgrade.sh" "$directory_name/support" \
"$directory_name/yarn.lock")
# temporary setup
cd ..
ln -s "PeerTube" "$directory_name"
XZ_OPT=-e9 tar cfJ "PeerTube/$tar_name" "${directories_to_archive[@]}"
# temporary setup destruction
rm "$directory_name"
)
git checkout -- ./package.json
実行可能ファイル
+85
ファイルの表示
@@ -0,0 +1,85 @@
#!/bin/bash
# Required environment vars
# =========================
# API_LANGS
# A ':' delimited list of the client lib languages to be generated
# API_GIT_USER
# The user that will be used to push/pull from the APIs repos
# API_GIT_EMAIL
# The git email
# GIT_TOKEN
# A personal access token for github or gilab for pushing to repos
# !!!This is a secret and shouldn't be logged publicly!!!
# (Optional environment vars)
# ===========================
# API_COMMIT_MSG
# A message to use when committing to the lib repo
# API_PATH_PREFIX
# Will be used for building the URL to the repo and path to checkout.
# !!! End with a slash "/", otherwise the prefix will be tacked onto the language
# API_URL_USERNAME
# The username to use building the URL to the git repo.
# Default: API_GIT_USER
# API_REPO_HOST
# Whoever's hosting the repo e.g gitlab.com, github.com, etc.
# Default: framagit.org
# Unofficial bash strict mode
# https://web.archive.org/web/20190115051613/https://redsymbol.net/articles/unofficial-bash-strict-mode/
set -euo pipefail
IFS=$'\n\t '
# Set default values
API_URL_USERNAME="${API_URL_USERNAME:-$API_GIT_USER}"
API_PATH_PREFIX="${API_PATH_PREFIX:-}"
API_REPO_HOST=${API_REPO_HOST:-framagit.org}
echo "API_GIT_USER='${API_GIT_USER}'"
echo "API_URL_USERNAME='${API_URL_USERNAME}'"
echo "API_LANGS='${API_LANGS}'"
git config --global user.email "${API_GIT_EMAIL}"
git config --global user.name "${API_GIT_USER}"
for lang in ${API_LANGS//:/ } ; do
(
echo "Generating client API libs for $lang"
lang_dir="support/openapi/${lang}"
out_dir_prefix="dist/api/${API_PATH_PREFIX}"
out_dir="${out_dir_prefix}/${lang}"
git_repo_id="${API_PATH_PREFIX}${lang}"
host_path="${API_REPO_HOST}/${API_URL_USERNAME}/${git_repo_id}.git"
git_remote="https://${API_GIT_USER}:${GIT_TOKEN}@${host_path}"
if ! [ -e "$out_dir" ] ; then
# Make sure the prefix exists before cloning the repo
mkdir -p "${out_dir_prefix}"
git clone "https://${host_path}" "$out_dir"
fi
npx @openapitools/openapi-generator-cli generate \
-i support/doc/api/openapi.yaml \
-c "${lang_dir}/def.yaml" \
-t "${lang_dir}" \
-g "$lang" \
--skip-validate-spec \
--git-host "${API_REPO_HOST}" \
--git-user-id "${API_URL_USERNAME}" \
--git-repo-id "${git_repo_id}" \
-o "${out_dir}"
# Commit and push changes to the remote
cd "$out_dir"
git remote set-url origin "$git_remote"
# Make sure something has changed
if [[ $(git status -s | wc -l) = 0 ]] ; then
echo "No changes from previous version"
continue
fi
git add .
git commit -m "${API_COMMIT_MSG:-"Minor update $lang"}"
git push
)
done
実行可能ファイル
+11
ファイルの表示
@@ -0,0 +1,11 @@
#!/usr/bin/env bash
# Version key/value should be on his own line
PACKAGE_VERSION=$(node -p "require('./package.json').version")
sed -i "s/\(^\s*\)version: .*/\1version: $PACKAGE_VERSION/" ./support/doc/api/openapi.yaml
# Sets the package version for libs
echo "packageVersion: $PACKAGE_VERSION" >> ./support/openapi/go.yaml
echo "artifactVersion: $PACKAGE_VERSION" >> ./support/openapi/kotlin.yaml
echo "packageVersion: $PACKAGE_VERSION" >> ./support/openapi/python.yaml
実行可能ファイル
+10
ファイルの表示
@@ -0,0 +1,10 @@
#!/bin/sh
set -eu
cd client/src/standalone/embed-player-api
npm run build
npm publish --access public
rm -rf dist build node_modules
実行可能ファイル
+147
ファイルの表示
@@ -0,0 +1,147 @@
#!/bin/bash
set -eu
shutdown() {
# Get our process group id
# shellcheck disable=SC2009
PGID=$(ps -o pgid= $$ | grep -o "[0-9]*")
# Kill it in a new new process group
setsid kill -- -"$PGID"
exit 0
}
trap "shutdown" SIGINT SIGTERM
if [ -z "$1" ]; then
echo "Need version as argument"
exit -1
fi
if [ -z "$GITHUB_TOKEN" ]; then
echo "Need GITHUB_TOKEN env set."
exit -1
fi
maintainer_public_key=${MAINTAINER_GPG:-"583A612D890159BE"}
peertube_directory=$(basename $(pwd))
branch=$(git symbolic-ref --short -q HEAD)
if [ "$branch" != "develop" ] && [[ "$branch" != release/* ]]; then
echo "Need to be on develop or release branch."
exit -1
fi
yarn check --integrity --verify-tree
(cd client && yarn check --integrity --verify-tree)
version="v$1"
github_prerelease_option=""
if [[ "$version" = *"-alpha."* ]] || [[ "$version" = *"-beta."* ]] || [[ "$version" = *"-rc."* ]]; then
echo -e "This is a pre-release.\n"
github_prerelease_option="--pre-release"
fi
directory_name="peertube-$version"
zip_name="peertube-$version.zip"
tar_name="peertube-$version.tar.xz"
changelog=$(awk -v version="$version" '/## v/ { printit = $2 == version }; printit;' CHANGELOG.md | grep -v "## $version" | sed '1{/^$/d}')
printf "Changelog will be:\\n\\n%s\\n\\n" "$changelog"
read -p "Are you sure to release? " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 0
fi
(
cd client
npm version --no-git-tag-version --no-commit-hooks "$1"
)
npm version -f --no-git-tag-version --no-commit-hooks "$1"
git commit package.json client/package.json ./support/doc/api/openapi.yaml -m "Bumped to version $version"
git tag -s -a "$version" -m "$version"
npm run build -- --source-map
rm -f "./client/dist/en-US/stats.json"
rm -f "./client/dist/embed-stats.json"
# Clean up declaration files
find dist/ packages/core-utils/dist/ \
packages/ffmpeg/dist/ \
packages/node-utils/dist/ \
packages/models/dist/ \
\( -name '*.d.ts' -o -name '*.d.ts.map' \) -type f -delete
# Creating the archives
(
# local variables
directories_to_archive=("$directory_name/CREDITS.md" "$directory_name/FAQ.md" \
"$directory_name/LICENSE" "$directory_name/README.md" \
"$directory_name/packages/core-utils/dist/" "$directory_name/packages/core-utils/package.json" \
"$directory_name/packages/ffmpeg/dist/" "$directory_name/packages/ffmpeg/package.json" \
"$directory_name/packages/node-utils/dist/" "$directory_name/packages/node-utils/package.json" \
"$directory_name/packages/models/dist/" "$directory_name/packages/models/package.json" \
"$directory_name/packages/transcription/dist/" "$directory_name/packages/transcription/package.json" \
"$directory_name/client/dist/" "$directory_name/client/yarn.lock" \
"$directory_name/client/package.json" "$directory_name/config" \
"$directory_name/dist" "$directory_name/package.json" \
"$directory_name/scripts/upgrade.sh" "$directory_name/support" \
"$directory_name/yarn.lock")
# temporary setup
cd ..
ln -s "$peertube_directory" "$directory_name"
# archive creation + signing
zip -9 -r "$peertube_directory/$zip_name" "${directories_to_archive[@]}"
gpg --armor --detach-sign -u "$maintainer_public_key" "$peertube_directory/$zip_name"
XZ_OPT="-e9 -T0" tar cfJ "$peertube_directory/$tar_name" "${directories_to_archive[@]}"
gpg --armor --detach-sign -u "$maintainer_public_key" "$peertube_directory/$tar_name"
# temporary setup destruction
rm "$directory_name"
)
# Creating the release on GitHub, with the created archives
(
git push origin --tag
if [ -z "$github_prerelease_option" ]; then
github-release release --user chocobozzz --repo peertube --tag "$version" --name "$version" --description "$changelog"
else
github-release release --user chocobozzz --repo peertube --tag "$version" --name "$version" --description "$changelog" "$github_prerelease_option"
fi
# Wait for the release to be published, we had some issues when the files were not uploaded because of "unknown release" error
sleep 2
github-release upload --user chocobozzz --repo peertube --tag "$version" --name "$zip_name" --file "$zip_name"
github-release upload --user chocobozzz --repo peertube --tag "$version" --name "$zip_name.asc" --file "$zip_name.asc"
github-release upload --user chocobozzz --repo peertube --tag "$version" --name "$tar_name" --file "$tar_name"
github-release upload --user chocobozzz --repo peertube --tag "$version" --name "$tar_name.asc" --file "$tar_name.asc"
git push origin "$branch"
# Only update master if it is not a pre release
if [ -z "$github_prerelease_option" ]; then
# Update master branch
git checkout master
git merge "$branch"
git push origin master
git checkout "$branch"
# Rebuild properly the server, with the declaration files
npm run build:server
# Release types package
npm run generate-types-package "$version"
cd packages/types-generator/dist
npm publish --access public
fi
)
+9
ファイルの表示
@@ -0,0 +1,9 @@
import Bluebird from "bluebird";
import { PeerTubeServer } from "@peertube/peertube-server-commands";
module.exports = async function sendViews(options) {
const { url, videoId, viewers } = options;
const server = new PeerTubeServer({ url });
await Bluebird.map(viewers, (viewer) => {
return server.views.simulateView({ id: videoId, xForwardedFor: viewer.xForwardedFor }).catch((err) => console.error("Cannot simulate viewer", err));
}, { concurrency: 500 });
};
+17
ファイルの表示
@@ -0,0 +1,17 @@
import Bluebird from 'bluebird'
import { PeerTubeServer } from '@peertube/peertube-server-commands'
module.exports = async function sendViews (options: {
url: string
videoId: number
viewers: { xForwardedFor: string }[]
}) {
const { url, videoId, viewers } = options
const server = new PeerTubeServer({ url })
await Bluebird.map(viewers, viewer => {
return server.views.simulateView({ id: videoId, xForwardedFor: viewer.xForwardedFor })
.catch(err => console.error('Cannot simulate viewer', err))
}, { concurrency: 500 })
}
+116
ファイルの表示
@@ -0,0 +1,116 @@
import { wait } from '@peertube/peertube-core-utils'
import {
createSingleServer,
doubleFollow,
killallServers,
PeerTubeServer,
setAccessTokensToServers,
waitJobs
} from '@peertube/peertube-server-commands'
import { dirname, join } from 'path'
import { Piscina } from 'piscina'
import { fileURLToPath } from 'url'
import { isMainThread } from 'worker_threads'
const THOUSAND_VIEWERS = 2
const TOTAL_THREADS = 20
let servers: PeerTubeServer[]
const viewers: { xForwardedFor: string }[] = []
let videoId: string
let pool: Piscina
if (isMainThread) {
run()
.then(() => process.exit(0))
.catch(err => console.error(err))
.finally(() => killallServers(servers))
}
// ---------------------------------------------------------------------------
async function run () {
await prepare()
while (true) {
await runViewers()
}
}
async function prepare () {
pool = new Piscina({
filename: join(dirname(fileURLToPath(import.meta.url)), 'simulate-many-viewers-worker.js'),
minThreads: 20,
maxThreads: 20
})
console.log('Preparing servers...')
const config = {
log: {
level: 'info',
log_http_requests: false
},
rates_limit: {
api: {
max: 5_000_000
}
},
views: {
videos: {
local_buffer_update_interval: '30 minutes',
view_expiration: '1 hour'
}
}
}
const env = { PRODUCTION_CONSTANTS: 'true' }
servers = await Promise.all([
createSingleServer(1, config, { env, nodeArgs: [ '--inspect' ] }),
createSingleServer(2, config, { env }),
createSingleServer(3, config, { env })
])
await setAccessTokensToServers(servers)
await doubleFollow(servers[0], servers[1])
await doubleFollow(servers[0], servers[2])
const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
videoId = uuid
await waitJobs(servers)
for (let i = 2; i < 252; i++) {
for (let j = 2; j < 6; j++) {
for (let k = 2; k < THOUSAND_VIEWERS + 2; k++) {
viewers.push({ xForwardedFor: `0.${k}.${j}.${i},127.0.0.1` })
}
}
}
console.log('Servers preparation finished.')
}
async function runViewers () {
console.log('Will run views of %d viewers.', viewers.length)
const before = new Date().getTime()
const promises: Promise<any>[] = []
for (let i = 0; i < TOTAL_THREADS; i++) {
const start = i * THOUSAND_VIEWERS * 1000 / TOTAL_THREADS
const end = (i + 1) * THOUSAND_VIEWERS * 1000 / TOTAL_THREADS
console.log(`Sending viewers ${start} to ${end}`)
promises.push(pool.run({ url: servers[0].url, viewers: viewers.slice(start, end), videoId }))
}
await Promise.all(promises)
console.log('Finished to run views in %d seconds.', (new Date().getTime() - before) / 1000)
await wait(5000)
}
実行可能ファイル
+15
ファイルの表示
@@ -0,0 +1,15 @@
#!/bin/sh
set -eu
npm run ci -- types
npm run ci -- client
npm run ci -- cli-plugin
npm run ci -- api-1
npm run ci -- api-2
npm run ci -- api-3
npm run ci -- api-4
npm run ci -- api-5
npm run ci -- external-plugins
npm run ci -- lint
+16
ファイルの表示
@@ -0,0 +1,16 @@
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"outDir": "../dist/scripts",
"paths": {
"@server/*": [ "../server/core/*" ]
}
},
"references": [
{ "path": "../packages/core-utils" },
{ "path": "../packages/models" },
{ "path": "../packages/node-utils" },
{ "path": "../packages/server-commands" },
{ "path": "../server" }
]
}
実行可能ファイル
+8
ファイルの表示
@@ -0,0 +1,8 @@
#!/bin/sh
set -eu
# Backward path compatibility now upgrade.sh is in dist/scripts since v6
/bin/sh ../dist/scripts/upgrade.sh ${1:-/var/www/peertube}