Skip to content

ci: Use trusted publishing to publish to PyPI #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 14, 2025
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
41 changes: 17 additions & 24 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,38 +14,31 @@
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"ms-python.black-formatter",
"ms-python.flake8",
"njpwerner.autodocstring"
"charliermarsh.ruff",
"ms-python.mypy-type-checker",
"timonwong.shellcheck"
],
"settings": {
"python.analysis.extraPaths": [
"/software/venv/lib/python3.8/site-packages/"
],
"python.defaultInterpreterPath": "/software/venv/bin/python",
"python.formatting.blackPath": "/software/venv/bin/black",
"python.formatting.provider": "black",
"python.linting.enabled": true,
"python.linting.flake8Enabled": true,
"python.linting.flake8Path": "/software/venv/bin/flake8",
"python.linting.mypyEnabled": true,
"python.linting.mypyPath": "/software/venv/bin/mypy",
"python.linting.pylintEnabled": false,
"python.testing.cwd": "/project",
"python.testing.pytestEnabled": true,
"python.testing.unittestEnabled": false,
"python.defaultInterpreterPath": "/software/venv/bin/python3",
"python.testing.pytestArgs": [
"tests",
"-p",
"nydok"
"."
],
"python.linting.mypyArgs": [],
"mypy-type-checker.importStrategy": "fromEnvironment",
"ruff.importStrategy": "fromEnvironment",
"python.formatting.provider": "none",
"[python]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
},
"python.testing.unittestEnabled": false,
"terminal.integrated.defaultProfile.linux": "bash"
"source.fixAll.ruff": "explicit",
"source.organizeImports.ruff": "explicit"
},
"editor.defaultFormatter": "charliermarsh.ruff"
}
}
}
}
}
}
3 changes: 0 additions & 3 deletions .flake8

This file was deleted.

40 changes: 31 additions & 9 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ jobs:
id: deployment
uses: actions/deploy-pages@v2

release:
name: Release
build:
name: Build package
needs: [test]
if: startsWith(github.ref, 'refs/tags/v')
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
permissions:
contents: write
Expand All @@ -68,9 +68,31 @@ jobs:
with:
body_path: changelog.md

- name: Publish to PyPI
env:
VERSION: ${{ github.ref_name }}
USERNAME: __token__
PASSWORD: ${{ secrets.PYPI_TOKEN }}
run: make publish
- name: Build package dist
run: make build-package

- name: Store package artifact
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
retention-days: 1

pypi-publish:
needs: [build]
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
name: Upload release to PyPI
runs-on: ubuntu-latest
environment:
name: release
url: https://pypi.org/p/nydok
permissions:
id-token: write
steps:
- name: Download dist artifacts
uses: actions/download-artifact@v4
with:
name: dist
path: dist/
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
13 changes: 0 additions & 13 deletions .vscode/project.code-workspace

This file was deleted.

22 changes: 6 additions & 16 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
# Update peridically to latest specific tag
FROM ubuntu AS base-image

ENV DEBIAN_FRONTEND=noninteractive
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8

# gettext-base -> envsubst
RUN apt-get update && apt-get install -y \
git \
curl \
wget \
gawk \
less \
ripgrep \
python3 \
python3-pip \
python3-venv \
gettext-base \
&& rm -rf /var/lib/apt/lists/*

# Use normal user in container
Expand All @@ -30,19 +26,13 @@ ENV PATH=/software/bin:$PATH
COPY --chown=dockeruser poetry.lock pyproject.toml /software/
ENV PATH=/software/venv/bin:/home/dockeruser/.local/bin:$PATH \
VIRTUAL_ENV=/software/venv
RUN pip3 install "poetry==1.5.0" && \

RUN curl -sSL https://install.python-poetry.org | python3 - && \
python3 -m venv /software/venv && \
/software/venv/bin/pip3 install pip=="22.3" && \
cd /software && \
poetry install --no-interaction --no-ansi --no-root

# To support running container as any UID, set $HOME explicitly
ENV HOME=/home/dockeruser

# Ensure any UID can read/write all relevant files
USER root
RUN chmod o+rwX -R /home /software
USER dockeruser

# Install git-cliff for changelog generation in CI
RUN cd /software/ && \
Expand All @@ -53,14 +43,14 @@ RUN cd /software/ && \
cd bin && \
ln -s ../git-cliff-0.5.0/git-cliff .

# To support running container as any UID, set $HOME explicitly
ENV HOME=/home/dockeruser

# Files are meant to be mounted in locally, don't copy in data as it can lead to confusion
WORKDIR /project

# Default user is root, container is meant to be run on rootless Docker and Github Actions
USER root
# We've added some software,
# ensure (again) any UID can read/write all relevant files
RUN chmod o+rwX -R /home /software

# Nicer prompt for shell in dev containers
RUN echo "PS1='[\[\e[31m\]\A\[\e[m\]] \[\e[33m\]\w\[\e[m\]: '" >> $HOME/.bashrc
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2023 Nykode Therapeutics
Copyright (c) 2025 Nykode Therapeutics

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
Expand All @@ -17,4 +17,4 @@ 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.
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ FROM_REF ?= $(shell git describe --abbrev=0 --tags $(shell git rev-parse HEAD^))
TO_REF ?= $(shell git rev-parse --short HEAD)
VERSION ?= $(TO_REF)

.PHONY: image-name build test lint docs docs-serve shell publish
.PHONY: build test lint docs docs-serve shell build-package

build:
docker build -t $(IMAGE_NAME) .
Expand Down Expand Up @@ -72,7 +72,7 @@ shell: build
$(IMAGE_NAME) \
bash -c 'poetry install && bash'

publish: build
build-package: build
docker run \
--rm $(USE_TTY) \
-e VERSION \
Expand All @@ -82,4 +82,4 @@ publish: build
-v $(PWD):/project \
-u $(DOCKER_USER) \
$(IMAGE_NAME) \
ops/dev/publish-package.sh
ops/dev/build-package.sh
6 changes: 0 additions & 6 deletions nydok/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ def _load_json(path: Path):
help="Output path (default: stdout).",
)
def traceability_matrix(result, base_prefix, categories, output):

if categories:
assert len(categories.split(",")) % 2 == 0, "Categories must be in pairs."
categories = list(zip(categories.split(",")[::2], categories.split(",")[1::2]))
Expand Down Expand Up @@ -83,7 +82,6 @@ def traceability_matrix(result, base_prefix, categories, output):
help="Output path (default: stdout).",
)
def risk_assessment(result, output):

data = _load_json(Path(result))
report = create_risk_report(data["risk_assessments"])

Expand All @@ -103,7 +101,6 @@ def risk_assessment(result, output):
help="Output path (default: stdout).",
)
def test_overview(result, output):

data = _load_json(Path(result))
report = create_test_overview_report(
data["requirements"].values(),
Expand All @@ -125,7 +122,6 @@ def test_overview(result, output):
help="Output path (default: stdout).",
)
def test_cases(result, output):

data = _load_json(Path(result))
report = create_test_case_report(
data["requirements"].values(),
Expand Down Expand Up @@ -166,7 +162,6 @@ def test_cases(result, output):
help="Output path (default: stdout).",
)
def code_review(repo_path, to_ref, from_ref, output):

report = create_codereview_report(
repo_path=repo_path,
to_ref=to_ref,
Expand Down Expand Up @@ -207,7 +202,6 @@ def code_review(repo_path, to_ref, from_ref, output):
help="Output path (default: stdout).",
)
def pipeline_logs(repo_path, pipeline_id, job_names, output):

job_names = job_names.split(",") if job_names else None

report = create_pipeline_logs_report(
Expand Down
12 changes: 4 additions & 8 deletions nydok/exception.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
class DuplicateRequirementException(Exception):
...
class DuplicateRequirementException(Exception): ...


class FailedTestCaseException(Exception):
...
class FailedTestCaseException(Exception): ...


class MissingTestCaseException(Exception):
...
class MissingTestCaseException(Exception): ...


class RiskPriorityExceedsThresholdException(Exception):
...
class RiskPriorityExceedsThresholdException(Exception): ...
15 changes: 6 additions & 9 deletions nydok/gitlab.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ def get_gitlab_token() -> str:


def _get_paginated_results(url: str, params: Dict[str, Any]) -> List[Any]:

params = dict(params)
params.setdefault("per_page", 100)

Expand All @@ -33,9 +32,9 @@ def _get_results(next_page: Optional[str] = None):
params=params,
headers={"Authorization": f"Bearer {get_gitlab_token()}"},
)
assert (
resp.status_code == 200
), f"Resource {fetch_url} returned status code {resp.status_code}.\n{resp.text}"
assert resp.status_code == 200, (
f"Resource {fetch_url} returned status code {resp.status_code}.\n{resp.text}"
)

return resp.json(), resp.links.get("next", {}).get("url")

Expand All @@ -54,9 +53,9 @@ def get_commit_for_tag(repo_path: str, tag: str) -> str:
fetch_url,
headers={"Authorization": f"Bearer {get_gitlab_token()}"},
)
assert (
resp.status_code == 200
), f"Resource {fetch_url} returned status code {resp.status_code}.\n{resp.text}"
assert resp.status_code == 200, (
f"Resource {fetch_url} returned status code {resp.status_code}.\n{resp.text}"
)
return resp.json()["commit"]["id"]


Expand All @@ -83,7 +82,6 @@ def get_commits_for_ref(


def fetch_mergerequests(repo_path: str) -> List[Dict[str, str]]:

url_encoded_repo_path = quote_plus(repo_path)

api_mrs = _get_paginated_results(
Expand All @@ -110,7 +108,6 @@ def fetch_mergerequests(repo_path: str) -> List[Dict[str, str]]:
def get_pipeline_logs(
repo_path: str, pipeline_id: int, job_names: Optional[List[str]] = None
) -> Dict[str, str]:

url_encoded_repo_path = quote_plus(repo_path)

api_jobs = _get_paginated_results(
Expand Down
1 change: 0 additions & 1 deletion nydok/markdown_ext/markdown_nydok.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ def test(self, parent, block):
return bool(self.RE.match(block))

def run(self, parent, blocks):

# Check fr multiple items in one block.
items = self.get_items(blocks.pop(0))

Expand Down
5 changes: 0 additions & 5 deletions nydok/plugin/junit.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@

class JUnitFile(pytest.File):
def collect(self):

with open(self.fspath) as f:

xml_data = lxml.etree.parse(f)
testsuites = xml_data.getroot()

Expand All @@ -32,7 +30,6 @@ def collect(self):
# If there are failures, we select the first failure.
chosen_testcases: Dict[str, JUnitItem] = {}
for testcase in testcases:

name = testcase.attrib["name"]
classname = testcase.attrib.get("classname", "")
# file = testcase.attrib.get("file", "")
Expand All @@ -57,7 +54,6 @@ def collect(self):

# Parse out references
for re_result in re.finditer(pattern, name):

matches = re_result.groupdict()
refs = []
if matches.get("refs"):
Expand Down Expand Up @@ -96,7 +92,6 @@ def __init__(
self.failures: List[str] = failures

def runtest(self):

if not self.test_case.passed:
raise FailedTestCaseException()

Expand Down
Loading