Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 172 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
name: Release Pipeline

on:
workflow_dispatch:
inputs:
mode:
description: "Choose whether to create a new tagged release or deploy an existing tag"
required: true
type: choice
default: release
options:
- release
- deploy-existing-tag
version:
description: "Version without the v prefix (examples: 1.2.0, 1.2.0-rc.1)"
required: true

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: release-pages
cancel-in-progress: false

jobs:
validate:
runs-on: ubuntu-latest
outputs:
tag_name: ${{ steps.meta.outputs.tag_name }}
source_ref: ${{ steps.meta.outputs.source_ref }}
is_prerelease: ${{ steps.meta.outputs.is_prerelease }}
should_create_release: ${{ steps.meta.outputs.should_create_release }}
steps:
- name: Validate version format
env:
VERSION: ${{ inputs.version }}
run: |
python - <<'PY'
import os, re, sys
version = os.environ["VERSION"]
pattern = r"\d+\.\d+\.\d+(?:-(?:alpha|beta|rc)\.\d+)?"
if not re.fullmatch(pattern, version):
print(f"Invalid version: {version}")
print("Expected formats: 1.2.0, 1.2.0-alpha.1, 1.2.0-beta.1, 1.2.0-rc.1")
sys.exit(1)
PY

- name: Restrict new releases to main
if: inputs.mode == 'release'
run: |
if [[ "${{ github.ref_name }}" != "main" ]]; then
echo "New releases must be dispatched from the main branch."
exit 1
fi

- name: Checkout repository metadata
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Resolve release metadata
id: meta
env:
MODE: ${{ inputs.mode }}
VERSION: ${{ inputs.version }}
DISPATCH_REF: ${{ github.ref_name }}
run: |
TAG_NAME="v${VERSION}"

if [[ "$MODE" == "release" ]]; then
if git ls-remote --exit-code --tags origin "refs/tags/${TAG_NAME}" >/dev/null 2>&1; then
echo "Tag ${TAG_NAME} already exists on origin."
exit 1
fi
SOURCE_REF="${GITHUB_SHA}"
SHOULD_CREATE_RELEASE=true
else
if ! git ls-remote --exit-code --tags origin "refs/tags/${TAG_NAME}" >/dev/null 2>&1; then
echo "Tag ${TAG_NAME} does not exist on origin."
exit 1
fi
SOURCE_REF="${TAG_NAME}"
SHOULD_CREATE_RELEASE=false
fi

if [[ "$VERSION" == *-* ]]; then
IS_PRERELEASE=true
else
IS_PRERELEASE=false
fi

{
echo "tag_name=${TAG_NAME}"
echo "source_ref=${SOURCE_REF}"
echo "is_prerelease=${IS_PRERELEASE}"
echo "should_create_release=${SHOULD_CREATE_RELEASE}"
} >> "$GITHUB_OUTPUT"

build:
runs-on: ubuntu-latest
needs: validate
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.validate.outputs.source_ref }}

- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm

- name: Set Eleventy path prefix
run: |
REPO_NAME="${GITHUB_REPOSITORY#*/}"
if [[ "$REPO_NAME" == *.github.io ]]; then
echo "ELEVENTY_PATH_PREFIX=/" >> "$GITHUB_ENV"
else
echo "ELEVENTY_PATH_PREFIX=/${REPO_NAME}/" >> "$GITHUB_ENV"
fi

- run: npm ci
- run: npm run build:css
- run: npx eleventy --pathprefix="$ELEVENTY_PATH_PREFIX"
- run: npm run check

- uses: actions/upload-pages-artifact@v3
with:
path: _site

release:
runs-on: ubuntu-latest
needs: [validate, build]
if: needs.validate.outputs.should_create_release == 'true'
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Create and push tag
env:
TAG_NAME: ${{ needs.validate.outputs.tag_name }}
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git fetch --tags origin
git tag "$TAG_NAME" "$GITHUB_SHA"
git push origin "$TAG_NAME"

- name: Create GitHub release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.validate.outputs.tag_name }}
generate_release_notes: true
prerelease: ${{ needs.validate.outputs.is_prerelease == 'true' }}

deploy:
runs-on: ubuntu-latest
needs: [validate, build, release]
if: |
always() &&
needs.build.result == 'success' &&
(needs.release.result == 'success' || needs.release.result == 'skipped')
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
2 changes: 1 addition & 1 deletion _includes/footer.njk
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
{% set projectLabel = "Project" if not isUzPage else "Loyiha" %}
{% set homeLabel = "Home" if not isUzPage else "Bosh sahifa" %}
{% set tutorialLabel = "Tutorials" if not isUzPage else "Darslar" %}
{% set toolsLabel = "Online IDE" if not isUzPage else "Onlayn IDE" %}
{% set toolsLabel = "Python Lab" %}
{% set joinGithubLabel = "Join on GitHub" if not isUzPage else "GitHub'da qo'shiling" %}
{% set contributeLabel = "Contributing Guide" if not isUzPage else "Hissa qo'shish qo'llanmasi" %}
{% set issueLabel = "Report an Issue" if not isUzPage else "Muammo haqida yozing" %}
Expand Down
10 changes: 5 additions & 5 deletions _includes/head.njk
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
{% set pageDescription = description or defaultSiteDescription %}
{% set metaKeywords = site.keywordsUz if (langCode == 'uz' and site.keywordsUz) else site.keywords %}
{% if isHomepage %}
{% set pageTitle = ("Python dasturlash darslari | " + site.name) if langCode == 'uz' else ("Python Programming Tutorial | " + site.name) %}
{% set pageTitle = ("Pythonni bepul o'rganing: Boshlang'ichdan advancedgacha darslar | " + site.name) if langCode == 'uz' else ("Learn Python Free: Beginner to Advanced Lessons | " + site.name) %}
{% elif isTutorial %}
{% set pageTitle = (tutorialDisplayTitle + " — Boshlang'ichdan advanced darajagacha to'liq dars") if langCode == 'uz' else (tutorialDisplayTitle + " - Complete Tutorial Basic to Advanced") %}
{% elif title %}
Expand Down Expand Up @@ -33,7 +33,7 @@
<meta property="og:title" content="{{ pageTitle }}">
<meta property="og:type" content="website">
<meta property="og:description" content="{{ pageDescription }}">
<meta property="og:image" content="{{ site.url }}/img/logos/logo-belajarpython-square.png">
<meta property="og:image" content="{{ site.url }}/img/logos/site-logo-square.svg">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="{{ 'Python darslari' if langCode == 'uz' else 'Belajarpython.com - Python Tutorial' }}">
Expand All @@ -43,7 +43,7 @@
<meta name="twitter:creator" content="@belajarpythoncom">
<meta name="twitter:title" content="{{ pageTitle }}">
<meta name="twitter:description" content="{{ pageDescription }}">
<meta name="twitter:image" content="{{ site.url }}/img/logos/logo-belajarpython-square.png">
<meta name="twitter:image" content="{{ site.url }}/img/logos/site-logo-square.svg">

<link rel="icon" href="{{ '/img/favicon.png' | url }}">
<link rel="apple-touch-icon" href="{{ '/img/favicon.png' | url }}">
Expand Down Expand Up @@ -74,14 +74,14 @@
{"@context":"https://schema.org","@type":"WebSite","@id":"{{ site.url }}/#website","url":"{{ site.url }}","name":"{{ site.name }}","description":"{{ pageDescription }}","inLanguage":"{{ 'uz-UZ' if langCode == 'uz' else 'en-US' }}"}
</script>
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"EducationalOrganization","@id":"{{ site.url }}/#organization","name":"{{ site.name }}","url":"{{ site.url }}","logo":"{{ site.url }}/img/logos/logo-belajarpython-square.png","description":"{{ 'Boshlang\\u0027ichdan ilg\\u0027orgacha Python bo\\u0027yicha to\\u0027liq darslar' if langCode == 'uz' else 'Complete Python Tutorial for Beginners to Advanced' }}","foundingDate":"2015","sameAs":["https://github.com/codeuzhub/python-lessons"],"areaServed":{"@type":"Country","name":"Global"},"teaches":["Python Programming","Data Science","Machine Learning","Web Development"]}
{"@context":"https://schema.org","@type":"EducationalOrganization","@id":"{{ site.url }}/#organization","name":"{{ site.name }}","url":"{{ site.url }}","logo":"{{ site.url }}/img/logos/site-logo-square.svg","description":"{{ 'Boshlang\\u0027ichdan ilg\\u0027orgacha Python bo\\u0027yicha to\\u0027liq darslar' if langCode == 'uz' else 'Complete Python Tutorial for Beginners to Advanced' }}","foundingDate":"2015","sameAs":["https://github.com/codeuzhub/python-lessons"],"areaServed":{"@type":"Country","name":"Global"},"teaches":["Python Programming","Data Science","Machine Learning","Web Development"]}
</script>
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"ItemList","itemListElement":[{"@type":"Course","position":1,"name":"{{ 'Python asoslari (Boshlang\\u0027ich)' if langCode == 'uz' else 'Basic Python Tutorial' }}","description":"{{ 'Pythonni o\\u0027rnatishdan boshlab OOPgacha bo\\u0027lgan asosiy tushunchalarni o\\u0027rganing' if langCode == 'uz' else 'Learn Python basics from installation to OOP concepts' }}","provider":{"@type":"Organization","name":"{{ site.name }}"},"educationalLevel":"{{ 'Beginner' if langCode != 'uz' else 'Beginner' }}","inLanguage":"{{ 'uz' if langCode == 'uz' else 'en' }}","isAccessibleForFree":true}]}
</script>
{% else %}
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"Article","headline":"{{ tutorialDisplayTitle if isTutorial else title }}","description":"{{ pageDescription }}","url":"{{ site.url }}{{ page.url }}","inLanguage":"{{ 'uz-UZ' if langCode == 'uz' else 'en-US' }}","publisher":{"@type":"Organization","name":"{{ site.name }}","logo":{"@type":"ImageObject","url":"{{ site.url }}/img/logos/logo-belajarpython-square.png"}}}
{"@context":"https://schema.org","@type":"Article","headline":"{{ tutorialDisplayTitle if isTutorial else title }}","description":"{{ pageDescription }}","url":"{{ site.url }}{{ page.url }}","inLanguage":"{{ 'uz-UZ' if langCode == 'uz' else 'en-US' }}","publisher":{"@type":"Organization","name":"{{ site.name }}","logo":{"@type":"ImageObject","url":"{{ site.url }}/img/logos/site-logo-square.svg"}}}
</script>
{% endif %}

Expand Down
Loading
Loading