diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 00000000..40eddc6e --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,29 @@ +# Contributing + +When contributing to this repository, please first discuss the change you wish +to make via issue, email, or any other method with the owners of this repository +before making a change. + +Please note we have a code of conduct, please follow it in all your interactions +with the project. + +## Issues and feature requests + +You've found a bug in the source code, a mistake in the documentation or maybe +you'd like a new feature? You can help us by submitting an issue to our +[GitHub Repository][github]. Before you create an issue, make sure you search +the archive, maybe your question was already answered. + +Even better: You could submit a pull request with a fix / new feature! + +## Pull request process + +1. Search our repository for open or closed [pull requests][prs] that relates + to your submission. You don't want to duplicate effort. + +1. You may merge the pull request in once you have the sign-off of two other + developers, or if you do not have permission to do that, you may request + the second reviewer to merge it for you. + +[github]: https://github.com/GauthamVarmaK/addon-tvheadend/issues +[prs]: https://github.com/GauthamVarmaK/addon-tvheadend/pulls diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml new file mode 100644 index 00000000..45dd97a4 --- /dev/null +++ b/.github/dependabot.yaml @@ -0,0 +1,8 @@ +--- +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: daily + time: "06:00" diff --git a/.github/labels.yml b/.github/labels.yml new file mode 100644 index 00000000..2d0f68ad --- /dev/null +++ b/.github/labels.yml @@ -0,0 +1,85 @@ +--- +- name: "breaking-change" + color: ee0701 + description: "A breaking change for existing users." +- name: "bugfix" + color: ee0701 + description: "Inconsistencies or issues which will cause a problem for users or implementors." +- name: "documentation" + color: 0052cc + description: "Solely about the documentation of the project." +- name: "enhancement" + color: 1d76db + description: "Enhancement of the code, not introducing new features." +- name: "refactor" + color: 1d76db + description: "Improvement of existing code, not introducing new features." +- name: "performance" + color: 1d76db + description: "Improving performance, not introducing new features." +- name: "new-feature" + color: 0e8a16 + description: "New features or options." +- name: "maintenance" + color: 2af79e + description: "Generic maintenance tasks." +- name: "ci" + color: 1d76db + description: "Work that improves the continue integration." +- name: "dependencies" + color: 1d76db + description: "Upgrade or downgrade of project dependencies." + +- name: "in-progress" + color: fbca04 + description: "Issue is currently being resolved by a developer." +- name: "stale" + color: fef2c0 + description: "There has not been activity on this issue or PR for quite some time." +- name: "no-stale" + color: fef2c0 + description: "This issue or PR is exempted from the stable bot." + +- name: "security" + color: ee0701 + description: "Marks a security issue that needs to be resolved asap." +- name: "incomplete" + color: fef2c0 + description: "Marks a PR or issue that is missing information." +- name: "invalid" + color: fef2c0 + description: "Marks a PR or issue that is missing information." + +- name: "beginner-friendly" + color: 0e8a16 + description: "Good first issue for people wanting to contribute to the project." +- name: "help-wanted" + color: 0e8a16 + description: "We need some extra helping hands or expertise in order to resolve this." + +- name: "hacktoberfest" + description: "Issues/PRs are participating in the Hacktoberfest." + color: fbca04 +- name: "hacktoberfest-accepted" + description: "Issues/PRs are participating in the Hacktoberfest." + color: fbca04 + +- name: "priority-critical" + color: ee0701 + description: "This should be dealt with ASAP. Not fixing this issue would be a serious error." +- name: "priority-high" + color: b60205 + description: "After critical issues are fixed, these should be dealt with before any further issues." +- name: "priority-medium" + color: 0e8a16 + description: "This issue may be useful, and needs some attention." +- name: "priority-low" + color: e4ea8a + description: "Nice addition, maybe... someday..." + +- name: "major" + color: b60205 + description: "This PR causes a major version bump in the version number." +- name: "minor" + color: 0e8a16 + description: "This PR causes a minor version bump in the version number." diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 00000000..cb404ea3 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,57 @@ +--- +name-template: "v$RESOLVED_VERSION" +tag-template: "v$RESOLVED_VERSION" +change-template: "- $TITLE @$AUTHOR (#$NUMBER)" +sort-direction: ascending + +categories: + - title: "🚨 Breaking changes" + labels: + - "breaking-change" + - title: "✨ New features" + labels: + - "new-feature" + - title: "πŸ› Bug fixes" + labels: + - "bugfix" + - title: "πŸš€ Enhancements" + labels: + - "enhancement" + - "refactor" + - "performance" + - title: "🧰 Maintenance" + labels: + - "maintenance" + - "ci" + - title: "πŸ“š Documentation" + labels: + - "documentation" + - title: "⬆️ Dependency updates" + labels: + - "dependencies" + +version-resolver: + major: + labels: + - "major" + - "breaking-change" + minor: + labels: + - "minor" + - "new-feature" + patch: + labels: + - "bugfix" + - "chore" + - "ci" + - "dependencies" + - "documentation" + - "enhancement" + - "performance" + - "refactor" + default: patch + +template: | + ## What’s changed + + $CHANGES diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 00000000..150cc8b5 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,199 @@ +--- +name: CI + +# yamllint disable-line rule:truthy +on: + push: + pull_request: + types: + - opened + - reopened + - synchronize + workflow_dispatch: + +jobs: + information: + name: Gather add-on information + runs-on: ubuntu-latest + outputs: + architectures: ${{ steps.information.outputs.architectures }} + build: ${{ steps.information.outputs.build }} + description: ${{ steps.information.outputs.description }} + name: ${{ steps.information.outputs.name }} + slug: ${{ steps.information.outputs.slug }} + target: ${{ steps.information.outputs.target }} + steps: + - name: ‡️ Check out code from GitHub + uses: actions/checkout@v2.3.4 + - name: πŸš€ Run add-on information action + id: information + uses: frenck/action-addon-information@v1.0.0 + + lint-addon: + name: Lint Add-on + needs: + - information + runs-on: ubuntu-latest + steps: + - name: ‡️ Check out code from GitHub + uses: actions/checkout@v2.3.4 + - name: πŸš€ Run Add-on Lint + uses: frenck/action-addon-linter@v2 + with: + community: true + path: "./${{ needs.information.outputs.target }}" + + lint-hadolint: + name: Hadolint + needs: + - information + runs-on: ubuntu-latest + steps: + - name: ‡️ Check out code from GitHub + uses: actions/checkout@v2.3.4 + - name: πŸš€ Run Hadolint + uses: brpaz/hadolint-action@v1.4.0 + with: + dockerfile: "./${{ needs.information.outputs.target }}/Dockerfile" + + lint-json: + name: JSON Lint + runs-on: ubuntu-latest + steps: + - name: ‡️ Check out code from GitHub + uses: actions/checkout@v2.3.4 + - name: πŸš€ Run JQ + run: | + shopt -s globstar + cat **/*.json | jq '.' + + lint-markdown: + name: MarkdownLint + runs-on: ubuntu-latest + steps: + - name: ‡️ Check out code from GitHub + uses: actions/checkout@v2.3.4 + - name: πŸš€ Run mdl + uses: actionshub/markdownlint@2.0.2 + + lint-shellcheck: + name: Shellcheck + runs-on: ubuntu-latest + steps: + - name: ‡️ Check out code from GitHub + uses: actions/checkout@v2.3.4 + - name: πŸš€ Run Shellcheck + uses: ludeeus/action-shellcheck@1.1.0 + env: + SHELLCHECK_OPTS: -s bash + + lint-yamllint: + name: YAMLLint + runs-on: ubuntu-latest + steps: + - name: ‡️ Check out code from GitHub + uses: actions/checkout@v2.3.4 + - name: πŸš€ Run YAMLLint + uses: frenck/action-yamllint@v1.1 + + lint-prettier: + name: Prettier + runs-on: ubuntu-latest + steps: + - name: ‡️ Check out code from GitHub + uses: actions/checkout@v2.3.4 + - name: πŸš€ Run Prettier + uses: creyD/prettier_action@v3.3 + with: + prettier_options: --write **/*.{json,js,md,yaml} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + build: + name: Build ${{ matrix.architecture }} + needs: + - information + - lint-addon + - lint-hadolint + - lint-json + - lint-markdown + - lint-prettier + - lint-shellcheck + - lint-yamllint + runs-on: ubuntu-latest + strategy: + matrix: + architecture: ${{ fromJson(needs.information.outputs.architectures) }} + steps: + - name: ‡️ Check out code from GitHub + uses: actions/checkout@v2.3.4 + - name: πŸ— Set up build cache + id: cache + uses: actions/cache@v2.1.5 + with: + path: /tmp/.docker-cache + key: + docker-${{ github.ref }}-${{ matrix.architecture }}-${{ github.sha + }} + restore-keys: | + docker-${{ github.ref }}-${{ matrix.architecture }} + - name: πŸ— Set up QEMU + uses: docker/setup-qemu-action@v1.0.2 + - name: πŸ— Set up Docker Buildx + uses: docker/setup-buildx-action@v1.1.2 + - name: πŸ— Set up CodeNotary + run: bash <(curl https://getvcn.codenotary.com -L) + - name: ℹ️ Compose build flags + id: flags + run: | + echo "::set-output name=date::$(date +"%Y-%m-%dT%H:%M:%SZ")" + from=$(jq --raw-output ".build_from.${{ matrix.architecture }}" "${{ needs.information.outputs.build }}") + echo "::set-output name=from::${from}" + + if [[ "${{ matrix.architecture}}" = "amd64" ]]; then + echo "::set-output name=platform::linux/amd64" + elif [[ "${{ matrix.architecture }}" = "i386" ]]; then + echo "::set-output name=platform::linux/386" + elif [[ "${{ matrix.architecture }}" = "armhf" ]]; then + echo "::set-output name=platform::linux/arm/v6" + elif [[ "${{ matrix.architecture }}" = "armv7" ]]; then + echo "::set-output name=platform::linux/arm/v7" + elif [[ "${{ matrix.architecture }}" = "aarch64" ]]; then + echo "::set-output name=platform::linux/arm64/v8" + else + echo "::error ::Could not determine platform for architecture ${{ matrix.architecture }}" + exit 1 + fi + - name: ‡️ Download base image + run: docker pull "${{ steps.flags.outputs.from }}" + - name: βœ… Verify authenticity of base image + run: | + vcn authenticate \ + "docker://${{ steps.flags.outputs.from }}" + vcn authenticate \ + --output json \ + --signerID 0x03e406879fd89e52f38f4aab0061266d1183980a \ + "docker://${{ steps.flags.outputs.from }}" \ + | jq \ + --exit-status \ + '.verification.status == 0' + - name: πŸš€ Build + uses: docker/build-push-action@v2.4.0 + with: + push: false + context: ${{ needs.information.outputs.target }} + file: ${{ needs.information.outputs.target }}/Dockerfile + cache-from: | + type=local,src=/tmp/.docker-cache + ghcr.io/gauthamvarmak/${{ needs.information.outputs.slug }}/${{ matrix.architecture }}:edge + cache-to: type=local,mode=max,dest=/tmp/.docker-cache + platforms: ${{ steps.flags.outputs.platform }} + build-args: | + BUILD_ARCH=${{ matrix.architecture }} + BUILD_DATE=${{ steps.flags.outputs.date }} + BUILD_DESCRIPTION=${{ needs.information.outputs.description }} + BUILD_FROM=${{ steps.flags.outputs.from }} + BUILD_NAME=${{ needs.information.outputs.name }} + BUILD_REF=${{ github.sha }} + BUILD_REPOSITORY=${{ github.repository }} + BUILD_VERSION=edge diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml new file mode 100644 index 00000000..73052b4f --- /dev/null +++ b/.github/workflows/deploy.yaml @@ -0,0 +1,180 @@ +--- +name: Deploy + +# yamllint disable-line rule:truthy +on: + release: + types: + - published + workflow_run: + workflows: ["CI"] + branches: [main] + types: + - completed + +jobs: + information: + if: | + github.event_name == 'release' + || ( + github.event_name == 'workflow_run' + && github.event.workflow_run.conclusion == 'success' + ) + name: ℹ️ Gather add-on information + runs-on: ubuntu-latest + outputs: + architectures: ${{ steps.information.outputs.architectures }} + build: ${{ steps.information.outputs.build }} + description: ${{ steps.information.outputs.description }} + environment: ${{ steps.release.outputs.environment }} + name: ${{ steps.information.outputs.name }} + slug: ${{ steps.information.outputs.slug }} + target: ${{ steps.information.outputs.target }} + version: ${{ steps.release.outputs.version }} + steps: + - name: ‡️ Check out code from GitHub + uses: actions/checkout@v2.3.4 + - name: πŸš€ Run add-on information action + id: information + uses: frenck/action-addon-information@v1.0.0 + - name: ℹ️ Gather version and environment + id: release + run: | + sha="${{ github.sha }}" + environment="edge" + version="${sha:0:7}" + if [[ "${{ github.event_name }}" = "release" ]]; then + version="${{ github.event.release.tag_name }}" + version="${version,,}" + version="${version#v}" + environment="stable" + if [[ "${{ github.event.release.prerelease }}" = "true" ]]; then + environment="beta" + fi + fi + + echo "::set-output name=environment::${environment}" + echo "::set-output name=version::${version}" + + deploy: + name: πŸ‘· Build & Deploy ${{ matrix.architecture }} + needs: information + runs-on: ubuntu-latest + strategy: + matrix: + architecture: ${{ fromJson(needs.information.outputs.architectures) }} + steps: + - name: πŸ”‚ Wait for other runs to complete + uses: softprops/turnstyle@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: ‡️ Check out code from GitHub + uses: actions/checkout@v2.3.4 + - name: πŸ— Set up build cache + id: cache + uses: actions/cache@v2.1.5 + with: + path: /tmp/.docker-cache + key: + docker-${{ github.ref }}-${{ matrix.architecture }}-${{ github.sha + }} + restore-keys: | + docker-${{ github.ref }}-${{ matrix.architecture }} + - name: πŸ— Set up QEMU + uses: docker/setup-qemu-action@v1.0.2 + - name: πŸ— Set up Docker Buildx + uses: docker/setup-buildx-action@v1.1.2 + - name: πŸ— Set up CodeNotary + run: bash <(curl https://getvcn.codenotary.com -L) + - name: ℹ️ Compose build flags + id: flags + run: | + echo "::set-output name=date::$(date +"%Y-%m-%dT%H:%M:%SZ")" + from=$(jq --raw-output ".build_from.${{ matrix.architecture }}" "${{ needs.information.outputs.build }}") + echo "::set-output name=from::${from}" + + if [[ "${{ matrix.architecture}}" = "amd64" ]]; then + echo "::set-output name=platform::linux/amd64" + elif [[ "${{ matrix.architecture }}" = "i386" ]]; then + echo "::set-output name=platform::linux/386" + elif [[ "${{ matrix.architecture }}" = "armhf" ]]; then + echo "::set-output name=platform::linux/arm/v6" + elif [[ "${{ matrix.architecture }}" = "armv7" ]]; then + echo "::set-output name=platform::linux/arm/v7" + elif [[ "${{ matrix.architecture }}" = "aarch64" ]]; then + echo "::set-output name=platform::linux/arm64/v8" + else + echo "::error ::Could not determine platform for architecture ${{ matrix.architecture }}" + exit 1 + fi + - name: πŸ— Login to GitHub Container Registry + uses: docker/login-action@v1.8.0 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GHRC_TOKEN }} + - name: ‡️ Download base image + run: docker pull "${{ steps.flags.outputs.from }}" + - name: βœ… Verify authenticity of base image + run: | + vcn authenticate \ + "docker://${{ steps.flags.outputs.from }}" + vcn authenticate \ + --output json \ + --signerID 0x03e406879fd89e52f38f4aab0061266d1183980a \ + "docker://${{ steps.flags.outputs.from }}" \ + | jq \ + --exit-status \ + '.verification.status == 0' + - name: πŸš€ Build + uses: docker/build-push-action@v2.4.0 + with: + load: true + # yamllint disable rule:line-length + tags: | + ghcr.io/gauthamvarmak/${{ needs.information.outputs.slug }}/${{ matrix.architecture }}:${{ needs.information.outputs.environment }} + ghcr.io/gauthamvarmak/${{ needs.information.outputs.slug }}/${{ matrix.architecture }}:${{ needs.information.outputs.version }} + # yamllint enable rule:line-length + context: ${{ needs.information.outputs.target }} + file: ${{ needs.information.outputs.target }}/Dockerfile + cache-from: | + type=local,src=/tmp/.docker-cache + ghcr.io/gauthamvarmak/${{ needs.information.outputs.slug }}/${{ matrix.architecture }}:edge + cache-to: type=local,mode=max,dest=/tmp/.docker-cache + platforms: ${{ steps.flags.outputs.platform }} + build-args: | + BUILD_ARCH=${{ matrix.architecture }} + BUILD_DATE=${{ steps.flags.outputs.date }} + BUILD_DESCRIPTION=${{ needs.information.outputs.description }} + BUILD_FROM=${{ steps.flags.outputs.from }} + BUILD_NAME=${{ needs.information.outputs.name }} + BUILD_REF=${{ github.sha }} + BUILD_REPOSITORY=${{ github.repository }} + BUILD_VERSION=${{ needs.information.outputs.version }} + - name: πŸ” Notarize + # yamllint disable rule:line-length + run: | + if vcn authenticate \ + --output json \ + "docker://ghcr.io/gauthamvarmak/${{ needs.information.outputs.slug }}/${{ matrix.architecture }}:${{ needs.information.outputs.version }}" \ + | jq \ + --exit-status \ + '.verification.status != 0'; + then + vcn login + vcn notarize \ + --public \ + "docker://ghcr.io/gauthamvarmak/${{ needs.information.outputs.slug }}/${{ matrix.architecture }}:${{ needs.information.outputs.version }}" + fi + env: + VCN_USER: ${{ secrets.VCN_USER }} + VCN_PASSWORD: ${{ secrets.VCN_PASSWORD }} + VCN_NOTARIZATION_PASSWORD: ${{ secrets.VCN_NOTARIZATION_PASSWORD }} + VCN_OTP_EMPTY: true + - name: πŸš€ Push + # yamllint disable rule:line-length + run: | + docker push \ + "ghcr.io/gauthamvarmak/${{ needs.information.outputs.slug }}/${{ matrix.architecture }}:${{ needs.information.outputs.environment }}" + docker push \ + "ghcr.io/gauthamvarmak/${{ needs.information.outputs.slug }}/${{ matrix.architecture }}:${{ needs.information.outputs.version }}" diff --git a/.github/workflows/labels.yaml b/.github/workflows/labels.yaml new file mode 100644 index 00000000..5a6ab37c --- /dev/null +++ b/.github/workflows/labels.yaml @@ -0,0 +1,22 @@ +--- +name: Sync labels + +# yamllint disable-line rule:truthy +on: + push: + branches: + - main + paths: + - .github/labels.yml + +jobs: + labels: + name: ♻️ Sync labels + runs-on: ubuntu-latest + steps: + - name: ‡️ Check out code from GitHub + uses: actions/checkout@v2.3.4 + - name: πŸš€ Run Label Syncer + uses: micnncim/action-label-syncer@v1.2.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/lock.yaml b/.github/workflows/lock.yaml new file mode 100644 index 00000000..ff147a20 --- /dev/null +++ b/.github/workflows/lock.yaml @@ -0,0 +1,21 @@ +--- +name: Lock + +# yamllint disable-line rule:truthy +on: + schedule: + - cron: "0 9 * * *" + workflow_dispatch: + +jobs: + lock: + name: πŸ”’ Lock closed issues and PRs + runs-on: ubuntu-latest + steps: + - uses: dessant/lock-threads@v2.0.3 + with: + github-token: ${{ github.token }} + issue-lock-inactive-days: "30" + issue-lock-reason: "" + pr-lock-inactive-days: "1" + pr-lock-reason: "" diff --git a/.github/workflows/pr-labels.yaml b/.github/workflows/pr-labels.yaml new file mode 100644 index 00000000..41da9cf7 --- /dev/null +++ b/.github/workflows/pr-labels.yaml @@ -0,0 +1,21 @@ +--- +name: PR Labels + +# yamllint disable-line rule:truthy +on: + pull_request: + types: [opened, labeled, unlabeled, synchronize] + +jobs: + pr_labels: + name: Verify + runs-on: ubuntu-latest + steps: + - name: 🏷 Verify PR has a valid label + uses: jesusvasquez333/verify-pr-label-action@v1.4.0 + with: + github-token: "${{ secrets.GITHUB_TOKEN }}" + valid-labels: >- + breaking-change, bugfix, documentation, enhancement, refactor, + performance, new-feature, maintenance, ci, dependencies + disable-reviews: true diff --git a/.github/workflows/release-drafter.yaml b/.github/workflows/release-drafter.yaml new file mode 100644 index 00000000..06cc26ae --- /dev/null +++ b/.github/workflows/release-drafter.yaml @@ -0,0 +1,18 @@ +--- +name: Release Drafter + +# yamllint disable-line rule:truthy +on: + push: + branches: + - main + +jobs: + update_release_draft: + name: ✏️ Draft release + runs-on: ubuntu-latest + steps: + - name: πŸš€ Run Release Drafter + uses: release-drafter/release-drafter@v5.15.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml new file mode 100644 index 00000000..e7cfe897 --- /dev/null +++ b/.github/workflows/stale.yaml @@ -0,0 +1,40 @@ +--- +name: Stale + +# yamllint disable-line rule:truthy +on: + schedule: + - cron: "0 8 * * *" + workflow_dispatch: + +jobs: + stale: + name: 🧹 Clean up stale issues and PRs + runs-on: ubuntu-latest + steps: + - name: πŸš€ Run stale + uses: actions/stale@v3.0.18 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + days-before-stale: 30 + days-before-close: 7 + remove-stale-when-updated: true + stale-issue-label: "stale" + exempt-issue-labels: "no-stale,help-wanted" + stale-issue-message: > + There hasn't been any activity on this issue recently, so we + clean up some of the older and inactive issues. + + Please make sure to update to the latest version and + check if that solves the issue. Let us know if that works for you + by leaving a comment πŸ‘ + + This issue has now been marked as stale and will be closed if no + further activity occurs. Thanks! + stale-pr-label: "stale" + exempt-pr-labels: "no-stale" + stale-pr-message: > + There hasn't been any activity on this pull request recently. This + pull request has been automatically marked as stale because of that + and will be closed if no further activity occurs within 7 days. + Thank you for your contributions. diff --git a/.mdlrc b/.mdlrc new file mode 100644 index 00000000..2b0128da --- /dev/null +++ b/.mdlrc @@ -0,0 +1 @@ +rules "~MD024" \ No newline at end of file diff --git a/.yamllint b/.yamllint new file mode 100644 index 00000000..0a2a889b --- /dev/null +++ b/.yamllint @@ -0,0 +1,64 @@ +--- +rules: + braces: + level: error + min-spaces-inside: 0 + max-spaces-inside: 1 + min-spaces-inside-empty: -1 + max-spaces-inside-empty: -1 + brackets: + level: error + min-spaces-inside: 0 + max-spaces-inside: 0 + min-spaces-inside-empty: -1 + max-spaces-inside-empty: -1 + colons: + level: error + max-spaces-before: 0 + max-spaces-after: 1 + commas: + level: error + max-spaces-before: 0 + min-spaces-after: 1 + max-spaces-after: 1 + comments: + level: error + require-starting-space: true + min-spaces-from-content: 2 + comments-indentation: + level: error + document-end: + level: error + present: false + document-start: + level: error + present: true + empty-lines: + level: error + max: 1 + max-start: 0 + max-end: 1 + hyphens: + level: error + max-spaces-after: 1 + indentation: + level: error + spaces: 2 + indent-sequences: true + check-multi-line-strings: false + key-duplicates: + level: error + line-length: + level: warning + max: 120 + allow-non-breakable-words: true + allow-non-breakable-inline-mappings: true + new-line-at-end-of-file: + level: error + new-lines: + level: error + type: unix + trailing-spaces: + level: error + truthy: + level: error diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000..52eba9a7 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +# MIT License + +Copyright (c) 2021-2021 Gautham varma K + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 00000000..1fcd4178 --- /dev/null +++ b/README.md @@ -0,0 +1,108 @@ +# Home Assistant Community Add-on: TVHeadend + +[![GitHub Release][releases-shield]][releases] +![Project Stage][project-stage-shield] +[![License][license-shield]](LICENSE.md) + +![Supports aarch64 Architecture][aarch64-shield] +![Supports amd64 Architecture][amd64-shield] +![Supports armhf Architecture][armhf-shield] +![Supports armv7 Architecture][armv7-shield] +![Supports i386 Architecture][i386-shield] + +[![Github Actions][github-actions-shield]][github-actions] +![Project Maintenance][maintenance-shield] +[![GitHub Activity][commits-shield]][commits] +[![Community Forum][forum-shield]][forum] + +TVHeadend is a TV streaming server and recorder. + +## About + +TVHeadend is a TV streaming server and recorder supporting: +DVB-S, DVB-S2, DVB-C, DVB-T, DVB-T2, ATSC, ISDB-T, IPTV, SAT>IP and HDHomeRun +as input sources. +TVHeadend offers the HTTP (VLC, MPlayer), HTSP (Kodi, Movian) and SAT>IP streaming. + +Multiple EPG sources are supported such as +over-the-air DVB and ATSC including OpenTV DVB extensions, XMLTV, PyXML. + +![TVHeadend](images/screenshot.png) + +This add-on comes with Webgrab+, Streamlink preinstalled as well. + +[:books: Read the full add-on documentation][docs] + +## Support + +Got questions? + +You have several options to get them answered: + +- The Home Assistant [Community Forum][forum]. +- You could also [open an issue here][issue] GitHub. + +## Contributing + +This is an active open-source project. We are always open to people who want to +use the code or contribute to it. + +We have set up a separate document containing our +[contribution guidelines](CONTRIBUTING.md). + +Thank you for being involved! :heart_eyes: + +## Authors & contributors + +This repository is owned and maintained by [GauthamVarmaK][gautham]. + +This has been possible thanks to the community add-ons initiative by [Frenck] + +For a full list of all authors and contributors, +check [the contributor's page][contributors]. + +## License + +MIT License + +Copyright (c) 2021 GauthamVarmaK + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +[contributors]: https://github.com/GauthamVarmaK/addon-tvheadend/graphs/contributors +[docs]: https://github.com/GauthamVarmaK/addon-tvheadend/blob/main/tvheadend/DOCS.md +[forum-shield]: https://img.shields.io/badge/community-forum-brightgreen.svg +[forum]: https://community.home-assistant.io/ +[gautham]: https://github.com/GauthamVarmaK +[frenck]: https://github.com/frenck +[github-actions-shield]: https://github.com/GauthamVarmaK/addon-tvheadend/workflows/CI/badge.svg +[github-actions]: https://github.com/GauthamVarmaK/addon-tvheadend/actions +[i386-shield]: https://img.shields.io/badge/i386-yes-green.svg +[issue]: https://github.com/GauthamVarmaK/addon-tvheadend/issues +[license-shield]: https://img.shields.io/github/license/GauthamVarmaK/addon-tvheadend.svg +[maintenance-shield]: https://img.shields.io/maintenance/yes/2021.svg +[project-stage-shield]: https://img.shields.io/badge/project%20stage-production%20ready-brightgreen.svg +[releases-shield]: https://img.shields.io/github/release/GauthamVarmaK/addon-tvheadend.svg +[releases]: https://github.com/GauthamVarmaK/addon-tvheadend/releases +[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg +[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg +[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg +[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg +[commits-shield]: https://img.shields.io/github/commit-activity/y/GauthamVarmaK/addon-tvheadend.svg +[commits]: https://github.com/GauthamVarmaK/addon-tvheadend/commits/main diff --git a/images/screenshot.png b/images/screenshot.png new file mode 100644 index 00000000..d90d173a Binary files /dev/null and b/images/screenshot.png differ diff --git a/tvheadend/.README.j2 b/tvheadend/.README.j2 new file mode 100644 index 00000000..7ded9e85 --- /dev/null +++ b/tvheadend/.README.j2 @@ -0,0 +1,27 @@ +# Home Assistant Community Add-on: TVHeadend + +[![Release][release-shield]][release] ![Project Stage][project-stage-shield] ![Project Maintenance][maintenance-shield] + +[![Community Forum][forum-shield]][forum] + +TVHeadend add-on by GauthamVarmaK. + +## About + +TVHeadend is a TV streaming server and recorder supporting: +DVB-S, DVB-S2, DVB-C, DVB-T, DVB-T2, ATSC, ISDB-T, IPTV, SAT>IP and HDHomeRun +as input sources. +TVHeadend offers the HTTP (VLC, MPlayer), HTSP (Kodi, Movian) and SAT>IP streaming. + +Multiple EPG sources are supported (over-the-air DVB and ATSC including OpenTV DVB extensions, XMLTV, PyXML). + +Have included the following along with TVHeadend: +-Webgrab+ +-Streamlink + +[forum-shield]: https://img.shields.io/badge/community-forum-brightgreen.svg +[forum]: https://community.home-assistant.io/u/gauthamvarmak +[maintenance-shield]: https://img.shields.io/maintenance/yes/2021.svg +[project-stage-shield]: https://img.shields.io/badge/project%20stage-production%20ready-brightgreen.svg +[release-shield]: https://img.shields.io/badge/version-{{ version }}-blue.svg +[release]: {{ repo }}/tree/{{ version }} diff --git a/tvheadend/DOCS.md b/tvheadend/DOCS.md new file mode 100644 index 00000000..1ebf8a7b --- /dev/null +++ b/tvheadend/DOCS.md @@ -0,0 +1,91 @@ +# Home Assistant Community Add-on: TVHeadend + +TVHeadend is a TV streaming server and recorder supporting: +DVB-S, DVB-S2, DVB-C, DVB-T, DVB-T2, ATSC, ISDB-T, IPTV, SAT>IP and HDHomeRun +as input sources. +TVHeadend offers the HTTP (VLC, MPlayer), HTSP (Kodi, Movian) and SAT>IP streaming. + +Multiple EPG sources are supported such as +over-the-air DVB and ATSC including OpenTV DVB extensions, XMLTV, PyXML. + +Have included the following along with TVHeadend: +-Webgrab+ +-Streamlink + +## Installation + +The installation of this add-on is pretty straightforward and not different in +comparison to installing any other Home Assistant add-on. + +1. Install "Gautham's Add-ons" in supervisor. +1. Search for the "TVHeadend" add-on in the Supervisor add-on store and install it. +1. Start the "TVHeadend" add-on. +1. Check the logs of the "TVHeadend" to see if everything went well. +1. Click the "OPEN WEB UI" button and start using it. +1. Ready to go! + +## Configuration + +No changes needed from the user, unless u need to change the ports. + +-Config files are stored in /config/tvheadend/ +-Recording files are stored in /config/tvheadend/recordings/ +Consider, backing them up whenever migrating. + +## Changelog & Releases + +This repository keeps a change log using [GitHub's releases][releases] +functionality. + +Releases are based on [Semantic Versioning][semver], and use the format +of `MAJOR.MINOR.PATCH`. In a nutshell, the version will be incremented +based on the following: + +- `MAJOR`: Incompatible or major changes. +- `MINOR`: Backwards-compatible new features and enhancements. +- `PATCH`: Backwards-compatible bugfixes and package updates. + +## Support + +Got questions? + +You have several options to get them answered: + +- The Home Assistant [Community Forum][forum]. +- You could also [open an issue here][issue] GitHub. + +## Authors & contributors + +This repository is owned and maintained by [GauthamVarmaK][gautham]. + +This has been possible thanks to the community add-ons initiative by [Frenck][frenck] + +## License + +MIT License + +Copyright (c) 2021 GauthamVarmaK + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +[forum]: https://community.home-assistant.io/ +[gautham]: https://github.com/GauthamVarmaK +[frenck]: https://github.com/frenck +[issue]: https://github.com/GauthamVarmaK/addon-tvheadend/issues +[releases]: https://github.com/GauthamVarmaK/addon-tvheadend/releases diff --git a/tvheadend/Dockerfile b/tvheadend/Dockerfile new file mode 100644 index 00000000..76be3b5e --- /dev/null +++ b/tvheadend/Dockerfile @@ -0,0 +1,33 @@ +ARG BUILD_FROM=ghcr.io/hassio-addons/base/amd64:9.2.0 +# hadolint ignore=DL3006 +FROM ${BUILD_FROM} + +RUN echo 'http://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/repositories +RUN echo 'http://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories +RUN echo 'http://dl-cdn.alpinelinux.org/alpine/edge/main' >> /etc/apk/repositories + +COPY run.sh /run.sh +RUN chmod +x /run.sh +RUN /run.sh + +RUN echo "Starting TVHeadend" +ENTRYPOINT ["/usr/bin/tvheadend", "--firstrun", "-u", "root", "-g", "root", "-c", "/config/tvheadend"] + +# Labels +LABEL \ + io.hass.name="TVHeadend" \ + io.hass.description="TVHeadend Add-On" \ + io.hass.arch="${BUILD_ARCH}" \ + io.hass.type="addon" \ + io.hass.version=${BUILD_VERSION} \ + maintainer="https://github.com/GauthamVarmaK" \ + org.label-schema.description="TVHeadend Home Assistant Add-On" \ + org.label-schema.build-date=${BUILD_DATE} \ + org.label-schema.name="TVHeadend" \ + org.label-schema.name="Home Assistant Addon: TVHeadend ${BUILD_ARCH}" \ + org.label-schema.schema-version="1.0" \ + org.label-schema.url="https://github.com/GauthamVarmaK/addon-tvheadend" \ + org.label-schema.usage="https://github.com/GauthamVarmaK/addon-tvheadend" \ + org.label-schema.vcs-ref=${BUILD_REF} \ + org.label-schema.vcs-url="https://github.com/GauthamVarmaK/addon-tvheadend" \ + org.label-schema.vendor="https://github.com/GauthamVarmaK" \ No newline at end of file diff --git a/tvheadend/build.json b/tvheadend/build.json new file mode 100644 index 00000000..2193cd2f --- /dev/null +++ b/tvheadend/build.json @@ -0,0 +1,9 @@ +{ + "build_from": { + "aarch64": "ghcr.io/hassio-addons/base/aarch64:9.2.0", + "amd64": "ghcr.io/hassio-addons/base/amd64:9.2.0", + "armhf": "ghcr.io/hassio-addons/base/armhf:9.2.0", + "armv7": "ghcr.io/hassio-addons/base/armv7:9.2.0", + "i386": "ghcr.io/hassio-addons/base/i386:9.2.0" + } +} diff --git a/tvheadend/config.json b/tvheadend/config.json new file mode 100644 index 00000000..8e456ae8 --- /dev/null +++ b/tvheadend/config.json @@ -0,0 +1,20 @@ +{ + "name": "TVHeadend", + "version": "dev", + "stage": "experimental", + "slug": "addon-tvheadend", + "description": "TV streaming server and recorder.", + "url": "https://github.com/GauthamVarmaK/addon-tvheadend", + "startup": "services", + "arch": ["aarch64", "amd64", "armhf", "armv7", "i386"], + "webui": "http://[HOST]:[PORT:9981]/", + "ports": { + "9981/tcp": 9981, + "9982/tcp": 9982 + }, + "ports_description": { + "9981/tcp": "TVH Web Interface", + "9982/tcp": "TVH HTSP" + }, + "map": ["config:rw"] +} diff --git a/tvheadend/icon.png b/tvheadend/icon.png new file mode 100644 index 00000000..d2a2f703 Binary files /dev/null and b/tvheadend/icon.png differ diff --git a/tvheadend/logo.png b/tvheadend/logo.png new file mode 100644 index 00000000..603bc1c0 Binary files /dev/null and b/tvheadend/logo.png differ diff --git a/tvheadend/run.sh b/tvheadend/run.sh new file mode 100644 index 00000000..4743c287 --- /dev/null +++ b/tvheadend/run.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bashio + +bashio::log.info "[TVHeadend] Installing TVHeadend" +apk update && apk add --no-cache tvheadend=4.2.8-r3 git=2.31.1-r1 mono=6.12.0.122-r1 + +mkdir -p /config/tvheadend/recordings + +bashio::log.info '[TVHeadend] Setup completed without errors!!' + +mkdir -p ~/.wg++ +ln -sf /config/tvheadend/wg++/guide.xml ~/.wg++/guide.xml + +if [ "$(ls -A /config/tvheadend/wg++)" ]; then + bashio::log.info "[Webgrab+] Webgrab+ already installed" +else + bashio::log.info "[Webgrab+] No webgrab+ installation found - Installing webgrab+" + cd /tmp && \ + wget http://www.webgrabplus.com/sites/default/files/download/SW/V2.1.0/WebGrabPlus_V2.1_install.tar.gz && \ + tar -xvf WebGrabPlus_V2.1_install.tar.gz && rm WebGrabPlus_V2.1_install.tar.gz && \ + mv .wg++/ /config/tvheadend/wg++ && \ + cd /config/tvheadend/wg++ && \ + ./install.sh + + rm -rf siteini.pack/ && \ + git clone https://github.com/DeBaschdi/webgrabplus-siteinipack.git && \ + cp -R webgrabplus-siteinipack/siteini.pack/ siteini.pack && \ + cp siteini.pack/International/horizon.tv.* siteini.user/ +fi + +wget -O /usr/bin/tv_grab_wg++ http://www.webgrabplus.com/sites/default/files/tv_grab_wg.txt && \ +chmod a+x /usr/bin/tv_grab_wg++ + +bashio::log.info '[Webgrab+] Setup completed without errors!!' + +echo "0 0 * * * /config/tvheadend/wg++/run.sh" >> /var/spool/cron/root +crond + +check_streamlink () { + if [ -z "$(command -v streamlink)" ]; then return 1; else return 0; fi +} + +streamlink_update () { + if pip3 install --no-cache --upgrade streamlink; then + bashio::log.info "[StreamLink] Streamlink version: $(streamlink --version)." + else + bashio::log.error '[StreamLink] Streamlink update failed!' + fi +} + +streamlink_install () { + bashio::log.info '[StreamLink] APK: Updating pkg list.' + if apk update; then + bashio::log.info '[StreamLink] APK: Installing required packages.' + if apk add --no-cache py3-pip && apk add --no-cache --virtual .build-deps gcc musl-dev; then + bashio::log.info '[StreamLink] PIP3: Updating and installing required packages.' + if ! pip3 install --no-cache --upgrade setuptools; then bashio::log.error '[StreamLink] PIP3: Error while upgrading setuptools.'; fi + if ! pip3 install --no-cache streamlink; then bashio::log.error '[StreamLink] PIP3: Error while installing Streamlink.'; fi + else + bashio::log.info '[StreamLink] APK: Critical error. Unable install required packages.' + exit 1 + fi + bashio::log.info '[StreamLink] APK: Removing packages no longer required.' + apk del .build-deps gcc musl-dev + else + bashio::log.error '[StreamLink] APK: Critical error. Unable to update pkg list. Check connectivity.' + exit 1 + fi + bashio::log.info '[StreamLink] Finsihed all APK and PIP3 updates and installs.' +} + +if check_streamlink; then + bashio::log.info '[StreamLink] Updating Streamlink...' ; streamlink_update +else + bashio::log.info '[StreamLink] Installing Streamlink...'; streamlink_install +fi + +bashio::log.info '[StreamLink] Setup completed without errors!!' \ No newline at end of file