As we no longer need to update each time yt-dlp updates, we going to use simver
This commit is contained in:
parent
8a3673bc07
commit
f50708852a
9 changed files with 230 additions and 103 deletions
107
.github/scripts/generate_changelog.py
vendored
Normal file
107
.github/scripts/generate_changelog.py
vendored
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
from datetime import UTC, datetime
|
||||
|
||||
try:
|
||||
import git # type: ignore
|
||||
except ImportError:
|
||||
print("Please install GitPython: pip install GitPython", file=sys.stderr) # noqa: T201
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def get_sorted_tags(repo):
|
||||
"""Returns all tags sorted by their commit date (newest first)."""
|
||||
return sorted(repo.tags, key=lambda t: t.commit.committed_datetime, reverse=True)
|
||||
|
||||
|
||||
def get_commits_between(repo, start, end):
|
||||
"""Return commits between two refs (no merges)."""
|
||||
return list(repo.iter_commits(f"{start}..{end}", no_merges=True))
|
||||
|
||||
|
||||
def generate_changelog(repo_path, changelog_path):
|
||||
repo = git.Repo(repo_path)
|
||||
tags = get_sorted_tags(repo)
|
||||
changelog = []
|
||||
|
||||
if not tags:
|
||||
start = repo.commit(repo.git.rev_list("--max-parents=0", "HEAD"))
|
||||
commits = get_commits_between(repo, start.hexsha, "HEAD")
|
||||
changelog.append(
|
||||
{
|
||||
"tag": "Initial Release",
|
||||
"date": datetime.now(UTC).isoformat(),
|
||||
"commits": [
|
||||
{
|
||||
"sha": c.hexsha[:8],
|
||||
"full_sha": c.hexsha,
|
||||
"message": c.message.strip(),
|
||||
"author": c.author.name,
|
||||
"date": c.committed_datetime.astimezone(UTC).isoformat(),
|
||||
}
|
||||
for c in commits
|
||||
],
|
||||
}
|
||||
)
|
||||
else:
|
||||
for i in range(len(tags) - 1):
|
||||
newer, older = tags[i], tags[i + 1]
|
||||
commits = get_commits_between(repo, older.commit.hexsha, newer.commit.hexsha)
|
||||
if not commits:
|
||||
continue
|
||||
changelog.append(
|
||||
{
|
||||
"tag": newer.name,
|
||||
"full_sha": newer.commit.hexsha,
|
||||
"date": newer.commit.committed_datetime.astimezone(UTC).isoformat(),
|
||||
"commits": [
|
||||
{
|
||||
"sha": c.hexsha[:8],
|
||||
"full_sha": c.hexsha,
|
||||
"message": c.message.strip(),
|
||||
"author": c.author.name,
|
||||
"date": c.committed_datetime.astimezone(UTC).isoformat(),
|
||||
}
|
||||
for c in commits
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
# Add HEAD -> latest tag if ahead
|
||||
head = repo.head.commit
|
||||
if head.hexsha != tags[0].commit.hexsha:
|
||||
commits = get_commits_between(repo, tags[0].commit.hexsha, head.hexsha)
|
||||
if commits:
|
||||
changelog.insert(
|
||||
0,
|
||||
{
|
||||
"tag": f"Unreleased ({head.hexsha[:8]})",
|
||||
"full_sha": head.hexsha,
|
||||
"date": head.committed_datetime.astimezone(UTC).isoformat(),
|
||||
"commits": [
|
||||
{
|
||||
"sha": c.hexsha[:8],
|
||||
"full_sha": c.hexsha,
|
||||
"message": c.message.strip(),
|
||||
"author": c.author.name,
|
||||
"date": c.committed_datetime.astimezone(UTC).isoformat(),
|
||||
}
|
||||
for c in commits
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
with open(changelog_path, "w", encoding="utf-8") as f:
|
||||
json.dump(changelog, f, indent=2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Generate CHANGELOG.json from Git tags.")
|
||||
parser.add_argument("--repo_path", "-p", default=".", help="Path to git repo")
|
||||
parser.add_argument("--changelog_path", "-f", default="CHANGELOG.json", help="Output file path")
|
||||
args = parser.parse_args()
|
||||
|
||||
generate_changelog(args.repo_path, args.changelog_path)
|
||||
93
.github/workflows/main.yml
vendored
93
.github/workflows/main.yml
vendored
|
|
@ -22,16 +22,13 @@ on:
|
|||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
create_release:
|
||||
description: "Create Release (requires build)"
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
- master
|
||||
tags:
|
||||
- "v*"
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
- ".github/**"
|
||||
|
|
@ -96,11 +93,13 @@ jobs:
|
|||
packages: write
|
||||
contents: write
|
||||
env:
|
||||
PLATFORMS: ${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && 'linux/amd64,linux/arm64' || 'linux/amd64' }}
|
||||
PLATFORMS: ${{ startsWith(github.ref, 'refs/tags/v') && 'linux/amd64,linux/arm64' || 'linux/amd64' }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
|
@ -120,13 +119,30 @@ jobs:
|
|||
pnpm install --production --prefer-offline --frozen-lockfile
|
||||
pnpm run generate
|
||||
|
||||
- name: Update Version File
|
||||
uses: ArabCoders/write-version-to-file@master
|
||||
with:
|
||||
filename: "/app/library/version.py"
|
||||
placeholder: "dev-master"
|
||||
with_date: "true"
|
||||
with_branch: "true"
|
||||
- name: Install GitPython
|
||||
run: pip install gitpython
|
||||
|
||||
- name: Generate CHANGELOG.json
|
||||
run: |
|
||||
python3 .github/scripts/generate_changelog.py -p . -f ./ui/exported/CHANGELOG.json
|
||||
|
||||
- name: Update app/library/version.py
|
||||
run: |
|
||||
VERSION="${GITHUB_REF##*/}"
|
||||
SHA=$(git rev-parse HEAD)
|
||||
DATE=$(date -u +"%Y%m%d")
|
||||
|
||||
echo "Current version: ${VERSION}, SHA: ${SHA}, Date: ${DATE}"
|
||||
|
||||
echo "APP_VERSION=${VERSION}" >> $"$GITHUB_ENV"
|
||||
echo "APP_SHA=${SHA}" >> "$GITHUB_ENV"
|
||||
echo "APP_DATE=${DATE}" >> "$GITHUB_ENV"
|
||||
|
||||
sed -i \
|
||||
-e "s/^APP_VERSION = \".*\"/APP_VERSION = \"${VERSION}\"/" \
|
||||
-e "s/^APP_COMMIT_SHA = \".*\"/APP_COMMIT_SHA = \"${SHA}\"/" \
|
||||
-e "s/^APP_BUILD_DATE = \".*\"/APP_BUILD_DATE = \"${DATE}\"/" \
|
||||
app/library/version.py
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
|
@ -142,10 +158,9 @@ jobs:
|
|||
${{ env.DOCKERHUB_SLUG }}
|
||||
${{ env.GHCR_SLUG }}
|
||||
tags: |
|
||||
type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}
|
||||
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/v') }}
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
type=raw,value={{branch}}{{base_ref}}-{{date 'YYYYMMDD'}}-{{sha}}
|
||||
flavor: |
|
||||
latest=false
|
||||
|
||||
|
|
@ -173,13 +188,49 @@ jobs:
|
|||
cache-from: type=gha, scope=${{ github.workflow }}
|
||||
cache-to: type=gha, mode=max, scope=${{ github.workflow }}
|
||||
|
||||
- name: Version tag
|
||||
uses: arabcoders/action-python-autotagger@master
|
||||
- name: Overwrite GitHub release notes
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
repo_name: arabcoders/ytptube
|
||||
path: app/library/version.py
|
||||
regex: 'APP_VERSION\s=\s\"(.+)\"'
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const tag = context.ref.replace('refs/tags/', '');
|
||||
|
||||
const latestRelease = await github.rest.repos.listReleases({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
});
|
||||
|
||||
const release = latestRelease.data.find(r => r.tag_name === tag);
|
||||
if (!release) {
|
||||
core.setFailed(`Release with tag ${tag} not found`);
|
||||
return;
|
||||
}
|
||||
|
||||
const { data: commits } = await github.rest.repos.compareCommits({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
base: latestRelease.data[1]?.tag_name || '', // fallback to second latest tag
|
||||
head: tag,
|
||||
});
|
||||
|
||||
const changelog = commits.commits.map(
|
||||
c => `- ${c.sha.substring(0, 7)} ${c.commit.message.split('\n')[0]} by ${c.commit.author.name}`
|
||||
).join('\n');
|
||||
|
||||
if (!changelog) {
|
||||
core.setFailed('No commits found for the changelog');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Changelog for ${tag}:\n${changelog}`);
|
||||
|
||||
await github.rest.repos.updateRelease({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
release_id: release.id,
|
||||
body: changelog
|
||||
});
|
||||
|
||||
dockerhub-sync-readme:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,6 +1,7 @@
|
|||
# compiled output
|
||||
/frontend/dist
|
||||
/ui/dist
|
||||
/ui/exported/CHANGELOG.json
|
||||
|
||||
# dependencies
|
||||
**/node_modules/*
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import coloredlogs
|
|||
from dotenv import load_dotenv
|
||||
|
||||
from .Utils import FileLogFormatter, arg_converter
|
||||
from .version import APP_VERSION
|
||||
from .version import APP_BUILD_DATE, APP_COMMIT_SHA, APP_VERSION
|
||||
|
||||
|
||||
class Config:
|
||||
|
|
@ -113,12 +113,18 @@ class Config:
|
|||
version: str = APP_VERSION
|
||||
"The version of the application."
|
||||
|
||||
app_version: str = APP_VERSION
|
||||
"The version of the application, same as `version`."
|
||||
|
||||
app_commit_sha: str = APP_COMMIT_SHA
|
||||
"The commit SHA of the application."
|
||||
|
||||
app_build_date: str = APP_BUILD_DATE
|
||||
"The build date of the application."
|
||||
|
||||
__instance = None
|
||||
"The instance of the class."
|
||||
|
||||
new_version_available: bool = False
|
||||
"A new version of the application is available."
|
||||
|
||||
started: int = 0
|
||||
"The time the application was started."
|
||||
|
||||
|
|
@ -188,11 +194,13 @@ class Config:
|
|||
"version",
|
||||
"__instance",
|
||||
"ytdl_options",
|
||||
"new_version_available",
|
||||
"started",
|
||||
"ytdlp_cli",
|
||||
"_ytdlp_cli_mutable",
|
||||
"is_native",
|
||||
"app_version",
|
||||
"app_commit_sha",
|
||||
"app_build_date",
|
||||
)
|
||||
"The variables that are immutable."
|
||||
|
||||
|
|
@ -246,6 +254,9 @@ class Config:
|
|||
"is_native",
|
||||
"app_env",
|
||||
"tasks_handler_timer",
|
||||
"app_version",
|
||||
"app_commit_sha",
|
||||
"app_build_date",
|
||||
)
|
||||
"The variables that are relevant to the frontend."
|
||||
|
||||
|
|
@ -441,9 +452,6 @@ class Config:
|
|||
)
|
||||
raise ValueError(msg)
|
||||
|
||||
if self.version == "dev-master":
|
||||
self._version_via_git()
|
||||
|
||||
def _get_attributes(self) -> dict:
|
||||
attrs: dict = {}
|
||||
vClass: str = self.__class__
|
||||
|
|
@ -511,59 +519,3 @@ class Config:
|
|||
return YTDLP_VERSION
|
||||
except ImportError:
|
||||
return "0.0.0"
|
||||
|
||||
def _version_via_git(self):
|
||||
"""
|
||||
Updates the version of the application using git tags.
|
||||
This is used to set the version to the latest git tag.
|
||||
"""
|
||||
git_path: Path = Path(__file__).parent / ".." / ".." / ".git"
|
||||
if not git_path.exists():
|
||||
logging.info(f"Git directory '{git_path}' does not exist. Cannot determine version.")
|
||||
return
|
||||
|
||||
try:
|
||||
import subprocess
|
||||
|
||||
branch_result = subprocess.run( # noqa: S603
|
||||
["git", "rev-parse", "--abbrev-ref", "HEAD"], # noqa: S607
|
||||
cwd=git_path.parent,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
|
||||
if 0 != branch_result.returncode:
|
||||
logging.error(f"Git rev-parse failed: {branch_result.stderr.strip()}")
|
||||
return
|
||||
|
||||
branch_name: str = branch_result.stdout.strip()
|
||||
if not branch_name:
|
||||
logging.warning("Git branch name is empty.")
|
||||
return
|
||||
|
||||
commit_result = subprocess.run( # noqa: S603
|
||||
["git", "log", "-1", "--format=%ct_%H"], # noqa: S607
|
||||
cwd=git_path.parent,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
|
||||
if 0 != commit_result.returncode:
|
||||
logging.error(f"Git log failed: {commit_result.stderr.strip()}")
|
||||
return
|
||||
|
||||
commit_info: str = commit_result.stdout.strip()
|
||||
if not commit_info:
|
||||
logging.warning("Git commit info is empty.")
|
||||
return
|
||||
|
||||
commit_date, commit_sha = commit_info.split("_", 1)
|
||||
commit_date = time.strftime("%Y%m%d", time.localtime(int(commit_date)))
|
||||
commit_sha = commit_sha[:8]
|
||||
|
||||
self.version = f"{branch_name}-{commit_date}-{commit_sha}"
|
||||
logging.info(f"Application version set to '{self.version}' based on git data.")
|
||||
except Exception as e:
|
||||
logging.error(f"Error while getting git version: {e!s}")
|
||||
|
|
|
|||
|
|
@ -5,3 +5,9 @@ This file is updated by the CI/CD pipeline, do not edit it manually.
|
|||
|
||||
APP_VERSION = "dev-master"
|
||||
"Application version"
|
||||
|
||||
APP_COMMIT_SHA = "unknown"
|
||||
"Commit SHA of the application"
|
||||
|
||||
APP_BUILD_DATE = "unknown"
|
||||
"Build date of the application"
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ class Main:
|
|||
|
||||
def started(_):
|
||||
LOG.info("=" * 40)
|
||||
LOG.info(f"YTPTube v{self._config.version} - started on http://{host}:{port}{self._config.base_path}")
|
||||
LOG.info(f"YTPTube {self._config.version} - started on http://{host}:{port}{self._config.base_path}")
|
||||
LOG.info("=" * 40)
|
||||
if cb:
|
||||
cb()
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@
|
|||
|
||||
<div>
|
||||
<Settings v-if="show_settings" :isLoading="loadingImage" @reload_bg="() => loadImage(true)" />
|
||||
<NuxtLoadingIndicator />
|
||||
<NuxtPage />
|
||||
</div>
|
||||
|
||||
|
|
@ -114,7 +115,9 @@
|
|||
<div class="column is-8-mobile">
|
||||
<div class="has-text-left" v-if="config.app?.version">
|
||||
© {{ Year }} - <NuxtLink href="https://github.com/ArabCoders/ytptube" target="_blank">YTPTube</NuxtLink>
|
||||
<span class="is-hidden-mobile"> ({{ config?.app?.version || 'unknown' }})</span>
|
||||
<span class="is-hidden-mobile"
|
||||
v-tooltip="`Build Date: ${config.app?.app_build_date}, commit: ${config.app?.app_commit_sha}`">
|
||||
({{ config?.app?.version || 'unknown' }})</span>
|
||||
- <NuxtLink target="_blank" href="https://github.com/yt-dlp/yt-dlp">yt-dlp</NuxtLink>
|
||||
<span class="is-hidden-mobile"> ({{ config?.app?.ytdlp_version || 'unknown' }})</span>
|
||||
- <NuxtLink :to="`/changelog?version=${config?.app?.version || 'unknown'}`">CHANGELOG</NuxtLink>
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
<div class="content p-0 m-0">
|
||||
<h1 class="is-4">
|
||||
<span class="icon"><i class="fas fa-code-branch" /></span>
|
||||
{{ formatTag(log) }} <span class="tag has-text-success" v-if="isInstalled(log)">Installed</span>
|
||||
{{ log.tag }} <span class="tag has-text-success" v-if="isInstalled(log)">Installed</span>
|
||||
</h1>
|
||||
<hr>
|
||||
<ul>
|
||||
|
|
@ -61,7 +61,7 @@ useHead({ title: 'CHANGELOG' })
|
|||
|
||||
const PROJECT = 'ytptube'
|
||||
const REPO = `https://github.com/arabcoders/${PROJECT}`
|
||||
const REPO_URL = `https://arabcoders.github.io/${PROJECT}/CHANGELOG-{branch}.json?version={version}`
|
||||
const REPO_URL = `https://arabcoders.github.io/${PROJECT}/CHANGELOG.json?version={version}`
|
||||
|
||||
const logs = ref([])
|
||||
const api_version = ref('')
|
||||
|
|
@ -73,18 +73,6 @@ const branch = computed(() => {
|
|||
return ['master', 'dev'].includes(branch) ? branch : 'master'
|
||||
})
|
||||
|
||||
const formatTag = log => {
|
||||
const parts = log.tag.split('-')
|
||||
if (parts.length < 3) {
|
||||
return log.tag
|
||||
}
|
||||
|
||||
const branch = parts[0]
|
||||
const date = parts[1]
|
||||
const shortSha = log.full_sha.substring(0, hashLength.value)
|
||||
return `${ucFirst(branch)}: ${moment(date, 'YYYYMMDD').format('YYYY-MM-DD')} - ${shortSha}`
|
||||
}
|
||||
|
||||
watch(() => config.app.version, async value => {
|
||||
if (!value) {
|
||||
return
|
||||
|
|
@ -104,8 +92,24 @@ const loadContent = async () => {
|
|||
|
||||
isLoading.value = true
|
||||
try {
|
||||
const changes = await fetch(REPO_URL.replace('{branch}', branch.value).replace('{version}', api_version.value))
|
||||
logs.value = await changes.json()
|
||||
try{
|
||||
logs.value = await (await request(uri('/CHANGELOG.json'), { method: 'GET' })).json()
|
||||
}catch(e){
|
||||
console.error(e)
|
||||
const changes = await fetch(REPO_URL.replace('{branch}', branch.value).replace('{version}', api_version.value))
|
||||
logs.value = await changes.json()
|
||||
}
|
||||
await nextTick()
|
||||
|
||||
logs.value = logs.value.slice(0, 10).map(log => {
|
||||
log.commits = log.commits.map(commit => {
|
||||
commit.full_sha = commit.sha.padEnd(hashLength.value, '0')
|
||||
return commit
|
||||
})
|
||||
log.full_sha = log.tag.padEnd(hashLength.value, '0')
|
||||
return log
|
||||
})
|
||||
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
toast.error('error', 'Error', `Failed to fetch changelog. ${e.message}`)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ const CONFIG_KEYS = {
|
|||
ytdlp_cli: '',
|
||||
file_logging: false,
|
||||
is_native: false,
|
||||
app_version: '',
|
||||
app_commit_sha: '',
|
||||
app_build_date: '',
|
||||
},
|
||||
presets: [
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue