Skip to content

Commit 48359cb

Browse files
authored
Merge pull request #2 from graphqlient/develop
ci: add release pipeline
2 parents 4c93938 + 0bb699d commit 48359cb

File tree

31 files changed

+437
-212
lines changed

31 files changed

+437
-212
lines changed

.deepsource.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ version = 1
44
name = "python"
55

66
[analyzers.meta]
7-
runtime_version = "3.x.x"
7+
runtime_version = "3.x.x"

.github/dependabot.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
version: 2
2+
updates:
3+
# GitHub Actions
4+
- package-ecosystem: "github-actions"
5+
directory: "/"
6+
schedule:
7+
interval: "monthly"
8+
commit-message:
9+
prefix: ci
10+
# Python
11+
- package-ecosystem: "pip"
12+
directory: "/"
13+
schedule:
14+
interval: "monthly"
15+
commit-message:
16+
prefix: ci

.github/workflows/deploy.yml

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
name: Deploy
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
jobs:
9+
release:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: write
13+
14+
steps:
15+
- uses: actions/checkout@v4
16+
with:
17+
fetch-depth: 0
18+
19+
- name: Install uv
20+
uses: astral-sh/setup-uv@v3
21+
22+
- name: Set up Python 3
23+
run: uv python install 3.12
24+
25+
- name: Install the latest version of rye
26+
uses: eifinger/setup-rye@v4
27+
28+
- name: Install dependencies
29+
run: rye sync
30+
31+
- name: Install dependencies
32+
run: rye install git-cliff --force
33+
34+
- name: Determine next version
35+
id: get_version
36+
run: |
37+
NEW_VERSION=$(rye run git-cliff --bumped-version)
38+
echo "QLIENT_NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV
39+
40+
- name: Generate a changelog
41+
uses: orhun/git-cliff-action@v4
42+
id: git-cliff
43+
with:
44+
config: cliff.toml
45+
args: --verbose --tag="$QLIENT_NEW_VERSION" --unreleased
46+
env:
47+
OUTPUT: CHANGELOG.md
48+
49+
- name: Build package
50+
run: rye build --all --clean
51+
52+
- name: Create and push the new tag
53+
run: |
54+
git config --global user.name 'github-actions[bot]'
55+
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
56+
git tag $QLIENT_NEW_VERSION
57+
git push origin $QLIENT_NEW_VERSION
58+
env:
59+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
60+
61+
- name: Create Release
62+
id: create_release
63+
uses: softprops/action-gh-release@v2
64+
with:
65+
tag_name: $QLIENT_NEW_VERSION
66+
name: $QLIENT_NEW_VERSION
67+
draft: true
68+
prerelease: true
69+
body_path: CHANGELOG.md
70+
files: |
71+
dist/*
72+
generate_release_notes: false
73+
env:
74+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/qa.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: QA
2+
3+
on:
4+
push:
5+
branches:
6+
- '**'
7+
8+
jobs:
9+
check-code-quality:
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- uses: actions/checkout@v4
14+
15+
- name: Install uv
16+
uses: astral-sh/setup-uv@v3
17+
18+
- name: Set up Python 3
19+
run: uv python install 3.12
20+
21+
- name: Install the latest version of rye
22+
uses: eifinger/setup-rye@v4
23+
24+
- name: Install dependencies
25+
run: rye sync
26+
27+
- name: Install dependencies
28+
run: |
29+
rye install pre-commit --force
30+
rye install commitizen --force
31+
rye install docformatter --features tomli --force
32+
33+
- name: Check commit message with Commitizen
34+
run: rye run cz check -m "${{ github.event.head_commit.message }}"
35+
36+
- name: Run docformatter
37+
run: rye run docformatter --check --config ./pyproject.toml .
38+
39+
- name: Run pre-commit checks
40+
run: rye run pre-commit run --all-files
41+
42+
- name: After script
43+
run: echo "Pre-commit checks completed."

.github/workflows/test.yml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
name: Qlient Core - Test
1+
name: Test
22

33
on:
44
pull_request:
5-
branches: [ "main" ]
5+
branches:
6+
- main
67

78
jobs:
89
test:
@@ -16,7 +17,7 @@ jobs:
1617
runs-on: ${{ matrix.os }}
1718

1819
steps:
19-
- uses: actions/checkout@v3
20+
- uses: actions/checkout@v4
2021
- name: Install uv
2122
uses: astral-sh/setup-uv@v3
2223
- name: Set up Python ${{ matrix.python-version }}
@@ -35,7 +36,7 @@ jobs:
3536
run: |
3637
# Install deepsource CLI
3738
curl https://deepsource.io/cli | sh
38-
39+
3940
# From the root directory, run the report coverage command
4041
./bin/deepsource report --analyzer test-coverage --key python --value-file ./coverage.xml
4142

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ wheels/
1111

1212
_version.py
1313

14-
.idea/
14+
.idea/

cliff.toml

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
[remote.github]
2+
owner = "graphqlient"
3+
repo = "qlient"
4+
5+
[changelog]
6+
body = """
7+
## What's Changed
8+
9+
{%- if version %} in {{ version }}{%- endif -%}
10+
{% for group, commits in commits | group_by(attribute="group") %}
11+
### {{ group | upper_first }}
12+
{%- for commit in commits %}
13+
{% if commit.remote.pr_title -%}
14+
{%- set commit_message = commit.remote.pr_title -%}
15+
{%- else -%}
16+
{%- set commit_message = commit.message -%}
17+
{%- endif -%}
18+
* {{ commit_message | split(pat="\n") | first | trim }}\
19+
{% if commit.remote.username %} by @{{ commit.remote.username }}{%- endif -%}
20+
{% if commit.remote.pr_number %} in \
21+
[#{{ commit.remote.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.remote.pr_number }}) \
22+
{%- endif %}
23+
{%- endfor -%}
24+
{%- endfor -%}
25+
26+
{%- if github -%}
27+
{% if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %}
28+
{% raw %}\n{% endraw -%}
29+
## New Contributors
30+
{%- endif %}\
31+
{% for contributor in github.contributors | filter(attribute="is_first_time", value=true) %}
32+
* @{{ contributor.username }} made their first contribution
33+
{%- if contributor.pr_number %} in \
34+
[#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \
35+
{%- endif %}
36+
{%- endfor -%}
37+
{%- endif -%}
38+
39+
{% if version %}
40+
{% if previous.version %}
41+
**Full Changelog**: {{ self::remote_url() }}/compare/{{ previous.version }}...{{ version }}
42+
{% endif %}
43+
{% else -%}
44+
{% raw %}\n{% endraw %}
45+
{% endif %}
46+
47+
{%- macro remote_url() -%}
48+
https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}
49+
{%- endmacro -%}
50+
"""
51+
# remove the leading and trailing whitespace from the template
52+
trim = true
53+
# template for the changelog footer
54+
footer = """"""
55+
# postprocessors
56+
postprocessors = []
57+
58+
[git]
59+
# parse the commits based on https://www.conventionalcommits.org
60+
conventional_commits = true
61+
# filter out the commits that are not conventional
62+
filter_unconventional = true
63+
# process each line of a commit as an individual commit
64+
split_commits = false
65+
# regex for preprocessing the commit messages
66+
commit_preprocessors = [
67+
# remove issue numbers from commits
68+
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "" },
69+
]
70+
# regex for parsing and grouping commits
71+
commit_parsers = [
72+
{ message = "^feat", group = "<!-- 0 -->⛰️ Features" },
73+
{ message = "^fix", group = "<!-- 1 -->🐛 Bug Fixes" },
74+
{ message = "^doc", group = "<!-- 3 -->📚 Documentation" },
75+
{ message = "^perf", group = "<!-- 4 -->⚡ Performance" },
76+
{ message = "^refactor", group = "<!-- 2 -->🚜 Refactor" },
77+
{ message = "^style", group = "<!-- 5 -->🎨 Styling" },
78+
{ message = "^test", group = "<!-- 6 -->🧪 Testing" },
79+
{ message = "^chore|^ci", group = "<!-- 7 -->⚙️ Miscellaneous Tasks" },
80+
{ body = ".*security", group = "<!-- 8 -->🛡️ Security" },
81+
{ message = "^revert", group = "<!-- 9 -->◀️ Revert" },
82+
]
83+
84+
# filter out the commits that are not matched by commit parsers
85+
filter_commits = false
86+
# sort the tags topologically
87+
topo_order = false
88+
# sort the commits inside sections by oldest/newest order
89+
sort_commits = "newest"

packages/qlient-aiohttp/src/qlient/aiohttp/backends.py

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ async def close_all():
3434

3535

3636
class AIOHTTPBackend(AsyncBackend):
37-
"""The AIOHTTP Backend
37+
"""The AIOHTTP Backend.
3838
3939
Examples:
4040
>>> backend = AIOHTTPBackend("https://swapi-graphql.netlify.app/.netlify/functions/index")
@@ -43,7 +43,7 @@ class AIOHTTPBackend(AsyncBackend):
4343

4444
@classmethod
4545
def generate_subscription_id(cls) -> str:
46-
"""Class method to generate unique subscription ids
46+
"""Class method to generate unique subscription ids.
4747
4848
Returns:
4949
A unique subscription id
@@ -52,7 +52,7 @@ def generate_subscription_id(cls) -> str:
5252

5353
@staticmethod
5454
def make_payload(request: GraphQLRequest) -> dict[str, Any]:
55-
"""Static method for generating the request payload
55+
"""Static method for generating the request payload.
5656
5757
Args:
5858
request: holds the graphql request
@@ -67,12 +67,12 @@ def make_payload(request: GraphQLRequest) -> dict[str, Any]:
6767
}
6868

6969
def __init__(
70-
self,
71-
endpoint: str,
72-
ws_endpoint: str | None = None,
73-
session: aiohttp.ClientSession | None = None,
74-
subscription_protocols: list[str] | None = None,
75-
settings: AIOHTTPSettings | None = None,
70+
self,
71+
endpoint: str,
72+
ws_endpoint: str | None = None,
73+
session: aiohttp.ClientSession | None = None,
74+
subscription_protocols: list[str] | None = None,
75+
settings: AIOHTTPSettings | None = None,
7676
):
7777
if settings is None:
7878
settings = AIOHTTPSettings()
@@ -92,7 +92,7 @@ def __init__(
9292
@property
9393
@asynccontextmanager
9494
async def session(self) -> aiohttp.ClientSession:
95-
"""Property to get the session to use for requests
95+
"""Property to get the session to use for requests.
9696
9797
If the session is pre-defined, use that session,
9898
otherwise create a new aiohttp.ClientSession.
@@ -128,12 +128,12 @@ async def execute_query(self, request: GraphQLRequest) -> GraphQLResponse:
128128
logger.debug(f"Sending request: {payload_str}")
129129
async with self.session as session:
130130
async with session.post(
131-
self.endpoint,
132-
data=payload_str,
133-
headers={
134-
"Content-Type": "application/json; charset=utf-8",
135-
"Accept": "application/json; charset=utf-8",
136-
}
131+
self.endpoint,
132+
data=payload_str,
133+
headers={
134+
"Content-Type": "application/json; charset=utf-8",
135+
"Accept": "application/json; charset=utf-8",
136+
},
137137
) as response:
138138
response_str = await response.text()
139139
response_body = self.settings.json_loads(response_str)
@@ -166,7 +166,6 @@ async def execute_subscription(self, request: GraphQLSubscriptionRequest) -> Gra
166166
request: holds the request to execute
167167
168168
Returns:
169-
170169
"""
171170
payload = self.make_payload(request)
172171
async with self.session as session:

packages/qlient-aiohttp/src/qlient/aiohttp/clients.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""The client implementation for aiohttp"""
1+
"""The client implementation for aiohttp."""
22

33
from qlient.aiohttp.backends import AIOHTTPBackend
44
from qlient.core import AsyncClient, Backend

packages/qlient-aiohttp/src/qlient/aiohttp/exceptions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33

44
class SubscriptionException(QlientException):
5-
"""Base class for all subscription related exceptions"""
5+
"""Base class for all subscription related exceptions."""
66

77

88
class ConnectionRejected(SubscriptionException):
9-
"""Indicates that the server did not acknowledge (rejected) the connection"""
9+
"""Indicates that the server did not acknowledge (rejected) the connection."""

0 commit comments

Comments
 (0)