├── .editorconfig
├── .github
├── plugin-repo-labels.yaml
├── release-drafter.adoc
├── release-drafter.yml
├── renovate.json
└── workflows
│ ├── build.yaml
│ ├── bump-version.yaml
│ ├── changelog.yaml
│ ├── command-dispatch.yaml
│ ├── command-rebase.yaml
│ ├── publish-unstable.yaml
│ ├── publish.yaml
│ ├── scan-codeql.yaml
│ ├── sync-labels.yaml
│ └── test.yaml
├── .gitignore
├── .gitmodules
├── README.md
├── build_all.sh
├── build_plugin.sh
├── show_drafts.sh
├── show_issues.sh
├── show_pullrequests.sh
└── update_submodules.py
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: https://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | [*]
7 | indent_style = space
8 | indent_size = 4
9 | end_of_line = lf
10 | charset = utf-8
11 | trim_trailing_whitespace = true
12 | insert_final_newline = true
13 |
14 | [*.{yaml,yml,json}]
15 | tab_width = 2
16 | indent_size = 2
17 |
--------------------------------------------------------------------------------
/.github/plugin-repo-labels.yaml:
--------------------------------------------------------------------------------
1 | # A central configuration of labels that should get propagated across all repos with a label-sync workflow
2 |
3 | # General Purpose Labels
4 | #
5 | # Labels applicable for the general development workflow
6 | - name: major-feature
7 | color: '003F00'
8 | description: This PR introduces a major new feature
9 | aliases:
10 | - major-feature
11 | - major-enhancement
12 |
13 | - name: major-bug
14 | color: 'FF1E0D'
15 | description: This PR fixes a major bug
16 |
17 | - name: deprecated
18 | color: 'FEC111'
19 | description: This PR marks a feature, function or other public API element as deprecated
20 |
21 | - name: removed
22 | color: 'd93f0b'
23 | description: This PR removes a feature, function or other public API element
24 |
25 | - name: reverted
26 | color: 'f05032'
27 | description: This PR reverts a commit or multiple commits
28 | aliases:
29 | - revert
30 |
31 | - name: breaking
32 | color: 'B60205'
33 | description: This PR introduces breaking changes
34 |
35 | - name: feature
36 | color: '164916'
37 | description: This PR or Issue requests or introduces a new feature
38 | aliases:
39 | - feature
40 | - enhancement
41 |
42 | - name: bug
43 | color: 'd73a4a'
44 | description: This PR or Issue describes or fixes something that isn't working
45 | aliases:
46 | - bug
47 | - fix
48 | - bugfix
49 | - regression
50 |
51 | - name: documentation
52 | color: '006699'
53 | description: This PR or Issue aims to improve or add to documentation
54 |
55 | - name: tests
56 | color: '25A162'
57 | description: This PR adds or imposes tests (e.g. coverage, quality, ...)
58 | aliases:
59 | - test
60 | - tests
61 |
62 |
63 | # Repository Maintenance Labels
64 | #
65 | # Labels used for PRs and Issues relevant for repo maintenance
66 | - name: wontfix
67 | color: 'a2eeef'
68 | description: This Issue contains a request or 'bug' that wont be fixed (e.g. out-of-scope, not-an-issue, ...)
69 |
70 | - name: duplicate
71 | color: 'cfd3d7'
72 | description: This Issue or PR is a duplicate of an existing Issue or PR
73 |
74 | - name: help wanted
75 | color: '008672'
76 | description: This Issue or PR requires extra attention and/or requires external help
77 | aliases:
78 | - help wanted
79 | - help-wanted
80 |
81 | - name: good first issue
82 | color: '7057ff'
83 | description: This Issue contains a requirement easy to be picked up by project newcomers
84 | aliases:
85 | - good first issue
86 | - good-first-issue
87 |
88 | - name: confirmed
89 | color: 'a5e569'
90 | description: This Issue describes a bug that has been confirmed by a org member
91 |
92 | - name: invalid
93 | color: 'e4e669'
94 | description: This Issue describes an invalid request or bug report
95 |
96 | - name: question
97 | color: 'd876e3'
98 | description: This Issue contains a question
99 |
100 | - name: blocked
101 | color: '8e0900'
102 | description: This PR is blocked due to a commented reason
103 |
104 | - name: chore
105 | color: '36566F'
106 | description: This PR contains repository maintenance changes
107 |
108 | - name: dependencies
109 | color: '1D76DB'
110 | description: This PR updates or changes a dependency file
111 | aliases:
112 | - dependency
113 | - dependencies
114 |
115 | - name: github-actions
116 | color: '000000'
117 | description: This PR updates or changes GH Actions used in this repo
118 | aliases:
119 | - github_actions
120 |
121 | - name: nuget
122 | color: '004880'
123 | description: This PR updates or changes some NuGet dependencies
124 |
125 | - name: ci
126 | color: 'FFFF09'
127 | description: This PR updates or changes something CI related
128 | aliases:
129 | - ci
130 | - build
131 |
132 | - name: release-prep
133 | color: 'e0e0e0'
134 | description: This PR is a meta PR to prepare for the next release
135 |
136 | # Release Drafter Labels
137 | #
138 | # these labels are used to control certain features of Release Drafter
139 | - name: skip-changelog
140 | color: 'e0e0e0'
141 | description: This PR gets ignored by the Release Drafter workflow
142 |
--------------------------------------------------------------------------------
/.github/release-drafter.adoc:
--------------------------------------------------------------------------------
1 | [[release-drafter]]
2 | = Release Drafter
3 | :toc:
4 | :toc-placement: preamble
5 | :toclevels: 3
6 |
7 | link:https://github.com/toolmantim/release-drafter[Release Drafter] is a tool and GitHub app which helps to automate the management of releases notes.
8 | This tool generates changelog drafts using pull request metadata (commit headers, links, etc.) and then suggest a changelog draft in GitHub Releases.
9 |
10 | This page provides information about how to use it.
11 |
12 | == Usage
13 |
14 | Despite the availability of Release Drafter as a GitHub app it is preferred to use the GitHub Action approach.
15 | The reason behind this is that the GitHub app does not produce any logs which would be available to plugin maintainers,
16 | and hence make it more difficult to troubleshoot errors if they occur.
17 |
18 | === Enabling Release Drafter GitHub Action in a Repository
19 |
20 | Have a look to the sample configuration available in the link:https://github.com/jellyfin/jellyfin-plugin-ldapauth/blob/master/.github/workflows/update-release-draft.yml[LDAP-Auth Plugin].
21 |
22 | === Configuring Release Drafter
23 |
24 | After enabling RD, it needs to be configured in `.github/release-drafter.yml` in the master branch of your repository.
25 | The Jellyfin project provides a link:./release-drafter.yml[Global Configuration file], so a minimal configuration looks like this one:
26 |
27 | [source,yml]
28 | ----
29 | _extends: jellyfin-meta-plugins
30 | #OPTIONAL: if your plugin uses a more suphisticated versioning update this acordingly
31 | # name-template: Version $NEXT_MINOR_VERSION
32 | # tag-template: v$NEXT_MAJOR_VERSION
33 | # version-template: $MAJOR
34 |
35 | #FIXME: overwrite the template so that the you dont have to manually update the download links
36 | # when releasing (see the example in the LDAP-Auth plugin mentioned above)
37 | # template: |
38 | #
39 | #
40 | #
41 | # ## :sparkles: What's New
42 | #
43 | # $CHANGES
44 | ----
45 |
46 | All global settings can be overridden in repositories.
47 | Or you can write your own configuration from scratch if needed.
48 | See the link:https://github.com/toolmantim/release-drafter/blob/master/README.md[Release Drafter Documentation] for guidelines.
49 | If a change you need is a common use-case for Jellyfin, it is recommended to submit a pull request to the link:./release-drafter.yml[Global Configuration file]
50 |
51 | ==== Global Configuration Notes
52 |
53 | There are some considerations about the default configuration:
54 |
55 | * Jellyfin plugins can use different versioning formats.
56 | Release Drafter defaults to link:https://semver.org/[semver], but the majority of Jellyfin plugins use only the major version number.
57 | We use it as a default in the global configuration, but it can be overridden (e.g. `version-template: $MAJOR.$MINOR.$PATCH`)
58 | * Next version number will be used by default as a next release name.
59 | Another naming template can be defined by a `name-template` property. (e.g. `name-template: My Plugin v$NEXT_PATCH_VERSION`)
60 | * The `tag-template` is the template for the tag of the draft release,
61 | if you create a tag according to this template before releasing the draft it will be pre-selected for the release.
62 | It also is templated in as the release tag if you creat a release from the draft manually, but can be overwritten. (e.g. `v$NEXT_PATCH_VERSION`)
63 | * Finally, the `template` property itself represents the Markdown body of the GitHub Release.
64 | It has a default value provided by the template found within this repo, but should bew overwritten based on this template to include a download link.
65 | (if you are unsure of what this means have a look at a plugin already using it e.g. link:https://github.com/jellyfin/jellyfin-plugin-ldapauth/blob/master/.github/release-drafter.yml[LDAP-Auth Plugin])
66 |
67 | === Releasing a Plugin with Release Drafter
68 |
69 | 1. Make sure that all pull requests in the release are properly labeled.
70 | See the link:./release-drafter.yml[Global Configuration file] for available labels
71 | 2. (optional) crate a git tag locally and push it to your plugin repo
72 | 3. Go to `${YOUR_REPO}/releases` and click "Edit" on the draft release.
73 | 4. Edit the tag, point it to a tag or a release commit created by the common release flow
74 | ** Tags represent a text field with auto-completion. Tag names can be also copy-pasted from `${YOUR_REPO}/tags`
75 | ** Recent commits can be selected from a dropdown
76 | ** (optional) if you pushed a tag manually you should see the text *Existing tag*
77 | 5. Edit the release name, if needed
78 | 6. Review and copy-edit the changelog
79 | ** First release draft will likely contain all history from the beginning of the repository,
80 | you will need to remove entries corresponding to PRs included in prior releases.
81 | If all new PRs are categorized, just delete everything before the first header.
82 | ** Release drafter is designed to add one entry per pull request.
83 | If a pull request includes multiple changes to be noted, manual editing will be needed
84 | 7. Click the _Publish_ button
85 |
86 | == Links
87 |
88 | * link:https://github.com/toolmantim/release-drafter/blob/master/README.md[Release Drafter Documentation]
89 | * link:https://github.com/jenkinsci/.github/blob/master/.github/release-drafter.adoc[Reference used for this Readme]
--------------------------------------------------------------------------------
/.github/release-drafter.yml:
--------------------------------------------------------------------------------
1 | # Configuration for Release Drafter: https://github.com/toolmantim/release-drafter
2 | name-template: 'Version $NEXT_MAJOR_VERSION'
3 | # Most plugins within the Jellyfin Org uses a single-digit versioning. Can be replaced by semver: $MAJOR.$MINOR.$PATCH
4 | # https://github.com/release-drafter/release-drafter#next-version-variables
5 | tag-template: 'v$NEXT_MAJOR_VERSION'
6 | version-template: '$MAJOR'
7 | category-template: '### $TITLE'
8 |
9 | # Emoji reference: https://gitmoji.carloscuesta.me/
10 | categories:
11 | - title: ':boom: Breaking changes'
12 | labels:
13 | - breaking
14 | - title: ':fire: Removed'
15 | labels:
16 | - removed
17 | - title: ':rewind: Reverted Changes'
18 | labels:
19 | - revert
20 | - reverted
21 | - title: ':rocket: Major features and improvements'
22 | labels:
23 | - major-enhancement
24 | - major-feature
25 | - title: ':ambulance: Major bug fixes'
26 | labels:
27 | - major-bug
28 | - title: ':wastebasket:️ Deprecated'
29 | label: deprecated
30 | - title: ':tada: New features and improvements'
31 | labels:
32 | - enhancement
33 | - feature
34 | - title: ':bug: Bug Fixes'
35 | labels:
36 | - bug
37 | - fix
38 | - bugfix
39 | - regression
40 | - title: ':white_check_mark: Tests'
41 | labels:
42 | - test
43 | - tests
44 | - title: ':gear: Code or Repo Maintenance'
45 | labels:
46 | - chore
47 | - cleanup
48 | - title: ':memo: Documentation updates'
49 | labels:
50 | - documentation
51 | - title: ':arrow_up: Dependency updates'
52 | labels:
53 | - dependencies # Default label used by Dependabot
54 | - dependency
55 | - title: ':construction_worker: CI & build changes'
56 | labels:
57 | - ci
58 | - build
59 | exclude-labels:
60 | - no-changelog
61 | - skip-changelog
62 | - invalid
63 |
64 | autolabeler:
65 | - label: ci
66 | files:
67 | - '.github/workflows/*'
68 | - '.github/dependabot.yml'
69 | branch:
70 | - '/ci\/.+/'
71 | - label: documentation
72 | files:
73 | - '*.md'
74 | branch:
75 | - '/docs?\/.+/'
76 | - label: bug
77 | branch:
78 | - '/fix\/.+/'
79 | title:
80 | - '/fix/i'
81 | - label: chore
82 | branch:
83 | - '/chore\/.+/'
84 | title:
85 | - '/chore/i'
86 | - label: feature
87 | branch:
88 | - '/feature\/.+/'
89 |
90 | template: |-
91 |
92 |
93 |
94 | ## :sparkles: What's New
95 |
96 | $CHANGES
97 |
98 |
--------------------------------------------------------------------------------
/.github/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "github>jellyfin/.github//renovate-presets/default",
5 | ":dependencyDashboard"
6 | ],
7 | "packageRules": [
8 | {
9 | "description": "Auto update the Git submodules of this repository and auto merge the branches",
10 | "matchManagers": ["git-submodules"],
11 | "addLabels": ["git-submodules"],
12 | "automerge": true,
13 | "ignoreTests": true,
14 | "automergeType": "branch"
15 | }
16 | ],
17 | "git-submodules": {
18 | "enabled": true
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.github/workflows/build.yaml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 | inputs:
4 | dotnet-version:
5 | required: false
6 | default: "8.0.x"
7 | description: "The .NET version to setup for the build"
8 | type: string
9 | dotnet-target:
10 | required: false
11 | default: "net8.0"
12 | description: "The .NET target to set for JPRM"
13 | type: string
14 |
15 | jobs:
16 | build:
17 | runs-on: ubuntu-latest
18 | steps:
19 | - name: Checkout Repository
20 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
21 |
22 | - name: Setup .NET
23 | uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0
24 | with:
25 | dotnet-version: "${{ inputs.dotnet-version }}"
26 |
27 | - name: Build Jellyfin Plugin
28 | uses: oddstr13/jellyfin-plugin-repository-manager@9497a0a499416cc572ed2e07a391d9f943a37b4d # v1.1.1
29 | id: jprm
30 | with:
31 | dotnet-target: "${{ inputs.dotnet-target }}"
32 |
33 | - name: Upload Artifact
34 | uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4
35 | with:
36 | name: build-artifact
37 | retention-days: 30
38 | if-no-files-found: error
39 | path: ${{ steps.jprm.outputs.artifact }}
40 |
--------------------------------------------------------------------------------
/.github/workflows/bump-version.yaml:
--------------------------------------------------------------------------------
1 | # DEPRECATED: Please use / rely on the changelog workflow as that works with protected branches
2 |
3 | on:
4 | workflow_call:
5 | inputs:
6 | csproj-name:
7 | required: true
8 | type: string
9 | csproj-folder:
10 | required: false
11 | type: string
12 | is-unstable:
13 | required: false
14 | default: false
15 | type: boolean
16 | default-branch:
17 | required: false
18 | default: "master"
19 | description: "The branch to commit the version bump to"
20 | type: string
21 | commiter-name:
22 | required: false
23 | default: "jellyfin-bot"
24 | description: "This param overwrites the version bump committing git user.name"
25 | type: string
26 | commiter-email:
27 | required: false
28 | default: "team@jellyfin.org"
29 | description: "This param overwrites the version bump committing git user.email"
30 | type: string
31 |
32 |
33 | jobs:
34 | bump-version:
35 | runs-on: ubuntu-latest
36 | if: ${{ ! inputs.isUnstable }}
37 | steps:
38 | - name: Checkout Repository
39 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
40 |
41 | - name: Read current version
42 | run: |-
43 | echo "CURRENT_VERSION=$(yq eval '.version' build.yaml)"
44 | echo "CURRENT_VERSION=$(yq eval '.version' build.yaml)" >> $GITHUB_ENV
45 |
46 | - name: Set next version
47 | run: |-
48 | # ensure even a version in schema 'x.y.z.b' is supported, yet only inc and persists the 'x' value further
49 | C_VERSION=${CURRENT_VERSION%%.*}
50 | CS_PROJ_NAME="${{ inputs.csproj-name }}"
51 | CS_PROJ_FOLDER="${{ inputs.csproj-folder }}"
52 |
53 | export NEXT_VERSION=$(( ${C_VERSION} + 1 ))
54 | echo "NEXT_VERSION=${NEXT_VERSION}"
55 | echo "NEXT_VERSION=${NEXT_VERSION}" >> $GITHUB_ENV
56 |
57 | yq eval '.version = env(NEXT_VERSION)' -i build.yaml
58 | sed -i ${CS_PROJ_FOLDER:-$CS_PROJ_NAME}/${CS_PROJ_NAME}.csproj \
59 | -e "s;.*;${NEXT_VERSION}.0.0.0;" \
60 | -e "s;.*;${NEXT_VERSION}.0.0.0;"
61 |
62 | - name: Commit bump
63 | run: |-
64 | git config user.name "${{ inputs.commiter-name }}"
65 | git config user.email "${{ inputs.commiter-email }}"
66 | git commit -am "chore: prepare for next release (v${NEXT_VERSION})"
67 | git push origin "HEAD:refs/heads/${{ inputs.default-branch }}"
68 |
--------------------------------------------------------------------------------
/.github/workflows/changelog.yaml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 | inputs:
4 | repository-name:
5 | required: true
6 | type: string
7 | commiter-name:
8 | required: false
9 | default: "jellyfin-bot"
10 | description: "This param overwrites the version bump committing git user.name"
11 | type: string
12 | commiter-email:
13 | required: false
14 | default: "team@jellyfin.org"
15 | description: "This param overwrites the version bump committing git user.email"
16 | type: string
17 | secrets:
18 | token:
19 | required: true
20 |
21 | jobs:
22 | update_release_draft:
23 | runs-on: ubuntu-latest
24 | if: ${{ github.repository == inputs.repository-name }}
25 |
26 | steps:
27 | # Drafts your next Release notes as Pull Requests are merged into "master"
28 | - name: Update Draft
29 | uses: release-drafter/release-drafter@3f0f87098bd6b5c5b9a36d49c41d998ea58f9348 # v6.0.0
30 | id: draft
31 | env:
32 | GITHUB_TOKEN: ${{ secrets.token }}
33 |
34 | - name: Set-up Environment
35 | run: |-
36 | TAG="${{ steps.draft.outputs.tag_name }}"
37 | echo "VERSION=${TAG#v}" >> $GITHUB_ENV
38 | cat << EOF | grep -P '^([*-] |###)' > cl.md
39 | ${{ steps.draft.outputs.body }}
40 | EOF
41 | sed -i -r 's/^(#+) (:.*:)? *(.*)$/\n\1 \3 \1/' cl.md
42 | sed -i -r 's/^\*/-/' cl.md
43 | echo "CHANGELOG<> $GITHUB_ENV
44 | cat cl.md >> $GITHUB_ENV
45 | echo "EOF" >> $GITHUB_ENV
46 | echo "HAS_CHANGES=$(grep -qie 'No changes$' cl.md && echo false || echo true)" >> $GITHUB_ENV
47 | rm cl.md
48 | echo "ABI_VERSION=$(curl -s https://api.jellyfin.org/openapi/jellyfin-openapi-stable.json | jq -r '.info.version').0" >> $GITHUB_ENV
49 |
50 | - name: Checkout Repository
51 | if: ${{ env.HAS_CHANGES == 'true' }}
52 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
53 |
54 | - name: Update build.yaml
55 | if: ${{ env.HAS_CHANGES == 'true' }}
56 | run: |-
57 | if [[ -f Directory.Build.props ]]; then
58 | # https://stackoverflow.com/a/57510475
59 | # https://docs.microsoft.com/en-us/visualstudio/msbuild/customize-your-build?view=vs-2022
60 | sed -i Directory.Build.props \
61 | -e "s;.*;${VERSION}.0.0.0;" \
62 | -e "s;.*;${VERSION}.0.0.0;" \
63 | -e "s;.*;${VERSION}.0.0.0;"
64 | fi
65 |
66 | yq eval '.version = env(VERSION) | .targetAbi = env(ABI_VERSION) | .changelog = strenv(CHANGELOG) | .changelog style="literal"' -i build.yaml
67 |
68 | - name: Commit Changes
69 | if: ${{ env.HAS_CHANGES == 'true' }}
70 | run: |-
71 | git config user.name "${{ inputs.commiter-name }}"
72 | git config user.email "${{ inputs.commiter-email }}"
73 | git checkout -b prepare-${{ env.VERSION }}
74 | git commit -am "Bump version to ${{ env.VERSION }}"
75 | git push -f origin prepare-${{ env.VERSION }}
76 |
77 | - name: Create or Update PR
78 | if: ${{ env.HAS_CHANGES == 'true' }}
79 | uses: k3rnels-actions/pr-update@7d7d8852095b87e6fa255ced7433f1d79737e0b1 # v2.1.0
80 | with:
81 | token: ${{ secrets.token }}
82 | pr_title: Prepare for release ${{ steps.draft.outputs.tag_name }}
83 | pr_source: prepare-${{ env.VERSION }}
84 | pr_labels: 'release-prep,skip-changelog'
85 | pr_body: |-
86 | :robot: This is a generated PR to update version and changelog in `build.yaml`.
87 | ---
88 | ${{ env.CHANGELOG }}
89 |
--------------------------------------------------------------------------------
/.github/workflows/command-dispatch.yaml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 | secrets:
4 | token:
5 | required: true
6 |
7 | jobs:
8 | launcher:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Command Dispatch
12 | uses: peter-evans/slash-command-dispatch@13bc09769d122a64f75aa5037256f6f2d78be8c4 # v4.0.0
13 | with:
14 | token: ${{ secrets.token }}
15 | reaction-token: ${{ secrets.token }}
16 | permission: write
17 | issue-type: pull-request
18 | commands: |-
19 | rebase
20 | update-prep
21 |
--------------------------------------------------------------------------------
/.github/workflows/command-rebase.yaml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 | inputs:
4 | rebase-head:
5 | required: true
6 | type: string
7 | repository-full-name:
8 | required: true
9 | type: string
10 | comment-id:
11 | required: true
12 | type: string
13 | secrets:
14 | token:
15 | required: true
16 |
17 | jobs:
18 | rebase:
19 | runs-on: ubuntu-latest
20 | steps:
21 | - name: Rebase PR
22 | uses: peter-evans/rebase@87c3fd9344792e51ab1c7494c3369620c84ed852 # v3.1.0
23 | id: rebase
24 | with:
25 | head: ${{ inputs.rebase-head }}
26 |
27 | - name: Add Success Reaction
28 | if: ${{ steps.rebase.outputs.rebased-count == 1 }}
29 | uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
30 | with:
31 | token: ${{ secrets.token }}
32 | repository: ${{ inputs.repository-full-name }}
33 | comment-id: ${{ inputs.comment-id }}
34 | reaction-type: hooray
35 |
36 | - name: Add Failure Reaction
37 | if: ${{ steps.rebase.outputs.rebased-count == 0 || failure() }}
38 | uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
39 | with:
40 | token: ${{ secrets.token }}
41 | repository: ${{ inputs.repository-full-name }}
42 | comment-id: ${{ inputs.comment-id }}
43 | reaction-type: confused, -1
44 |
--------------------------------------------------------------------------------
/.github/workflows/publish-unstable.yaml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 | inputs:
4 | dotnet-version:
5 | required: false
6 | default: "9.0.x"
7 | description: "The .NET version to setup for the build"
8 | type: string
9 | dotnet-target:
10 | required: false
11 | default: "net9.0"
12 | description: "The .NET target to set for JPRM"
13 | type: string
14 | secrets:
15 | deploy-host:
16 | required: true
17 | deploy-user:
18 | required: true
19 | deploy-key:
20 | required: true
21 | token:
22 | required: true
23 |
24 | jobs:
25 | build:
26 | runs-on: ubuntu-latest
27 | steps:
28 | - name: Checkout Repository
29 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
30 | with:
31 | ref: 'unstable'
32 |
33 | - name: Setup .NET
34 | uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0
35 | with:
36 | dotnet-version: "${{ inputs.dotnet-version }}"
37 |
38 | - name: Update prerelease dependencies
39 | id: unstable
40 | run: |
41 | dotnet nuget add source --username jellyfin-bot --password ${{ secrets.token }} --store-password-in-clear-text --name jellyfin-pre "https://nuget.pkg.github.com/jellyfin/index.json"
42 | dotnet tool install --global dotnet-outdated-tool
43 | dotnet outdated -pre Always -u -inc Jellyfin
44 |
45 | - name: Generate version number using date and run number
46 | id: version-creator
47 | run: |
48 | pluginVersion=`yq '.version' build.yaml | tr -d '"'`
49 | buildDay=`date +%y%m`
50 | runNum=$GITHUB_RUN_NUMBER
51 | ver="${pluginVersion}.${buildDay}.${runNum}.0"
52 | echo "PLUGIN_VERSION=$ver" >> $GITHUB_OUTPUT
53 |
54 | - name: Build Jellyfin Plugin
55 | uses: oddstr13/jellyfin-plugin-repository-manager@9497a0a499416cc572ed2e07a391d9f943a37b4d # v1.1.1
56 | id: jprm
57 | with:
58 | dotnet-target: "${{ inputs.dotnet-target }}"
59 | version: ${{ steps.version-creator.outputs.PLUGIN_VERSION }}
60 |
61 | - name: Upload Artifact
62 | uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
63 | with:
64 | name: build-artifact
65 | retention-days: 30
66 | if-no-files-found: error
67 | path: ${{ steps.jprm.outputs.artifact }}
68 |
69 | upload:
70 | needs:
71 | - build
72 | runs-on: ubuntu-latest
73 | steps:
74 | - name: Download Artifact
75 | uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
76 | with:
77 | name: build-artifact
78 |
79 | - name: Ensure Destination Path Exists
80 | uses: appleboy/ssh-action@7eaf76671a0d7eec5d98ee897acda4f968735a17 # v1.2.0
81 | if: ${{ contains(github.repository, 'jellyfin/') }}
82 | with:
83 | host: ${{ secrets.deploy-host }}
84 | username: ${{ secrets.deploy-user }}
85 | key: ${{ secrets.deploy-key }}
86 | script_stop: true
87 | script: |-
88 | mkdir -p "/srv/incoming/plugin/${{ github.repository }}/${{ inputs.version }}" || exit 1
89 |
90 | - name: Upload Jellyfin Plugin Repository Assets
91 | uses: burnett01/rsync-deployments@0dc935cdecc5f5e571865e60d2a6cdc673704823 # tag=5.2
92 | if: ${{ contains(github.repository, 'jellyfin/') }}
93 | with:
94 | switches: -vrptz
95 | path: ./*.zip
96 | remote_path: /srv/incoming/plugin/${{ github.repository }}/${{ inputs.version }}
97 | remote_host: ${{ secrets.deploy-host }}
98 | remote_user: ${{ secrets.deploy-user }}
99 | remote_key: ${{ secrets.deploy-key }}
100 |
101 | publish:
102 | needs:
103 | - upload
104 | runs-on: ubuntu-latest
105 | if: ${{ contains(github.repository, 'jellyfin/') }}
106 | env:
107 | JELLYFIN_REPO: "/srv/repository/main/plugin-unstable/manifest.json"
108 | JELLYFIN_REPO_URL: "https://repo.jellyfin.org/files/plugin-unstable/"
109 | steps:
110 | - name: Update Plugin Manifest
111 | uses: appleboy/ssh-action@7eaf76671a0d7eec5d98ee897acda4f968735a17 # v1.2.0
112 | with:
113 | host: ${{ secrets.deploy-host }}
114 | username: ${{ secrets.deploy-user }}
115 | key: ${{ secrets.deploy-key }}
116 | script_stop: true
117 | envs: JELLYFIN_REPO,JELLYFIN_REPO_URL
118 | script: |-
119 | lockfile="/run/lock/jprm.lock"
120 | pushd "/srv/incoming/plugin/${{ github.repository }}/${{ inputs.version }}" || exit 1
121 | (
122 | flock -x 300
123 | sudo /usr/local/bin/jprm --verbosity=debug repo add --url="${JELLYFIN_REPO_URL}" "${JELLYFIN_REPO}" ./*.zip || exit 1
124 | ) 300>${lockfile}
125 | popd || exit 1
126 | rm -r "/srv/incoming/plugin/${{ github.repository }}/${{ inputs.version }}" || exit 1
127 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yaml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 | inputs:
4 | version:
5 | required: true
6 | type: string
7 | is-unstable:
8 | required: false
9 | default: false
10 | type: boolean
11 | dotnet-version:
12 | required: false
13 | default: "8.0.x"
14 | description: "The .NET version to setup for the build"
15 | type: string
16 | dotnet-target:
17 | required: false
18 | default: "net8.0"
19 | description: "The .NET target to set for JPRM"
20 | type: string
21 | secrets:
22 | deploy-host:
23 | required: true
24 | deploy-user:
25 | required: true
26 | deploy-key:
27 | required: true
28 |
29 |
30 | jobs:
31 | build:
32 | runs-on: ubuntu-latest
33 | steps:
34 | - name: Checkout Repository
35 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
36 |
37 | - name: Setup .NET
38 | uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0
39 | with:
40 | dotnet-version: "${{ inputs.dotnet-version }}"
41 |
42 | - name: Build Jellyfin Plugin
43 | uses: oddstr13/jellyfin-plugin-repository-manager@9497a0a499416cc572ed2e07a391d9f943a37b4d # v1.1.1
44 | id: jprm
45 | with:
46 | dotnet-target: "${{ inputs.dotnet-target }}"
47 |
48 | - name: Upload Artifact
49 | uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
50 | with:
51 | name: build-artifact
52 | retention-days: 30
53 | if-no-files-found: error
54 | path: ${{ steps.jprm.outputs.artifact }}
55 |
56 | upload:
57 | needs:
58 | - build
59 | runs-on: ubuntu-latest
60 | steps:
61 | - name: Download Artifact
62 | uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
63 | with:
64 | name: build-artifact
65 |
66 | - name: Prepare GH Release Assets
67 | run: |-
68 | for file in ./*; do
69 | md5sum ${file#./} >> ${file%.*}.md5
70 | sha256sum ${file#./} >> ${file%.*}.sha256
71 | done
72 | ls -l
73 |
74 | - name: Upload GH Release Assets
75 | uses: shogo82148/actions-upload-release-asset@8482bd769644976d847e96fb4b9354228885e7b4 # v1.7.8
76 | with:
77 | upload_url: ${{ github.event.release.upload_url }}
78 | asset_path: ./*
79 |
80 | - name: Ensure Destination Path Exists
81 | uses: appleboy/ssh-action@7eaf76671a0d7eec5d98ee897acda4f968735a17 # v1.2.0
82 | if: ${{ contains(github.repository, 'jellyfin/') }}
83 | with:
84 | host: ${{ secrets.deploy-host }}
85 | username: ${{ secrets.deploy-user }}
86 | key: ${{ secrets.deploy-key }}
87 | script_stop: true
88 | script: |-
89 | mkdir -p "/srv/incoming/plugin/${{ github.repository }}/${{ inputs.version }}" || exit 1
90 |
91 | - name: Upload Jellyfin Plugin Repository Assets
92 | uses: burnett01/rsync-deployments@0dc935cdecc5f5e571865e60d2a6cdc673704823 # tag=5.2
93 | if: ${{ contains(github.repository, 'jellyfin/') }}
94 | with:
95 | switches: -vrptz
96 | path: ./*.zip
97 | remote_path: /srv/incoming/plugin/${{ github.repository }}/${{ inputs.version }}
98 | remote_host: ${{ secrets.deploy-host }}
99 | remote_user: ${{ secrets.deploy-user }}
100 | remote_key: ${{ secrets.deploy-key }}
101 |
102 | publish:
103 | needs:
104 | - upload
105 | runs-on: ubuntu-latest
106 | if: ${{ contains(github.repository, 'jellyfin/') }}
107 | env:
108 | JELLYFIN_REPO: "/srv/repository/main/plugin/manifest.json"
109 | JELLYFIN_REPO_URL: "https://repo.jellyfin.org/files/plugin/"
110 | steps:
111 | - name: Update Plugin Manifest
112 | uses: appleboy/ssh-action@7eaf76671a0d7eec5d98ee897acda4f968735a17 # v1.2.0
113 | with:
114 | host: ${{ secrets.deploy-host }}
115 | username: ${{ secrets.deploy-user }}
116 | key: ${{ secrets.deploy-key }}
117 | script_stop: true
118 | envs: JELLYFIN_REPO,JELLYFIN_REPO_URL
119 | script: |-
120 | lockfile="/run/lock/jprm.lock"
121 | pushd "/srv/incoming/plugin/${{ github.repository }}/${{ inputs.version }}" || exit 1
122 | (
123 | flock -x 300
124 | sudo /usr/local/bin/jprm --verbosity=debug repo add --url="${JELLYFIN_REPO_URL}" "${JELLYFIN_REPO}" ./*.zip || exit 1
125 | ) 300>${lockfile}
126 | popd || exit 1
127 | rm -r "/srv/incoming/plugin/${{ github.repository }}/${{ inputs.version }}" || exit 1
128 |
--------------------------------------------------------------------------------
/.github/workflows/scan-codeql.yaml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 | inputs:
4 | repository-name:
5 | required: true
6 | type: string
7 | dotnet-version:
8 | required: false
9 | default: "8.0.x"
10 | description: "The .NET version to setup for the build"
11 | type: string
12 |
13 | jobs:
14 | analyze:
15 | name: Analyze
16 | runs-on: ubuntu-latest
17 | if: ${{ github.repository == inputs.repository-name }}
18 |
19 | strategy:
20 | fail-fast: false
21 | matrix:
22 | language: [ 'csharp' ]
23 |
24 | steps:
25 | - name: Checkout repository
26 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
27 |
28 | - name: Setup .NET
29 | uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0
30 | with:
31 | dotnet-version: "${{ inputs.dotnet-version }}"
32 |
33 | - name: Initialize CodeQL
34 | uses: github/codeql-action/init@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1
35 | with:
36 | languages: ${{ matrix.language }}
37 | queries: +security-and-quality
38 |
39 | - name: Autobuild
40 | uses: github/codeql-action/autobuild@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1
41 |
42 | - name: Perform CodeQL Analysis
43 | uses: github/codeql-action/analyze@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1
44 |
--------------------------------------------------------------------------------
/.github/workflows/sync-labels.yaml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 | secrets:
4 | token:
5 | required: true
6 |
7 | jobs:
8 | labels:
9 | runs-on: ubuntu-latest
10 |
11 | steps:
12 | - uses: EndBug/label-sync@52074158190acb45f3077f9099fea818aa43f97a # v2.3.3
13 | with:
14 | config-file: https://raw.githubusercontent.com/jellyfin/jellyfin-meta-plugins/master/.github/plugin-repo-labels.yaml
15 | delete-other-labels: true
16 | token: ${{ secrets.token }}
17 |
--------------------------------------------------------------------------------
/.github/workflows/test.yaml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_call:
3 | inputs:
4 | dotnet-version:
5 | required: false
6 | default: "8.0.x"
7 | description: "The .NET version to setup for the build"
8 | type: string
9 |
10 | jobs:
11 | test:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Checkout Repository
15 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
16 |
17 | - name: Setup .NET
18 | uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0
19 | with:
20 | dotnet-version: "${{ inputs.dotnet-version }}"
21 |
22 | - name: Install dependencies
23 | run: dotnet restore
24 |
25 | - name: Build
26 | run: dotnet build --configuration Release --no-restore
27 |
28 | - name: Test
29 | run: dotnet test --no-restore --verbosity normal
30 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | artifacts/
2 | test_repo/
3 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "jellyfin-plugin-template"]
2 | path = jellyfin-plugin-template
3 | url = https://github.com/jellyfin/jellyfin-plugin-template
4 | [submodule "jellyfin-plugin-trakt"]
5 | path = jellyfin-plugin-trakt
6 | url = https://github.com/jellyfin/jellyfin-plugin-trakt
7 | [submodule "jellyfin-plugin-ldapauth"]
8 | path = jellyfin-plugin-ldapauth
9 | url = https://github.com/jellyfin/jellyfin-plugin-ldapauth
10 | [submodule "jellyfin-plugin-reports"]
11 | path = jellyfin-plugin-reports
12 | url = https://github.com/jellyfin/jellyfin-plugin-reports
13 | [submodule "jellyfin-plugin-bookshelf"]
14 | path = jellyfin-plugin-bookshelf
15 | url = https://github.com/jellyfin/jellyfin-plugin-bookshelf
16 | [submodule "jellyfin-plugin-opensubtitles"]
17 | path = jellyfin-plugin-opensubtitles
18 | url = https://github.com/jellyfin/jellyfin-plugin-opensubtitles
19 | [submodule "jellyfin-plugin-tvheadend"]
20 | path = jellyfin-plugin-tvheadend
21 | url = https://github.com/jellyfin/jellyfin-plugin-tvheadend
22 | [submodule "jellyfin-plugin-playbackreporting"]
23 | path = jellyfin-plugin-playbackreporting
24 | url = https://github.com/jellyfin/jellyfin-plugin-playbackreporting
25 | [submodule "jellyfin-plugin-tmdbboxsets"]
26 | path = jellyfin-plugin-tmdbboxsets
27 | url = https://github.com/jellyfin/jellyfin-plugin-tmdbboxsets
28 | [submodule "jellyfin-plugin-fanart"]
29 | path = jellyfin-plugin-fanart
30 | url = https://github.com/jellyfin/jellyfin-plugin-fanart
31 | [submodule "jellyfin-plugin-nextpvr"]
32 | path = jellyfin-plugin-nextpvr
33 | url = https://github.com/jellyfin/jellyfin-plugin-nextpvr
34 | [submodule "jellyfin-plugin-kodisyncqueue"]
35 | path = jellyfin-plugin-kodisyncqueue
36 | url = https://github.com/jellyfin/jellyfin-plugin-kodisyncqueue
37 | [submodule "jellyfin-plugin-artwork"]
38 | path = jellyfin-plugin-artwork
39 | url = https://github.com/jellyfin/jellyfin-plugin-artwork.git
40 | branch = master
41 | [submodule "jellyfin-plugin-anisearch"]
42 | path = jellyfin-plugin-anisearch
43 | url = https://github.com/jellyfin/jellyfin-plugin-anisearch.git
44 | branch = master
45 | [submodule "jellyfin-plugin-anilist"]
46 | path = jellyfin-plugin-anilist
47 | url = https://github.com/jellyfin/jellyfin-plugin-anilist.git
48 | branch = master
49 | [submodule "jellyfin-plugin-anidb"]
50 | path = jellyfin-plugin-anidb
51 | url = https://github.com/jellyfin/jellyfin-plugin-anidb.git
52 | branch = master
53 | [submodule "jellyfin-plugin-kitsu"]
54 | path = jellyfin-plugin-kitsu
55 | url = https://github.com/jellyfin/jellyfin-plugin-kitsu.git
56 | branch = master
57 | [submodule "jellyfin-plugin-tvmaze"]
58 | path = jellyfin-plugin-tvmaze
59 | url = https://github.com/jellyfin/jellyfin-plugin-tvmaze.git
60 | branch = master
61 | [submodule "jellyfin-plugin-tvdb"]
62 | path = jellyfin-plugin-tvdb
63 | url = https://github.com/jellyfin/jellyfin-plugin-tvdb.git
64 | branch = master
65 | [submodule "jellyfin-plugin-coverartarchive"]
66 | path = jellyfin-plugin-coverartarchive
67 | url = https://github.com/jellyfin/jellyfin-plugin-coverartarchive.git
68 | branch = master
69 | [submodule "jellyfin-plugin-webhook"]
70 | path = jellyfin-plugin-webhook
71 | url = https://github.com/jellyfin/jellyfin-plugin-webhook.git
72 | branch = master
73 | [submodule "jellyfin-plugin-opds"]
74 | path = jellyfin-plugin-opds
75 | url = https://github.com/jellyfin/jellyfin-plugin-opds.git
76 | branch = master
77 | [submodule "jellyfin-plugin-sessioncleaner"]
78 | path = jellyfin-plugin-sessioncleaner
79 | url = https://github.com/jellyfin/jellyfin-plugin-sessioncleaner.git
80 | branch = master
81 | [submodule "jellyfin-plugin-imvdb"]
82 | path = jellyfin-plugin-imvdb
83 | url = https://github.com/jellyfin/jellyfin-plugin-imvdb.git
84 | branch = master
85 | [submodule "jellyfin-plugin-simkl"]
86 | path = jellyfin-plugin-simkl
87 | url = https://github.com/jellyfin/jellyfin-plugin-simkl.git
88 | branch = master
89 | [submodule "jellyfin-plugin-vgmdb"]
90 | path = jellyfin-plugin-vgmdb
91 | url = https://github.com/jellyfin/jellyfin-plugin-vgmdb.git
92 | branch = master
93 | [submodule "jellyfin-plugin-discogs"]
94 | path = jellyfin-plugin-discogs
95 | url = https://github.com/jellyfin/jellyfin-plugin-discogs.git
96 | branch = master
97 | [submodule "jellyfin-plugin-dlna"]
98 | path = jellyfin-plugin-dlna
99 | url = https://github.com/jellyfin/jellyfin-plugin-dlna.git
100 | branch = master
101 | [submodule "jellyfin-plugin-subtitleextract"]
102 | path = jellyfin-plugin-subtitleextract
103 | url = https://github.com/jellyfin/jellyfin-plugin-subtitleextract.git
104 | branch = master
105 | [submodule "jellyfin-plugin-intros"]
106 | path = jellyfin-plugin-intros
107 | url = https://github.com/jellyfin/jellyfin-plugin-intros.git
108 | branch = master
109 | [submodule "jellyfin-plugin-transcodekiller"]
110 | path = jellyfin-plugin-transcodekiller
111 | url = https://github.com/jellyfin/jellyfin-plugin-transcodekiller.git
112 | branch = master
113 | [submodule "jellyfin-plugin-chapter-segments"]
114 | path = jellyfin-plugin-chapter-segments
115 | url = https://github.com/jellyfin/jellyfin-plugin-chapter-segments.git
116 | branch = master
117 | [submodule "jellyfin-plugin-lrclib"]
118 | path = jellyfin-plugin-lrclib
119 | url = https://github.com/jellyfin/jellyfin-plugin-lrclib.git
120 | branch = master
121 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Plugin tools
2 | ============
3 |
4 | Dependencies
5 | ------------
6 |
7 | - [hub](https://hub.github.com/)
8 | - [jprm](https://pypi.org/project/jprm/) (building)
9 | - dotnet (building)
10 | - git
11 | - bash
12 | - python3
13 |
14 | Tools
15 | -----
16 |
17 | - `build_all.sh`
18 | Builds (and publishes) all plugins.
19 | - `build_plugin.sh`
20 | Builds (and publishes) a single plugin.
21 | - `show_drafts.sh`
22 | Lists draft releases prepared by release-drafter.
23 | - `show_issues.sh`
24 | Lists all open issues on the plugin repositories.
25 | - `show_pullrequests.sh`
26 | Lists all open pull-requests on the plugin repositories.
27 | - `update_submodules.py`
28 | Updates sub-modules, adds new plugins from the org, and removes archived/moved ones.
29 |
--------------------------------------------------------------------------------
/build_all.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #set -x
3 | MY=$(dirname $(realpath -s "${0}"))
4 |
5 | export ARTIFACT_DIR="${MY}/artifacts"
6 | mkdir -p "${ARTIFACT_DIR}"
7 |
8 | DEFAULT_REPO_DIR="${MY}/test_repo"
9 | DEFAULT_REPO_URL="http://localhost:8080"
10 |
11 | export JELLYFIN_REPO=${JELLYFIN_REPO:-$DEFAULT_REPO_DIR}
12 | export JELLYFIN_REPO_URL=${JELLYFIN_REPO_URL:-$DEFAULT_REPO_URL}
13 |
14 | export VERSION_SUFFIX=$(date -u +%y%m.%d%H.%M%S)
15 |
16 | FAILED=()
17 |
18 | for plugin in $(find . -maxdepth 1 -mindepth 1 -type d -name 'jellyfin-plugin-*' | sort); do
19 | name=$(basename $plugin)
20 | if [ "$name" = "jellyfin-plugin-meta" ]; then
21 | continue
22 | fi
23 | pushd $plugin > /dev/null
24 | echo -e "\n##### ${name} #####"
25 |
26 | bash $MY/build_plugin.sh || {
27 | FAILED+=("$name")
28 | }
29 |
30 | popd > /dev/null
31 | done
32 |
33 | if [ ! ${#FAILED[@]} -eq 0 ]; then
34 | echo -e "\n\nThe following plugins failed to compile:" > /dev/stderr
35 | for plugin in "${FAILED[@]}"; do
36 | echo " - $plugin" > /dev/stderr
37 | done
38 |
39 | exit 1
40 | fi
41 |
--------------------------------------------------------------------------------
/build_plugin.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Copyright (c) 2020 - Odd Strabo
4 | #
5 | #
6 | # The Unlicense
7 | # =============
8 | #
9 | # This is free and unencumbered software released into the public domain.
10 | #
11 | # Anyone is free to copy, modify, publish, use, compile, sell, or
12 | # distribute this software, either in source code form or as a compiled
13 | # binary, for any purpose, commercial or non-commercial, and by any
14 | # means.
15 | #
16 | # In jurisdictions that recognize copyright laws, the author or authors
17 | # of this software dedicate any and all copyright interest in the
18 | # software to the public domain. We make this dedication for the benefit
19 | # of the public at large and to the detriment of our heirs and
20 | # successors. We intend this dedication to be an overt act of
21 | # relinquishment in perpetuity of all present and future rights to this
22 | # software under copyright law.
23 | #
24 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
27 | # IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
28 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
29 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
30 | # OTHER DEALINGS IN THE SOFTWARE.
31 | #
32 | # For more information, please refer to
33 | #
34 |
35 | MY=$(dirname $(realpath -s "${0}"))
36 | JPRM="jprm"
37 |
38 | DEFAULT_REPO_DIR="${MY}/test_repo"
39 | DEFAULT_REPO_URL="http://localhost:8080"
40 |
41 | PLUGIN=${1:-${PLUGIN:-.}}
42 |
43 | ARTIFACT_DIR=${ARTIFACT_DIR:-"${MY}/artifacts"}
44 | mkdir -p "${ARTIFACT_DIR}"
45 |
46 | JELLYFIN_REPO=${JELLYFIN_REPO:-${DEFAULT_REPO_DIR}}
47 | JELLYFIN_REPO_URL=${JELLYFIN_REPO_URL:-${DEFAULT_REPO_URL}}
48 |
49 | # Each segment of the version is a 16bit number.
50 | # Max number is 65535.
51 | VERSION_SUFFIX=${VERSION_SUFFIX:-$(date -u +%y%m.%d%H.%M%S)}
52 |
53 | meta_version=$(grep -Po '^ *version: * "*\K[^"$]+' "${PLUGIN}/build.yaml")
54 | VERSION=${VERSION:-$(echo $meta_version | sed 's/\.[0-9]*\.[0-9]*\.[0-9]*$/.'"$VERSION_SUFFIX"'/')}
55 |
56 | # !!! VERSION IS OVERWRITTEN HERE
57 | #VERSION="${meta_version}"
58 |
59 | find "${PLUGIN}" -name project.assets.json -exec rm -v '{}' ';'
60 |
61 | zipfile=$($JPRM --verbosity=debug plugin build "${PLUGIN}" --output="${ARTIFACT_DIR}" --version="${VERSION}") && {
62 | $JPRM --verbosity=debug repo add --url=${JELLYFIN_REPO_URL} "${JELLYFIN_REPO}" "${zipfile}"
63 | }
64 | exit $?
65 |
--------------------------------------------------------------------------------
/show_drafts.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | rstrip_ver() {
4 | if [ -z "$1" ]; then
5 | grep -Po "^.*?(?=(\.0\.0\.0|\.0\.0|\.0)?$)"
6 | else
7 | echo $1 | grep -Po "^.*?(?=(\.0\.0\.0|\.0\.0|\.0)?$)"
8 | fi
9 | }
10 |
11 | esc=$(printf '\033')
12 | colorize_changelog() {
13 | #1 pr number
14 | #2 list char
15 | #3 pr submitter
16 | sed -r -e "s/\\((#[0-9]+)\)/(${esc}[32m\1${esc}[0m)/g" \
17 | -e "s/^\s*[*+-]\s*/ ${esc}[1;30m-${esc}[0m /g" \
18 | -e "s/@([^ ]+)$/${esc}[1;30m@${esc}[0;36m\1${esc}[0m/gi"
19 | }
20 |
21 |
22 | IFS=$'\n'
23 | for name in $(git submodule foreach --quiet 'basename $PWD'); do
24 | pushd $name > /dev/null
25 | draft="$(hub release --include-drafts -L2 -f 'SOF:%S%n%T%n%t%n%U%n%b%nEOF%n' --color=always | sed -n -e '/SOF:draft/,/EOF/p' | sed -e '1d' -e '$d')"
26 |
27 | if [ ! -z "$draft" ]; then
28 | IFS=$'\n' parts=(${draft})
29 |
30 | tag="${parts[0]}"
31 | title="${parts[1]}"
32 | url="${parts[2]}"
33 | IFS=$'\n' description="${parts[*]:3}"
34 |
35 | echo
36 | echo -e "\e[1m$name\e[0m: $title\n \e[34m$url\e[0m"
37 |
38 | changes=$(echo "$description" | grep -Po '^\s*\K\*.*$' )
39 |
40 | meta_version=$(grep -Po "version: ?[\"']?\K.*(?=[\"']$)" build.yaml | rstrip_ver)
41 | draft_version=$(echo $tag | grep -Po 'v\K.*' | rstrip_ver)
42 |
43 | if [ "$meta_version" != "$draft_version" ]; then
44 | echo -e " \e[1;31mVersion bump needed!"
45 | echo -e " \e[0;31mDraft is for v\e[0m\e[1m$draft_version\e[0;31m, but build.yaml specifies v\e[0m\e[1m$meta_version\e[0m"
46 | fi
47 |
48 | echo "$changes" | colorize_changelog
49 | fi
50 | popd > /dev/null
51 | done
52 |
--------------------------------------------------------------------------------
/show_issues.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | git submodule foreach \
4 | hub issue --format='%sC%>(8)%i%Creset %t% l%n%Cblue% U%Creset%n' --color=always
5 |
--------------------------------------------------------------------------------
/show_pullrequests.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | git submodule foreach \
4 | hub pr list --format='%pC%>(8)%i%Creset %t% l%n%Cblue% U%Creset%n' --color=always
5 |
--------------------------------------------------------------------------------
/update_submodules.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | import os
3 | import subprocess
4 | import requests
5 | import time
6 |
7 |
8 | try:
9 | subprocess.run(["git", "diff", "--staged", "--quiet", "--exit-code"], check=True)
10 | except subprocess.SubprocessError:
11 | print("Error: You have staged changes!")
12 | exit(1)
13 |
14 | available = []
15 | fetched = []
16 | failed = []
17 | removed = []
18 | added = []
19 |
20 |
21 | def update(_name, url=None):
22 | if not os.path.exists(_name):
23 | print("Adding {} @ {}".format(_name, url))
24 | subprocess.run(["git", "submodule", "add", "--force", "-b", "master", url, _name], check=True)
25 | added.append(_name)
26 | subprocess.run(["git", "submodule", "update", "--init", "--remote", "--checkout", "--force", _name], check=True)
27 |
28 | subprocess.run(["git", "fetch", "--all", "--tags"], cwd=_name, check=True)
29 | subprocess.run(["git", "checkout", "-f", "-B", "master", "origin/master"], cwd=_name, check=True)
30 | subprocess.run(["git", "add", _name], check=True)
31 | fetched.append(_name)
32 |
33 |
34 | def remove(_name):
35 | if os.path.exists(_name):
36 | print("Removing {}".format(_name))
37 | subprocess.run(["git", "rm", _name], check=True)
38 | removed.append(_name)
39 |
40 |
41 | page_num = 1
42 | per_page = 100
43 | PAGINATION_URL = "https://api.github.com/orgs/jellyfin/repos?sort=created&per_page={per}&page={page}"
44 |
45 | next = PAGINATION_URL.format(per=per_page, page=page_num)
46 |
47 | while next:
48 | resp = requests.get(next)
49 | repos = resp.json()
50 |
51 | page_num += 1
52 | next = PAGINATION_URL.format(per=per_page, page=page_num)
53 | if len(repos) < per_page:
54 | next = None
55 |
56 | for repo in repos:
57 | _name = repo.get("name")
58 | url = repo.get("clone_url")
59 | if _name.startswith("jellyfin-plugin-"):
60 | available.append(_name)
61 | try:
62 | update(_name, url)
63 | pass
64 | except Exception as e:
65 | failed.append((_name, e))
66 |
67 |
68 | for repo in os.listdir("."):
69 | if repo in fetched:
70 | continue
71 |
72 | if not os.path.isdir(repo):
73 | continue
74 |
75 | if not repo.startswith("jellyfin-plugin-"):
76 | continue
77 |
78 | try:
79 | if not repo in available:
80 | remove(repo)
81 | except Exception as e:
82 | failed.append((repo, e))
83 |
84 |
85 | if failed:
86 | print("The following repositories failed to update:")
87 | for repo, e in failed:
88 | print(repo, e)
89 |
90 | commit_message = ["Updated plugin submodules"]
91 |
92 | if added:
93 | commit_message.append("")
94 | commit_message.append("Added")
95 | commit_message.append("-----")
96 | commit_message.append("")
97 | for plugin in added:
98 | commit_message.append("- {}".format(plugin))
99 |
100 | if removed:
101 | commit_message.append("")
102 | commit_message.append("Removed")
103 | commit_message.append("-------")
104 | commit_message.append("")
105 | for plugin in removed:
106 | commit_message.append("- {}".format(plugin))
107 |
108 | subprocess.run(["git", "commit", "-m", "\n".join(commit_message)])
109 |
--------------------------------------------------------------------------------