diff --git a/.github/workflows/docs-localization-download.yml b/.github/workflows/docs-localization-download.yml index cc62511ed0..34e75a4dc7 100644 --- a/.github/workflows/docs-localization-download.yml +++ b/.github/workflows/docs-localization-download.yml @@ -9,6 +9,7 @@ jobs: download: name: "Download localizations from Crowdin" runs-on: ubuntu-latest + environment: translations outputs: pr_ref: ${{ steps.convert_outputs.outputs.pr_ref }} pr_id: ${{ steps.convert_outputs.outputs.pr_id }} @@ -35,7 +36,7 @@ jobs: working-directory: ./docs - name: "Build locales" run: - sphinx-intl update -p ./build/locales -l ja -l de -l ja -l fr -l it -l en -l hi -l ko -l pt_BR -l es -l zh_CN -l ru + sphinx-intl update -p ./build/locales ${{ vars.SPHINX_LANGUAGES }} working-directory: ./docs - name: "Crowdin" id: crowdin @@ -44,19 +45,19 @@ jobs: upload_sources: false upload_translations: false download_translations: false - download_bundle: ${{ secrets.CROWDIN_BUNDLE_ID }} - localization_branch_name: l10n_master + download_bundle: ${{ vars.CROWDIN_BUNDLE_ID }} + localization_branch_name: ${{ vars.CROWDIN_LOCALIZATION_BRANCH }} create_pull_request: true - pull_request_title: "docs: Update localizations from Crowdin" - pull_request_body: "Crowdin download was triggered due to completely translated file or project. Starting sync. CC @Lulalaby" + pull_request_title: ${{ vars.CROWDIN_PR_TITLE }} + pull_request_body: ${{ vars.CROWDIN_PR_BODY }} pull_request_base_branch_name: "master" pull_request_reviewers: "Lulalaby" config: "crowdin.yml" base_path: "." - commit_message: "docs: Update localizations from Crowdin" + commit_message: ${{ vars.CROWDIN_COMMIT_MSG }} env: GITHUB_TOKEN: ${{ secrets.CI_TOKEN }} - CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} + CROWDIN_PROJECT_ID: ${{ vars.CROWDIN_PROJECT_ID }} CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_API_TOKEN }} - name: "Convert Outputs" id: convert_outputs @@ -70,6 +71,7 @@ jobs: name: "PR operations" needs: [download] runs-on: ubuntu-latest + environment: translations steps: - name: "Checkout Repository" uses: actions/checkout@v4 @@ -121,7 +123,7 @@ jobs: #workflow: version-updates.yml #ref: ${{ steps.convert_outputs.outputs.pr_ref }} - name: "Auto Approve" - run: gh pr review --approve -b "auto-approval for localization sync :3" "$PR_ID" + run: gh pr review --approve -b "Auto-approval for localization sync" "$PR_ID" env: PR_ID: ${{ steps.convert_outputs.outputs.pr_id }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/docs-localization-upload.yml b/.github/workflows/docs-localization-upload.yml index 9bf2d5317a..521dc80ee3 100644 --- a/.github/workflows/docs-localization-upload.yml +++ b/.github/workflows/docs-localization-upload.yml @@ -17,8 +17,12 @@ jobs: name: "Upload localization base to Crowdin" runs-on: ubuntu-latest if: ${{ contains(github.event.head_commit.message, '!crowdin upload') || github.event_name == 'workflow_dispatch' }} + environment: translations steps: - - uses: actions/checkout@v4 + - name: "Checkout Repository" + uses: actions/checkout@v4 + with: + fetch-tags: true - name: "Install Python" uses: actions/setup-python@v5 with: @@ -37,7 +41,7 @@ jobs: working-directory: ./docs - name: "Build locales" run: - sphinx-intl update -p ./build/locales -l ja -l de -l ja -l fr -l it -l en -l hi -l ko -l pt_BR -l es -l zh_CN -l ru + sphinx-intl update -p ./build/locales ${{ vars.SPHINX_LANGUAGES }} working-directory: ./docs - name: "Crowdin" uses: crowdin/github-action@v2 @@ -45,10 +49,10 @@ jobs: upload_sources: true upload_translations: false download_translations: false - localization_branch_name: l10n_master + localization_branch_name: ${{ vars.CROWDIN_LOCALIZATION_BRANCH }} create_pull_request: false config: "crowdin.yml" env: GITHUB_TOKEN: ${{ secrets.CI_TOKEN }} - CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} + CROWDIN_PROJECT_ID: ${{ vars.CROWDIN_PROJECT_ID }} CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_API_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..b1bba58ae4 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,237 @@ +name: "Release" + +on: + workflow_dispatch: + inputs: + version: + type: string + description: "Version number to release (e.g., 1.2.3, 1.2.3-rc1, 1.2.0)" + required: true + +permissions: write-all + +jobs: + safety_check: + runs-on: ubuntu-latest + environment: release + env: + ALLOWED_USER_IDS: ${{ vars.ALLOWED_USER_IDS }} + steps: + - name: "Check if Executing User is Allowed" + id: safety + run: | + USER_ID=${{ github.actor_id }} + ALLOWED_IDS=$(echo $ALLOWED_USER_IDS | tr "," "\n") + if echo "$ALLOWED_IDS" | grep -q -w "$USER_ID"; then + echo "User $USER_ID is allowed to run this workflow." + else + echo "User $USER_ID is not authorized to run this workflow." + exit 1 + fi + + pre_config: + needs: [safety_check] + outputs: + branch_name: ${{ steps.determine_vars.outputs.branch_name }} + is_rc: ${{ steps.determine_vars.outputs.version }} + version: ${{ steps.determine_vars.outputs.is_rc }} + previous_tag: ${{ steps.determine_vars.outputs.previous_tag }} + runs-on: ububtu-latest + steps: + - name: "Checkout Repository" + uses: actions/checkout@v4 + + - name: "Determine Push Branch" + id: determine_vars + run: | + VERSION=${{ github.event.inputs.version }} + echo "version=${VERSION}" >> $GITHUB_OUTPUT + PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD^) + echo "previous_tag=${PREVIOUS_TAG}" >> $GITHUB_OUTPUT + if [[ $VERSION =~ -rc ]]; then + MAJOR_MINOR_VERSION=$(echo $VERSION | grep -oE '^[0-9]+\.[0-9]+') + echo "branch_name=v${MAJOR_MINOR_VERSION}.x" >> $GITHUB_OUTPUT + echo "is_rc=true" >> $GITHUB_OUTPUT + elif [[ $VERSION =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + MAJOR_MINOR_VERSION=$(echo $VERSION | grep -oE '^[0-9]+\.[0-9]+') + echo "branch_name=v${MAJOR_MINOR_VERSION}.x" >> $GITHUB_OUTPUT + echo "is_rc=false" >> $GITHUB_OUTPUT + else + MAJOR_MINOR_VERSION=$(echo $VERSION | grep -oE '^[0-9]+\.[0-9]+') + echo "branch_name=v${MAJOR_MINOR_VERSION}.x" >> $GITHUB_OUTPUT + echo "is_rc=false" >> $GITHUB_OUTPUT + fi + + lib_release: + needs: [safety_check,pre_config] + runs-on: ubuntu-latest + environment: release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - name: "Checkout Repository" + uses: actions/checkout@v4 + + - name: "Setup Python" + uses: actions/setup-python@v5 + with: + python-version: "3.12" + cache: "pip" + cache-dependency-path: "requirements/_release.txt" + + - name: "Install Release Dependencies" + run: | + python -m pip install --upgrade pip + pip install -r requirements/_release.txt + + - name: "Prepare and Update CHANGELOG.md" + run: | + VERSION=${{ needs.pre_config.outputs.version }} + DATE=$(date +'%Y-%m-%d') + sed -i "s/## \[Unreleased\]/## [$VERSION] - $DATE/" CHANGELOG.md + sed -i "0,/## \[$VERSION\]/ s|## \[$VERSION\]|## [Unreleased]\n\n### Added\n\n### Changed\n\n### Fixed\n\n### Removed\n\n$&|" CHANGELOG.md + sed -i "s|\[Unreleased\]:.*|[Unreleased]: https://github.com/Pycord-Development/pycord/compare/v$VERSION...HEAD\n[$VERSION]: https://github.com/Pycord-Development/pycord/compare/v$(git describe --tags --abbrev=0 @^)...v$VERSION|" CHANGELOG.md + echo "[Unreleased]: https://github.com/Pycord-Development/pycord/compare/v$VERSION...HEAD" >> CHANGELOG.md + git add CHANGELOG.md + git commit -m "chore(release): update CHANGELOG for version $VERSION" + + - name: "Commit and Push Changelog to Master" + run: | + git config user.name "GitHub Actions" + git config user.email "actions@github.com" + git add CHANGELOG.md + git commit -m "chore(release): update CHANGELOG for version ${{ needs.pre_config.outputs.version }}" + git push origin HEAD:master + + - name: "Push Changelog to Version Branch" + run: | + git push origin HEAD:${{ needs.pre_config.outputs.branch_name }} + + - name: "Create Git Tag" + run: | + git config user.name "GitHub Actions" + git config user.email "actions@github.com" + VERSION=${{ needs.pre_config.outputs.version }} + git tag -s v$VERSION -m "Release version $VERSION" + git push origin v$VERSION + + - name: "Verify Version" + run: python -m setuptools_scm + + - name: "Build Package" + run: | + python3 -m build --sdist + python3 -m build --wheel + + - name: "Create GitHub Release" + uses: softprops/action-gh-release@v2.0.8 + with: + tag_name: "v${{ needs.pre_config.outputs.version }}" + name: "v${{ needs.pre_config.outputs.version }}" + generate_release_notes: true + draft: false + prerelease: ${{ needs.pre_config.outputs.is_rc == 'true' }} + files: | + dist/*.whl + dist/*.tar.gz + token: ${{ secrets.GITHUB_TOKEN }} + make_latest: true + + - name: "Publish package distributions to PyPI" + uses: pypa/gh-action-pypi-publish@v1.9.0 + env: + name: pypi + url: https://pypi.org/p/pycord + with: + password: ${{ secrets.PYPI_TOKEN }} + + docs_release: + runs-on: ubuntu-latest + needs: [lib_release,pre_config] + if: needs.pre_config.outputs.is_rc == 'false' || (needs.pre_config.outputs.is_rc == 'true' && endsWith(needs.pre_config.outputs.version, '.0-rc1')) + environment: release + steps: + - name: "Sync Versions on Read the Docs" + run: | + curl --location --request POST 'https://readthedocs.org/api/v3/projects/pycord/sync-versions/' \ + --header 'Content-Type: application/json' \ + --header "Authorization: Token ${{ secrets.READTHEDOCS_TOKEN }}" + + - name: "Activate and Show Version on Read the Docs" + run: | + VERSION=${{ needs.pre_config.outputs.version }} + MAJOR_MINOR_VERSION=$(echo $VERSION | grep -oE '^[0-9]+\.[0-9]+') + PATCH_VERSION=${VERSION##*.} + if [[ $PATCH_VERSION =~ ^[0-9]+$ ]]; then + DOCS_VERSION="v$VERSION" + else + DOCS_VERSION="v$MAJOR_MINOR_VERSION.x" + fi + curl --location --request PATCH "https://readthedocs.org/api/v3/projects/pycord/versions/$DOCS_VERSION/" \ + --header 'Content-Type: application/json' \ + --header "Authorization: Token ${{ secrets.READTHEDOCS_TOKEN }}" \ + --data '{ + "active": true, + "hidden": false + }' + + determine_milestone_id: + runs-on: ubuntu-latest + needs: [lib_release,docs_release,pre_config] + if: ${{ !contains(needs.pre_config.outputs.version, '-') && endsWith(needs.pre_config.outputs.version, '.0') }} + outputs: + milestone_version: ${{ steps.extract_version.outputs.milestone_version }} + environment: release + steps: + - name: "Extract Milestone Version" + id: extract_version + run: | + VERSION=${{ needs.pre_config.outputs.version }} + MILESTONE_VERSION=$(echo $VERSION | grep -oE '^[0-9]+\.[0-9]+') + echo "milestone_version=$MILESTONE_VERSION" >> $GITHUB_OUTPUT + + close_milestone: + runs-on: ubuntu-latest + needs: [determine_milestone_id,pre_config] + if: ${{ !contains(needs.pre_config.outputs.version, '-') && endsWith(needs.pre_config.outputs.version, '.0') }} + environment: release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - name: "Close Milestone" + run: gh milestone edit "v${{ needs.determine_milestone_id.outputs.milestone_version }}" --state closed + + - name: "Create New Milestone" + run: | + NEW_MILESTONE_VERSION=$(echo ${{ needs.determine_milestone_id.outputs.milestone_version }} | awk -F. '{print $1"."$2+1}') + gh milestone create "v${NEW_MILESTONE_VERSION}" + + - name: "Move Open Issues and PRs" + run: | + gh issue list --milestone "v${{ needs.determine_milestone_id.outputs.milestone_version }}" --state open | while read issue + do + gh issue edit $issue --milestone "v${NEW_MILESTONE_VERSION}" + done + + inform_discord: + runs-on: ubuntu-latest + needs: [lib_release,docs_release,close_milestone,pre_config] + environment: release + steps: + - name: "Notify Discord" + run: | + VERSION=${{ needs.pre_config.outputs.version }} + MAJOR_MINOR_VERSION=$(echo $VERSION | grep -oE '^[0-9]+\.[0-9]+') + DOCS_URL="" + GITHUB_COMPARE_URL="" + GITHUB_RELEASE_URL="" + PYPI_RELEASE_URL="" + ANNOUNCEMENT="## <:pycord:1063211537008955495> Pycord v${MAJOR_MINOR_VERSION} is out!\n\n" + ANNOUNCEMENT="${ANNOUNCEMENT}[@everyone]\n\n" + ANNOUNCEMENT="${ANNOUNCEMENT}You can view the changelog here: <$DOCS_URL>\n\n" + ANNOUNCEMENT="${ANNOUNCEMENT}Feel free to take a look at the [GitHub changelog]($GITHUB_COMPARE_URL), [GitHub release page]($GITHUB_RELEASE_URL) and the [PyPI release page]($PYPI_RELEASE_URL).\n\n" + ANNOUNCEMENT="${ANNOUNCEMENT}You can install this version by running the following command:\n\`\`\`sh\npip install -U py-cord==$VERSION\n\`\`\`\n\n" + curl -H "Content-Type: application/json" \ + -X POST \ + -d "{\"content\":\"$ANNOUNCEMENT\"}" \ + ${{ secrets.DISCORD_WEBHOOK_URL }} diff --git a/README.rst b/README.rst index 5e82acb518..19503bd234 100644 --- a/README.rst +++ b/README.rst @@ -1,9 +1,9 @@ -Pycord +.. image:: https://raw.githubusercontent.com/Pycord-Development/pycord-next/main/docs/assets/pycord-v3.png + :alt: Pycord v3 +Pycord is a modern, easy to use, feature-rich, and async ready API wrapper for Discord written in Python. + ====== -.. image:: https://img.shields.io/discord/881207955029110855?label=discord&style=for-the-badge&logo=discord&color=5865F2&logoColor=white - :target: https://pycord.dev/discord - :alt: Discord server invite .. image:: https://img.shields.io/pypi/v/py-cord.svg?style=for-the-badge&logo=pypi&color=yellowgreen&logoColor=white :target: https://pypi.python.org/pypi/py-cord :alt: PyPI version info @@ -16,11 +16,16 @@ Pycord .. image:: https://img.shields.io/github/v/release/Pycord-Development/pycord?include_prereleases&label=Latest%20Release&logo=github&sort=semver&style=for-the-badge&logoColor=white :target: https://github.com/Pycord-Development/pycord/releases :alt: Latest release + +.. image:: https://img.shields.io/discord/881207955029110855?label=discord&style=for-the-badge&logo=discord&color=5865F2&logoColor=white + :target: https://pycord.dev/discord + :alt: Discord server invite + .. image:: https://badges.crowdin.net/badge/dark/crowdin-on-light.png :target: https://translations.pycord.dev/documentation/?utm_source=badge&utm_medium=referral&utm_campaign=badge-add-on :alt: Crowdin | Agile localization for tech companies - Pycord is a modern, easy to use, feature-rich, and async ready API wrapper for Discord written in Python. +====== Key Features ------------