Skip to content

Commit cf28c0f

Browse files
authored
Publish to code artifact (#13)
## Why is this change necessary? Need to be able to have workflows that publish to CodeArtifact ## How does this change address the issue? Creates a workflow to publish to the staging repository, and one for the primary repository ## What side effects does this change have? None ## How is this change tested? In a downstream repo that successfully published
1 parent c279c9d commit cf28c0f

File tree

7 files changed

+174
-12
lines changed

7 files changed

+174
-12
lines changed

.copier-answers.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Changes here will be overwritten by Copier
2-
_commit: v0.0.7-44-gea357db
2+
_commit: v0.0.9
33
_src_path: gh:LabAutomationAndScreening/copier-base-template.git
44
description: Copier template for creating Python libraries and executables
55
python_ci_versions:

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ jobs:
112112
113113
- name: install new dependencies
114114
env:
115+
# Provide a fake token so it doesn't attempt to access AWS to generate a new one when the script is run if CodeArtifact is set as the registry
115116
CODEARTIFACT_AUTH_TOKEN: 'faketoken'
116-
UV_NO_CACHE: 'true'
117117
run: |
118118
# Remove any specification of a Python repository having a default other than PyPI...because in this CI pipeline we can only install from PyPI
119119
python $RUNNER_TEMP/replace_private_package_registries.py

extensions/context.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ def hook(self, context: dict[Any, Any]) -> dict[Any, Any]:
2828
context["ephemeral_pulumi_deploy_version"] = "0.0.2"
2929
context["pydantic_version"] = "2.10.6"
3030
context["pyinstaller_version"] = "6.12.0"
31+
context["setuptools_version"] = "76.0.0"
3132

3233
context["gha_checkout"] = "v4.2.2"
3334
context["gha_setup_python"] = "v5.4.0"

template/.devcontainer/code-artifact-auth.sh.jinja

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ if [ -z "$AWS_PROFILE" ] && [ -z "$AWS_ACCESS_KEY_ID" ] && [ -z "$CODEARTIFACT_A
66
echo "No AWS profile, access key, or auth token found, cannot proceed."
77
exit 1
88
else
9-
# Only regenerate the token if it doesn't exist or wasn't already set as an environmental variable (e.g. during CI or passed into a docker image build)
9+
# Only regenerate the token if it wasn't already set as an environmental variable (e.g. during CI or passed into a docker image build)
1010
if [ -z "$CODEARTIFACT_AUTH_TOKEN" ]; then
1111
echo "Fetching CodeArtifact token"
1212
if [ -z "$CI" ]; then
@@ -30,17 +30,19 @@ else
3030
fi
3131

3232
set +x
33-
export CODEARTIFACT_AUTH_TOKEN=$(aws codeartifact get-authorization-token \
33+
CODEARTIFACT_AUTH_TOKEN=$(aws codeartifact get-authorization-token \
3434
--domain {% endraw %}{{ repo_org_name }}{% raw %} \
3535
--domain-owner {% endraw %}{{ aws_central_infrastructure_account_id }}{% raw %} \
3636
--region {% endraw %}{{ aws_org_home_region }}{% raw %} \
3737
--query authorizationToken \
3838
--output text $PROFILE_ARGS)
3939
set -x
4040
fi
41-
41+
# uv sometimes uses has better luck when setting the twine env vars
42+
export TWINE_USERNAME=aws
4243
set +x
4344
export UV_INDEX_CODE_ARTIFACT_PRIMARY_PASSWORD="$CODEARTIFACT_AUTH_TOKEN"
45+
export TWINE_PASSWORD="$CODEARTIFACT_AUTH_TOKEN"
4446
export UV_INDEX_CODE_ARTIFACT_STAGING_PASSWORD="$CODEARTIFACT_AUTH_TOKEN"
4547
set -x
4648

template/.github/workflows/publish.yaml.jinja

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{% raw %}name: Publish to PyPI
1+
{% raw %}name: Publish to Production Package Registry
22

33
on:
44
workflow_dispatch:
@@ -22,7 +22,10 @@ jobs:
2222
- name: Install latest versions of python packages
2323
uses: ./.github/actions/install_deps_uv
2424
with:
25-
python-version: {% endraw %}{{ python_version }}{% raw %}
25+
python-version: {% endraw %}{{ python_version }}{% if python_package_registry == "AWS CodeArtifact" %}{% raw %}
26+
code-artifact-auth-role-name: CoreInfraBaseAccess
27+
code-artifact-auth-role-account-id: {% endraw %}{{ aws_central_infrastructure_account_id }}{% raw %}
28+
code-artifact-auth-region: {% endraw %}{{ aws_org_home_region }}{% endif %}{% raw %}
2629

2730
- name: Set up mutex # Github concurrency management is horrible, things get arbitrarily cancelled if queued up. So using mutex until github fixes itself. When multiple jobs are modifying cache at once, weird things can happen. possible issue is https://github.com/actions/toolkit/issues/658
2831
if: ${{ runner.os != 'Windows' }} # we're just gonna have to YOLO on Windows, because this action doesn't support it yet https://github.com/ben-z/gh-action-mutex/issues/14
@@ -69,7 +72,10 @@ jobs:
6972
- name: Install python tooling
7073
uses: ./.github/actions/install_deps_uv
7174
with:
72-
python-version: ${{ matrix.python-version }}
75+
python-version: ${{ matrix.python-version }}{% endraw %}{% if python_package_registry == "AWS CodeArtifact" %}{% raw %}
76+
code-artifact-auth-role-name: CoreInfraBaseAccess
77+
code-artifact-auth-role-account-id: {% endraw %}{{ aws_central_infrastructure_account_id }}{% raw %}
78+
code-artifact-auth-region: {% endraw %}{{ aws_org_home_region }}{% endif %}{% raw %}
7379

7480
- name: Unit test
7581
run: uv run pytest --durations=5
@@ -85,7 +91,34 @@ jobs:
8591
- name: Install python tooling
8692
uses: ./.github/actions/install_deps_uv
8793
with:
88-
python-version: {% endraw %}{{ python_version }}{% raw %}
94+
python-version: {% endraw %}{{ python_version }}{% if python_package_registry == "AWS CodeArtifact" %}{% raw %}
95+
code-artifact-auth-role-name: CoreInfraBaseAccess
96+
code-artifact-auth-role-account-id: {% endraw %}{{ aws_central_infrastructure_account_id }}{% raw %}
97+
code-artifact-auth-region: {% endraw %}{{ aws_org_home_region }}{% endif %}{% raw %}
98+
99+
{% endraw %}{% if python_package_registry == "AWS CodeArtifact" %}{% raw %}
100+
- name: OIDC Auth for Installing any dependencies that uv may need for build (sometimes it likes to install setuptools...even if it's already in the package dependencies)
101+
uses: aws-actions/configure-aws-credentials@{% endraw %}{{ gha_configure_aws_credentials }}{% raw %}
102+
with:
103+
role-to-assume: arn:aws:iam::{% endraw %}{{ aws_central_infrastructure_account_id }}{% raw %}:role/CoreInfraBaseAccess
104+
aws-region: {% endraw %}{{ aws_org_home_region }}{% raw %}
89105

106+
{% endraw %}{% endif %}{% raw %}
90107
- name: Build package
91-
run: uv build --no-sources{% endraw %}
108+
run: |
109+
{% endraw %}{% if python_package_registry == "AWS CodeArtifact" %}{% raw %} . .devcontainer/code-artifact-auth.sh{% endraw %}{% endif %}{% raw %}
110+
uv build --no-sources
111+
112+
{% endraw %}{% if python_package_registry == "AWS CodeArtifact" %}{% raw %}
113+
- name: OIDC Auth for Publishing to CodeArtifact
114+
uses: aws-actions/configure-aws-credentials@{% endraw %}{{ gha_configure_aws_credentials }}{% raw %}
115+
with:
116+
role-to-assume: arn:aws:iam::{% endraw %}{{ aws_central_infrastructure_account_id }}{% raw %}:role/GHA-CA-Primary-{% endraw %}{{ repo_name }}{% raw %}
117+
aws-region: {% endraw %}{{ aws_org_home_region }}{% raw %}
118+
119+
{% endraw %}{% endif %}{% raw %}
120+
121+
- name: Publish package
122+
run: |
123+
{% endraw %}{% if python_package_registry == "AWS CodeArtifact" %}{% raw %} . .devcontainer/code-artifact-auth.sh{% endraw %}{% endif %}{% raw %}
124+
uv publish --verbose --index {% endraw %}{% if python_package_registry == "AWS CodeArtifact" %}code-artifact-primary --username aws --password "$TWINE_PASSWORD"{% else %}pypi{% endif %}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
{% raw %}name: Publish to Staging Package Registry
2+
3+
on:
4+
workflow_dispatch:
5+
6+
env:
7+
PYTHONUNBUFFERED: True
8+
PRE_COMMIT_HOME: ${{ github.workspace }}/.precommit_cache
9+
10+
permissions:
11+
id-token: write
12+
contents: write # needed for mutex
13+
14+
jobs:
15+
lint:
16+
name: Pre-commit
17+
runs-on: {% endraw %}{{ gha_linux_runner }}{% raw %}
18+
steps:
19+
- name: Checkout code
20+
uses: actions/checkout@{% endraw %}{{ gha_checkout }}{% raw %}
21+
22+
- name: Install latest versions of python packages
23+
uses: ./.github/actions/install_deps_uv
24+
with:
25+
python-version: {% endraw %}{{ python_version }}{% if python_package_registry == "AWS CodeArtifact" %}{% raw %}
26+
code-artifact-auth-role-name: CoreInfraBaseAccess
27+
code-artifact-auth-role-account-id: {% endraw %}{{ aws_central_infrastructure_account_id }}{% raw %}
28+
code-artifact-auth-region: {% endraw %}{{ aws_org_home_region }}{% endif %}{% raw %}
29+
30+
- name: Set up mutex # Github concurrency management is horrible, things get arbitrarily cancelled if queued up. So using mutex until github fixes itself. When multiple jobs are modifying cache at once, weird things can happen. possible issue is https://github.com/actions/toolkit/issues/658
31+
if: ${{ runner.os != 'Windows' }} # we're just gonna have to YOLO on Windows, because this action doesn't support it yet https://github.com/ben-z/gh-action-mutex/issues/14
32+
uses: ben-z/gh-action-mutex@{% endraw %}{{ gha_mutex }}{% raw %}
33+
with:
34+
branch: mutex-venv-{% endraw %}{{ gha_linux_runner }}{% raw %}-py{% endraw %}{{ python_version }}{% raw %}
35+
timeout-minutes: 30 # this is the amount of time this action will wait to attempt to acquire the mutex lock before failing, e.g. if other jobs are queued up in front of it
36+
37+
- name: Cache Pre-commit hooks
38+
uses: actions/cache@{% endraw %}{{ gha_cache }}{% raw %}
39+
env:
40+
cache-name: cache-pre-commit-hooks
41+
with:
42+
path: ${{ env.PRE_COMMIT_HOME }}
43+
key: {% endraw %}{{ gha_linux_runner }}{% raw %}-py{% endraw %}{{ python_version }}{% raw %}-build-${{ env.cache-name }}-${{ hashFiles('.pre-commit-config.yaml') }}
44+
restore-keys: |
45+
{% endraw %}{{ gha_linux_runner }}{% raw %}-py{% endraw %}{{ python_version }}{% raw %}-build-${{ env.cache-name }}-
46+
47+
- name: Run pre-commit
48+
run: pre-commit run -a
49+
50+
test:
51+
needs: [ lint ]
52+
strategy:
53+
matrix:
54+
os:
55+
- "{% endraw %}{{ gha_linux_runner }}{% raw %}"
56+
{% endraw %}{% if use_windows_in_ci %} - {{ gha_windows_runner }}{% endif %}{% raw %}
57+
python-version:
58+
{% endraw %}{% for item in python_ci_versions %}
59+
- {{ item }}
60+
{% endfor %}{% raw %}
61+
include:
62+
- os: "{% endraw %}{{ gha_linux_runner }}{% raw %}"
63+
python-version: "{% endraw %}{{ python_ci_versions[0] }}{% raw %}"
64+
JOB_MATCHING_DEV_ENV: true
65+
66+
runs-on: ${{ matrix.os }}
67+
68+
steps:
69+
- name: Checkout code
70+
uses: actions/checkout@{% endraw %}{{ gha_checkout }}{% raw %}
71+
72+
- name: Install python tooling
73+
uses: ./.github/actions/install_deps_uv
74+
with:
75+
python-version: ${{ matrix.python-version }}{% endraw %}{% if python_package_registry == "AWS CodeArtifact" %}{% raw %}
76+
code-artifact-auth-role-name: CoreInfraBaseAccess
77+
code-artifact-auth-role-account-id: "{% endraw %}{{ aws_central_infrastructure_account_id }}{% raw %}"
78+
code-artifact-auth-region: {% endraw %}{{ aws_org_home_region }}{% endif %}{% raw %}
79+
80+
- name: Unit test
81+
run: uv run pytest --durations=5
82+
83+
build:
84+
needs: [ test ]
85+
runs-on: {% endraw %}{{ gha_linux_runner }}{% raw %}
86+
87+
steps:
88+
- name: Checkout code
89+
uses: actions/checkout@{% endraw %}{{ gha_checkout }}{% raw %}
90+
91+
- name: Install python tooling
92+
uses: ./.github/actions/install_deps_uv
93+
with:
94+
python-version: {% endraw %}{{ python_version }}{% raw %}{% endraw %}{% if python_package_registry == "AWS CodeArtifact" %}{% raw %}
95+
code-artifact-auth-role-name: CoreInfraBaseAccess
96+
code-artifact-auth-role-account-id: "{% endraw %}{{ aws_central_infrastructure_account_id }}{% raw %}"
97+
code-artifact-auth-region: {% endraw %}{{ aws_org_home_region }}{% endif %}{% raw %}
98+
{% endraw %}{% if python_package_registry == "AWS CodeArtifact" %}{% raw %}
99+
- name: OIDC Auth for Installing any dependencies that uv may need for build (sometimes it likes to install setuptools...even if it's already in the package dependencies)
100+
uses: aws-actions/configure-aws-credentials@{% endraw %}{{ gha_configure_aws_credentials }}{% raw %}
101+
with:
102+
role-to-assume: arn:aws:iam::{% endraw %}{{ aws_central_infrastructure_account_id }}{% raw %}:role/CoreInfraBaseAccess
103+
aws-region: {% endraw %}{{ aws_org_home_region }}{% raw %}
104+
105+
{% endraw %}{% endif %}{% raw %}
106+
- name: Build package
107+
run: |
108+
{% endraw %}{% if python_package_registry == "AWS CodeArtifact" %}{% raw %} . .devcontainer/code-artifact-auth.sh{% endraw %}{% endif %}{% raw %}
109+
uv build --no-sources
110+
{% endraw %}{% if python_package_registry == "AWS CodeArtifact" %}{% raw %}
111+
- name: OIDC Auth for Publishing to CodeArtifact
112+
uses: aws-actions/configure-aws-credentials@{% endraw %}{{ gha_configure_aws_credentials }}{% raw %}
113+
with:
114+
role-to-assume: arn:aws:iam::{% endraw %}{{ aws_central_infrastructure_account_id }}{% raw %}:role/GHA-CA-Staging-{% endraw %}{{ repo_name }}{% raw %}
115+
aws-region: {% endraw %}{{ aws_org_home_region }}{% raw %}
116+
117+
{% endraw %}{% endif %}{% raw %}
118+
119+
- name: Publish package
120+
run: |
121+
{% endraw %}{% if python_package_registry == "AWS CodeArtifact" %}{% raw %} . .devcontainer/code-artifact-auth.sh{% endraw %}{% endif %}{% raw %}
122+
uv publish --verbose --index {% endraw %}{% if python_package_registry == "AWS CodeArtifact" %}code-artifact-staging --username aws --password "$TWINE_PASSWORD"{% else %}testpypi{% endif %}

template/pyproject.toml.jinja

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ dependencies = [
2121

2222
[dependency-groups]
2323
dev = [
24-
# Specific to this template
24+
# Specific to this repository
2525

2626

2727
# Managed by upstream template
@@ -53,9 +53,13 @@ publish-url = "https://test.pypi.org/legacy/"{% endraw %}{% else %}{% raw %}
5353
default = true
5454
name = "code-artifact-primary"
5555
username = "aws"
56+
publish-username = "aws"
5657
url = "https://{% endraw %}{{ repo_org_name }}{% raw %}-{% endraw %}{{ aws_central_infrastructure_account_id }}{% raw %}.d.codeartifact.{% endraw %}{{ aws_org_home_region }}{% raw %}.amazonaws.com/pypi/{% endraw %}{{ repo_org_name }}{% raw %}-primary/simple/"
58+
publish-url = "https://{% endraw %}{{ repo_org_name }}{% raw %}-{% endraw %}{{ aws_central_infrastructure_account_id }}{% raw %}.d.codeartifact.{% endraw %}{{ aws_org_home_region }}{% raw %}.amazonaws.com/pypi/{% endraw %}{{ repo_org_name }}{% raw %}-primary/"
5759

5860
[[tool.uv.index]]
5961
name = "code-artifact-staging"
6062
username = "aws"
61-
url = "https://{% endraw %}{{ repo_org_name }}{% raw %}-{% endraw %}{{ aws_central_infrastructure_account_id }}{% raw %}.d.codeartifact.{% endraw %}{{ aws_org_home_region }}{% raw %}.amazonaws.com/pypi/{% endraw %}{{ repo_org_name }}{% raw %}-staging/simple/"{% endraw %}{% endif %}
63+
publish-username = "aws"
64+
url = "https://{% endraw %}{{ repo_org_name }}{% raw %}-{% endraw %}{{ aws_central_infrastructure_account_id }}{% raw %}.d.codeartifact.{% endraw %}{{ aws_org_home_region }}{% raw %}.amazonaws.com/pypi/{% endraw %}{{ repo_org_name }}{% raw %}-staging/simple/"
65+
publish-url = "https://{% endraw %}{{ repo_org_name }}{% raw %}-{% endraw %}{{ aws_central_infrastructure_account_id }}{% raw %}.d.codeartifact.{% endraw %}{{ aws_org_home_region }}{% raw %}.amazonaws.com/pypi/{% endraw %}{{ repo_org_name }}{% raw %}-staging/"{% endraw %}{% endif %}

0 commit comments

Comments
 (0)