1 Commits

Author SHA1 Message Date
79b6b0b1c1 WIP
All checks were successful
run tests / check (push) Successful in 23s
run tests / release (push) Successful in 16s
2025-12-09 10:51:26 +01:00
26 changed files with 203 additions and 618 deletions

View File

@@ -1 +1 @@
version_descriptor: pyproject.toml version_descriptor: version.txt

View File

@@ -1,10 +0,0 @@
name: check if project is already released
on:
- pull_request
jobs:
unittest:
runs-on: action-runner
steps:
- uses: actions/checkout@v4
- uses: ./check-is-not-released

View File

@@ -23,70 +23,6 @@ jobs:
- run: set -u; echo "$RELEASE_PROJECT_CURRENT_VERSION" - run: set -u; echo "$RELEASE_PROJECT_CURRENT_VERSION"
test-sync-versions:
runs-on: action-runner
steps:
- uses: actions/checkout@v4
# skip login locally
- if: github.repository == 'actions/release'
uses: https://gitea.puzzleyou.net/actions/configure-runner-environment@master
- run: |
echo "1.33.7" > /tmp/version-test.txt
echo "0.0.42" > /tmp/other-version.txt
- uses: ./declare
with:
configure_runner_environment: false
version_descriptor: /tmp/version-test.txt
artefact_type: oci_image
artefact_name: default-image
artefact_version_descriptor: /tmp/other-version.txt
- uses: ./sync-versions
- run: test "$(cat /tmp/version-test.txt)" = "$RELEASE_PROJECT_PLANNED_VERSION"
- run: test "$(cat /tmp/other-version.txt)" = "$RELEASE_PROJECT_PLANNED_VERSION"
test-is-not-yet-released:
runs-on: action-runner
steps:
- uses: actions/checkout@v4
# skip login locally
- if: github.repository == 'actions/release'
uses: https://gitea.puzzleyou.net/actions/configure-runner-environment@master
- uses: ./declare
with:
configure_runner_environment: false
version_descriptor: test-assets/version.txt
- uses: ./check-is-not-released
with:
configure_runner_environment: false
test-skip-release-if-already-released:
runs-on: action-runner
steps:
- uses: actions/checkout@v4
# skip login locally
- if: github.repository == 'actions/release'
uses: https://gitea.puzzleyou.net/actions/configure-runner-environment@master
- uses: ./declare
with:
configure_runner_environment: false
version_descriptor: test-assets/Cargo.toml
- uses: ./release
with:
configure_runner_environment: false
dry_run: true
sync_versions: false
test-declare-with-release-yaml: test-declare-with-release-yaml:
runs-on: action-runner runs-on: action-runner
steps: steps:
@@ -100,7 +36,6 @@ jobs:
with: with:
dry_run: true dry_run: true
configure_runner_environment: false configure_runner_environment: false
sync_versions: false
- run: set -u; echo "$RELEASE_PROJECT_CURRENT_VERSION" - run: set -u; echo "$RELEASE_PROJECT_CURRENT_VERSION"
@@ -135,7 +70,7 @@ jobs:
- uses: ./add-artefact - uses: ./add-artefact
with: with:
type: wheel type: wheel
filename: "test-assets/wheels/*.whl" pattern: "test-assets/wheels/*.whl"
- uses: ./add-artefact - uses: ./add-artefact
with: with:
@@ -156,21 +91,12 @@ jobs:
repository: europe-docker.hetzner.cloud/puzzleyou/helm repository: europe-docker.hetzner.cloud/puzzleyou/helm
condition: always condition: always
- name: ensure that default artefact is set - name: ensure that environment variables are set
run: env | grep "RELEASE_IMAGE_LOCAL_NAME_DEFAULT_IMAGE"
- name: ensure that additional artefact is set
run: env | grep "RELEASE_IMAGE_LOCAL_NAME_SOME_DOCKER_IMAGE" run: env | grep "RELEASE_IMAGE_LOCAL_NAME_SOME_DOCKER_IMAGE"
- name: dump release environment variables - name: dump release environment variables
run: env | grep "RELEASE_" run: env | grep "RELEASE_"
- name: check version
run: echo "$RELEASE_PROJECT_CURRENT_VERSION" | grep "1.33.7"
- name: check state file is set
run: set -u; echo "$RELEASE_ACTION_STATEFILE"
- name: dump project description - name: dump project description
uses: ./dump uses: ./dump

View File

@@ -14,4 +14,4 @@ jobs:
runs-on: action-runner runs-on: action-runner
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: ./ - uses: ./release

195
README.md
View File

@@ -1,196 +1,3 @@
# release action # release action
Gitea/Github-Action, die hilft das Veröffentlichen von Projekten zu
automatisieren.
## Features TODO document usage
- Laden von Credentials und Einrichten der Runner-Umgebung
- Veröffentlichen von Artefakten
- Docker Images
- Python Pakete (wheel, sdist)
- NPM Pakete
- Tarballs
- Ausrollen von Helm-Releases
- Anlegen von Gitea-Releases
- Anlegen von Git-Tags
## Verwendung
Die Action erwartet eine Beschreibung des zu veröffentlichenden Projekts in
`.gitea/release.yaml`. Darin werden folgende Eigenschaften beschrieben:
- Welche Datei legt die aktuelle Version fest?
- Welche Artefakte sollen veröffentlicht werden?
- Welche Releases sollen wann aktualisiert werden?
### Beispiel für release.yaml
```yaml
# Die Version wird in der Datei Cargo.toml im Hauptverzeichnis des Projekts festgelegt
version_descriptor: Cargo.toml
artefacts:
# Es soll ein Docker/OCI-Image mit dem Namen masa-images veröffentlicht werden
- type: oci_image
name: masa-images
# Es soll ein Python-Paket als Wheel veröffentlicht werden
- type: wheel
# Unter diesem Pfad ist das Wheel abgelegt (vor dem Upload in die Registry)
filename: ./scratch/wheels/*.whl
# Diese Datei bestimmt die Version des Pakets.
# Wird synchronisiert mit der Version des Projekts.
version_descriptor: pyproject.toml
deployments:
# Bei einem Prerelease (push in testing) soll das Helm-Release masa-images-testing
# aktualisiert werden.
- type: helm
release_name: masa-images-testing
```
Alle möglichen Einstellungen können
[hier](/src/release/tests/assets/release.yaml) eingesehen werden.
### Aufruf im Workflow
Die Action kann die generischen Aufgaben bei einem Release übernehmen. Was sie
nicht kann ist die Artefakte bauen. Wie das zu tun ist muss das Projekt selbst
beschreiben.
Dafür gibt es zwei Möglichkeiten: Die Kurzform in einem Schritt und die
Langform in mehreren Schritten.
#### Langform
Wenn ein Projekt veröffentlicht wird, dann werden folgende Schritt ausgeführt:
- `actions/release/declare`: Hier wird die `release.yaml` gelesen und die
Credentials werden geladen.
- `actions/release/sync-versions`: Hier werden die Versionen der Artefakte mit
der Version des Projekts synchronisiert.
- Hier muss das Projekt die Artefakte bauen.
- `actions/release/release`: Hier werden die Artefakte veröffentlicht, das
Helm-Release aktualisiert und das Gitea-Release angelegt.
Beispiel:
```yaml
name: release
on:
push:
branches:
- master
- testing
jobs:
check:
uses: ./.gitea/workflows/checks.yaml
release:
needs: ["check"]
runs-on: action-runner
env:
RUSTC_WRAPPER: sccache
steps:
- uses: actions/checkout@v4
- uses: https://gitea.puzzleyou.net/actions/release/declare@v0
- uses: https://gitea.puzzleyou.net/actions/release/sync-versions@v0
- name: build image
run: |
nix develop --command just build-image ${RELEASE_IMAGE_TAG}
sccache --show-stats
- name: build wheel
run: |
mkdir -p ./scratch/wheels
nix develop --command \
maturin build \
--release \
--out ./scratch/wheels/ \
--strip \
-m Cargo.toml \
--compatibility linux \
--interpreter python3.13
sccache --show-stats
- uses: https://gitea.puzzleyou.net/actions/release@v0
```
#### Kurzform
Wenn es nur ein Artefakt gibt und das auch einfach zu bauen ist, dann kann die
Kurzform `actions/release` verwendet werden. Das ist der Normalfall. Im
Parameter `build_run` muss das Projekt (in Form eines Bash-Scripts) beschreiben
wie die Artefakte gebaut werden.
Beispiel:
```yaml
name: release
on:
push:
branches:
- master
- testing
jobs:
release:
runs-on: action-runner
steps:
- uses: actions/checkout@v4
- uses: https://gitea.puzzleyou.net/actions/release@v0
with:
build_run: docker build -t "${RELEASE_IMAGE_LOCAL_NAME_ALI}" .
```
## Umgebungsvariablen
Die Action stellt einige Umgebungsvariablen bereit, die im Workflow nützlich
sein können:
- `RELEASE_IMAGE_TAG`: Tag, der Docker/OCI-Images zugewiesen werden muss, damit
diese veröffentlicht und in Helm-Releases verwendet werden können. Entspricht
momentan dem Commit-Hash.
- `RELEASE_IMAGE_LOCAL_NAME_XXX`: Voller Name eines Docker/OCI-Images mit Tag.
- `RELEASE_IS_PRERELEASE`: Wird gerade ein Release (master/main) oder ein
Prerelease (testing) verarbeitet?
- `RELEASE_PROJECT_IS_RELEASED`: Wurde das Projekt schon unter dieser Version
veröffentlicht?
- `RELEASE_PROJECT_CURRENT_VERSION`: Aktuelle Version des Projekts, z.B.
'2.10.4'
- `RELEASE_PROJECT_PLANNED_VERSION`: "Geplante" Version des Projekts.
Entspricht der aktuellen Version mit optionalem Suffix bei Prerelease, z.B.
'2.10.4-dev42'
## Release vs. Prerelease
Die Release-Action kann für Releases (merge in master/main) oder Prereleases
(merge in testing) verwendet werden.
Es unterscheiden sich dann image-tags, git-tags und Versionsnummern der
Artefakte.
### Release
- Image-Tags: `v1`, `v1.2`, `v1.2.3`, `latest`, `master/main.latest`
- Git-Tags: `v1`, `v1.2`, `v1.2.3`, `latest`
- Versionsummern: Wie Projekt
### Prerelease
- Image-Tags: `v1.2.3-dev4`, `development`, `testing.latest`
- Git-Tags: `v1.2.3-dev4`, `development`
- Versionsnummern: Wie Projekt, mit Suffix `-dev$ACTION_LAUF_NUMMER`
## Prüfung ob eine Version schon veröffentlicht wurde
Beim Release selbst (merge in main/master) wird geprüft ob eine Version bereits
veröffentlicht wurde. Falls ja, ist das kein Fehler. **ABER** es wird in dem
Fall weder ein Docker/OCI-Image hochgeladen, noch ein Helm-Release aktualisiert
oder irgendwelche anderen Artefakte veröffentlicht. Das kann erwünscht sein,
wenn eine Änderung nicht ausgerollt werden muss (z.b. Dokumentation angepasst,
fixtures verändert, etc.)
Um bei einem Pull-Request eine Warnung zu sehen, wenn die Version nicht erhöht
wurde kann folgender Workflow verwendet werden. Es ist keine Anpassung nötig.
```yaml
name: check if project is already released
on:
- pull_request
jobs:
check:
runs-on: action-runner
steps:
- uses: actions/checkout@v4
- uses: https://gitea.puzzleyou.net/actions/release/check-is-not-released@v0
```
Bei einem Prerelease (merge in testing) muss die Version nicht angepasst
werden. Das geschieht automatisch.

View File

@@ -1 +0,0 @@
release/action.yaml

View File

@@ -18,7 +18,7 @@ inputs:
filename: filename:
required: false required: false
description: "required for tarball, sdist, wheel" description: "required for tarball, sdist"
default: "" default: ""
package_name: package_name:
@@ -26,6 +26,11 @@ inputs:
description: "required for tarball" description: "required for tarball"
default: "" default: ""
pattern:
required: false
description: "required for wheel"
default: ""
directory: directory:
required: false required: false
description: "required for npm" description: "required for npm"
@@ -49,6 +54,7 @@ runs:
--artefact-name "${{ inputs.name }}" \ --artefact-name "${{ inputs.name }}" \
--artefact-filename "${{ inputs.filename }}" \ --artefact-filename "${{ inputs.filename }}" \
--artefact-package-name "${{ inputs.package_name }}" \ --artefact-package-name "${{ inputs.package_name }}" \
--artefact-pattern "${{ inputs.pattern }}" \
--artefact-directory "${{ inputs.directory }}" \ --artefact-directory "${{ inputs.directory }}" \
--version-descriptor "${{ inputs.version_descriptor }}" \ --version-descriptor "${{ inputs.version_descriptor }}" \
--write-env-vars-to-filename "$GITHUB_ENV" --write-env-vars-to-filename "$GITHUB_ENV"

View File

@@ -1,44 +0,0 @@
name: "check not released"
description: "ensure that there is no release with the current version"
inputs:
configure_runner_environment:
required: false
default: true
runs:
using: composite
steps:
- if: inputs.configure_runner_environment == 'true'
uses: https://gitea.puzzleyou.net/actions/configure-runner-environment@master
- name: declare project if neccessary
run: |
if [[ ! -z "${RELEASE_PROJECT_CURRENT_VERSION}" ]]; then
echo "already set up."
exit 0
fi
nix run ${{ github.action_path }} -- \
declare \
--release-yaml-filename ".gitea/release.yaml" \
--gitea-instance "https://gitea.puzzleyou.net" \
--release-repository-name "${{ github.repository }}" \
--release-ref-name "${{ github.ref_name }}" \
--release-run-number "${{ github.run_number }}" \
--release-commit-sha "${{ github.sha }}" \
--write-env-vars-to-filename "$GITHUB_ENV"
- name: check release state
run: |
set +e
if [[ "$RELEASE_PROJECT_IS_RELEASED" = "1" ]]; then
VERSION="$RELEASE_PROJECT_CURRENT_VERSION"
echo "Project is already released with version ${VERSION}."
echo "You should increment the project version."
echo "If you don't, then the project will not be released."
exit -1
else
echo "Project is not yet released."
fi

View File

@@ -41,7 +41,7 @@ inputs:
artefact_filename: artefact_filename:
required: false required: false
description: "required for tarball, sdist, wheel" description: "required for tarball, sdist"
default: "" default: ""
artefact_package_name: artefact_package_name:
@@ -49,6 +49,11 @@ inputs:
description: "required for tarball" description: "required for tarball"
default: "" default: ""
artefact_pattern:
required: false
description: "required for wheel"
default: ""
artefact_directory: artefact_directory:
required: false required: false
description: "required for npm" description: "required for npm"
@@ -97,23 +102,72 @@ runs:
- if: inputs.configure_runner_environment == 'true' - if: inputs.configure_runner_environment == 'true'
uses: https://gitea.puzzleyou.net/actions/configure-runner-environment@master uses: https://gitea.puzzleyou.net/actions/configure-runner-environment@master
- name: declare release project - name: init action state
run: | run: |
if [[ ! -z "${RELEASE_PROJECT_CURRENT_VERSION}" ]]; then if [[ ! -z "${RELEASE_PROJECT_CURRENT_VERSION}" ]]; then
echo "already set up." echo "already set up."
exit 0 exit 0
fi fi
RELEASE_ACTION_STATEFILE=$(mktemp)
echo "[release] statefile: $RELEASE_ACTION_STATEFILE"
echo "RELEASE_ACTION_STATEFILE="$RELEASE_ACTION_STATEFILE"" \
>> "$GITHUB_ENV"
- name: declare release project
if: inputs.version_descriptor == ''
run: |
if [[ ! -z "${RELEASE_PROJECT_CURRENT_VERSION}" ]]; then
echo "already set up."
exit 0
fi
if [[ "${{ github.ref_name }}" == "master" || "${{ github.ref_name }}" == "main" ]]; then
IS_PRE_RELEASE="0"
else
IS_PRE_RELEASE="1"
fi
nix run ${{ github.action_path }} -- \ nix run ${{ github.action_path }} -- \
declare \ declare \
--state "${RELEASE_ACTION_STATEFILE}" \
--release-yaml-filename "${{ inputs.filename }}" \ --release-yaml-filename "${{ inputs.filename }}" \
--gitea-instance "${{ inputs.gitea_instance }}" \
--release-repository-name "${{ inputs.repository }}" \
--release-ref-name "${{ github.ref_name }}" \
--release-run-number "${{ github.run_number }}" \
--release-commit-sha "${{ github.sha }}" \
--is-pre-release "${IS_PRE_RELEASE}"
nix run ${{ github.action_path }} -- \
dump \
--state "${RELEASE_ACTION_STATEFILE}" \
--write-env-vars-to-filename "$GITHUB_ENV"
- name: declare release project
if: inputs.version_descriptor != ''
run: |
if [[ ! -z "${RELEASE_PROJECT_CURRENT_VERSION}" ]]; then
echo "already set up."
exit 0
fi
if [[ "${{ github.ref_name }}" == "master" || "${{ github.ref_name }}" == "main" ]]; then
IS_PRE_RELEASE="0"
else
IS_PRE_RELEASE="1"
fi
nix run ${{ github.action_path }} -- \
declare \
--state "${RELEASE_ACTION_STATEFILE}" \
--version-descriptor "${{ inputs.version_descriptor }}" \ --version-descriptor "${{ inputs.version_descriptor }}" \
--gitea-instance "${{ inputs.gitea_instance }}" \ --gitea-instance "${{ inputs.gitea_instance }}" \
--release-repository-name "${{ inputs.repository }}" \ --release-repository-name "${{ inputs.repository }}" \
--release-ref-name "${{ github.ref_name }}" \ --release-ref-name "${{ github.ref_name }}" \
--release-run-number "${{ github.run_number }}" \ --release-run-number "${{ github.run_number }}" \
--release-commit-sha "${{ github.sha }}" \ --release-commit-sha "${{ github.sha }}" \
--write-env-vars-to-filename "$GITHUB_ENV" --is-pre-release "${IS_PRE_RELEASE}" \
if [[ ! -z "${{ inputs.artefact_type }}" ]]; then if [[ ! -z "${{ inputs.artefact_type }}" ]]; then
nix run ${{ github.action_path }} -- \ nix run ${{ github.action_path }} -- \
@@ -124,6 +178,7 @@ runs:
--artefact-name "${{ inputs.artefact_name }}" \ --artefact-name "${{ inputs.artefact_name }}" \
--artefact-filename "${{ inputs.artefact_filename }}" \ --artefact-filename "${{ inputs.artefact_filename }}" \
--artefact-package-name "${{ inputs.artefact_package_name }}" \ --artefact-package-name "${{ inputs.artefact_package_name }}" \
--artefact-pattern "${{ inputs.artefact_pattern }}" \
--artefact-directory "${{ inputs.artefact_directory }}" \ --artefact-directory "${{ inputs.artefact_directory }}" \
--version-descriptor "${{ inputs.artefact_version_descriptor }}" --version-descriptor "${{ inputs.artefact_version_descriptor }}"
fi fi
@@ -139,3 +194,8 @@ runs:
--deployment-namespace "${{ inputs.deployment_namespace }}" \ --deployment-namespace "${{ inputs.deployment_namespace }}" \
--deployment-repository "${{ inputs.deployment_repository }}" --deployment-repository "${{ inputs.deployment_repository }}"
fi fi
nix run ${{ github.action_path }} -- \
dump \
--state "${RELEASE_ACTION_STATEFILE}" \
--write-env-vars-to-filename "$GITHUB_ENV"

View File

@@ -4,23 +4,6 @@ description: "dump current project description"
runs: runs:
using: composite using: composite
steps: steps:
- name: declare project if neccessary
run: |
if [[ ! -z "${RELEASE_PROJECT_CURRENT_VERSION}" ]]; then
echo "already set up."
exit 0
fi
nix run ${{ github.action_path }} -- \
declare \
--release-yaml-filename ".gitea/release.yaml" \
--gitea-instance "https://gitea.puzzleyou.net" \
--release-repository-name "${{ github.repository }}" \
--release-ref-name "${{ github.ref_name }}" \
--release-run-number "${{ github.run_number }}" \
--release-commit-sha "${{ github.sha }}" \
--write-env-vars-to-filename "$GITHUB_ENV"
- name: dump project description - name: dump project description
run: | run: |
nix run ${{ github.action_path }} -- \ nix run ${{ github.action_path }} -- \

23
flake.lock generated
View File

@@ -34,31 +34,10 @@
"type": "github" "type": "github"
} }
}, },
"pyproject-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1764134915,
"narHash": "sha256-xaKvtPx6YAnA3HQVp5LwyYG1MaN4LLehpQI8xEdBvBY=",
"owner": "pyproject-nix",
"repo": "pyproject.nix",
"rev": "2c8df1383b32e5443c921f61224b198a2282a657",
"type": "github"
},
"original": {
"owner": "pyproject-nix",
"repo": "pyproject.nix",
"type": "github"
}
},
"root": { "root": {
"inputs": { "inputs": {
"flake-utils": "flake-utils", "flake-utils": "flake-utils",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs"
"pyproject-nix": "pyproject-nix"
} }
}, },
"systems": { "systems": {

View File

@@ -4,41 +4,50 @@
inputs = { inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05"; nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
flake-utils.url = "github:numtide/flake-utils"; flake-utils.url = "github:numtide/flake-utils";
pyproject-nix = {
url = "github:pyproject-nix/pyproject.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
}; };
outputs = { self, nixpkgs, flake-utils, pyproject-nix }: outputs = { self, nixpkgs, flake-utils, ... }:
flake-utils.lib.eachDefaultSystem (system: flake-utils.lib.eachDefaultSystem (system:
let let
pkgs = import nixpkgs { inherit system; }; pkgs = import nixpkgs { inherit system; };
pythonProject = pyproject-nix.lib.project.loadPyproject { python = pkgs.python313.withPackages (ps: with ps; [
projectRoot = ./.; isort
}; flake8
semver
toml
requests
pyyaml
]);
pythonInterpreter = pkgs.python313; pythonPackage = pkgs.python3Packages.buildPythonPackage {
name = "release-action";
src = ./.;
};
in in
{ {
devShells.default = pkgs.mkShell { devShells.default = pkgs.mkShell {
buildInputs = [ buildInputs = [
pkgs.envsubst
pkgs.just pkgs.just
pkgs.gitea-actions-runner pkgs.gitea-actions-runner
(pythonInterpreter.withPackages python
(pythonProject.renderers.withPackages {
python = pythonInterpreter;
extraPackages = ps: with ps; [ flake8 isort ];
}))
]; ];
}; };
packages.default = pythonInterpreter.pkgs.buildPythonPackage ( packages.default = pkgs.writers.writePython3Bin
pythonProject.renderers.buildPythonPackage { "release-action"
python = pythonInterpreter; {
}); libraries = with pkgs.python3Packages; [
semver # TODO move to setup.py?
toml
requests
pythonPackage
pyyaml
];
}
(builtins.readFile ./src/main.py)
;
} }
); );
} }

View File

@@ -24,20 +24,4 @@ test-workflows:
--workflows ./.gitea/workflows/check.yaml \ --workflows ./.gitea/workflows/check.yaml \
--job test-declare-default --job test-declare-default
act_runner exec \ # --image "europe-docker.pkg.dev/puzzle-and-play/docker/action-runner-job:latest" \
--image "-self-hosted" \
--event pull_request \
--workflows ./.gitea/workflows/check.yaml \
--job test-is-not-yet-released
act_runner exec \
--image "-self-hosted" \
--event pull_request \
--workflows ./.gitea/workflows/check.yaml \
--job test-skip-release-if-already-released
act_runner exec \
--image "-self-hosted" \
--event pull_request \
--workflows ./.gitea/workflows/check.yaml \
--job test-sync-versions

View File

@@ -1,16 +0,0 @@
[project]
name = "gitea-release-action"
version = "0.0.1"
description = "reusable action for release workflows"
authors = [ ]
requires-python = ">=3.13"
dependencies = [
"semver",
"toml",
"requests",
"pyyaml",
"packaging"
]
[project.scripts]
gitea-release-action = "main:main_cli"

View File

@@ -11,21 +11,13 @@ inputs:
required: false required: false
default: true default: true
build_run:
required: false
description: "commands to run before publishing artefacts"
default: ""
sync_versions:
required: false
default: true
runs: runs:
using: composite using: composite
steps: steps:
- if: inputs.configure_runner_environment == 'true' - if: inputs.configure_runner_environment == 'true'
uses: https://gitea.puzzleyou.net/actions/configure-runner-environment@master uses: https://gitea.puzzleyou.net/actions/configure-runner-environment@master
# TODO duplicate code (declare/action.yaml)
- name: declare project if neccessary - name: declare project if neccessary
run: | run: |
if [[ ! -z "${RELEASE_PROJECT_CURRENT_VERSION}" ]]; then if [[ ! -z "${RELEASE_PROJECT_CURRENT_VERSION}" ]]; then
@@ -33,38 +25,34 @@ runs:
exit 0 exit 0
fi fi
RELEASE_ACTION_STATEFILE=$(mktemp)
echo "[release] statefile: $RELEASE_ACTION_STATEFILE"
echo "RELEASE_ACTION_STATEFILE="$RELEASE_ACTION_STATEFILE"" \
>> "$GITHUB_ENV"
if [[ "${{ github.ref_name }}" == "master" || "${{ github.ref_name }}" == "main" ]]; then
IS_PRE_RELEASE="0"
else
IS_PRE_RELEASE="1"
fi
nix run ${{ github.action_path }} -- \ nix run ${{ github.action_path }} -- \
declare \ declare \
--state "${RELEASE_ACTION_STATEFILE}" \
--release-yaml-filename ".gitea/release.yaml" \ --release-yaml-filename ".gitea/release.yaml" \
--gitea-instance "https://gitea.puzzleyou.net" \ --gitea-instance "https://gitea.puzzleyou.net" \
--release-repository-name "${{ github.repository }}" \ --release-repository-name "${{ github.repository }}" \
--release-ref-name "${{ github.ref_name }}" \ --release-ref-name "${{ github.ref_name }}" \
--release-run-number "${{ github.run_number }}" \ --release-run-number "${{ github.run_number }}" \
--release-commit-sha "${{ github.sha }}" \ --release-commit-sha "${{ github.sha }}" \
--is-pre-release "${IS_PRE_RELEASE}"
nix run ${{ github.action_path }} -- \
dump \
--state "${RELEASE_ACTION_STATEFILE}" \
--write-env-vars-to-filename "$GITHUB_ENV" --write-env-vars-to-filename "$GITHUB_ENV"
- name: check if already released
id: check_released
run: |
if [[ "$RELEASE_PROJECT_IS_RELEASED" == "1" ]] && [[ "$RELEASE_IS_PRERELEASE" == "0" ]]; then
echo "is_released=1" >> "$GITHUB_OUTPUT"
else
echo "is_released=0" >> "$GITHUB_OUTPUT"
fi
- name: sync versions
if: ${{ steps.check_released.outputs.is_released == '0' && inputs.sync_versions == 'true' }}
run: |
nix run ${{ github.action_path }} -- \
sync-versions \
--state "${RELEASE_ACTION_STATEFILE}"
- name: run build commands
if: ${{ steps.check_released.outputs.is_released == '0' && inputs.build_run != '' }}
run: ${{ inputs.build_run }}
- name: publish artefacts - name: publish artefacts
if: ${{ steps.check_released.outputs.is_released == '0' }}
run: | run: |
nix run ${{ github.action_path }} -- \ nix run ${{ github.action_path }} -- \
publish-artefacts \ publish-artefacts \
@@ -72,7 +60,6 @@ runs:
--dry-run "${{ inputs.dry_run }}" --dry-run "${{ inputs.dry_run }}"
- name: update deployments - name: update deployments
if: ${{ steps.check_released.outputs.is_released == '0' }}
run: | run: |
nix run ${{ github.action_path }} -- \ nix run ${{ github.action_path }} -- \
update-deployments \ update-deployments \
@@ -80,7 +67,6 @@ runs:
--dry-run "${{ inputs.dry_run }}" --dry-run "${{ inputs.dry_run }}"
- name: create release - name: create release
if: ${{ steps.check_released.outputs.is_released == '0' }}
run: | run: |
nix run ${{ github.action_path }} -- \ nix run ${{ github.action_path }} -- \
create-release \ create-release \

6
setup.py Normal file
View File

@@ -0,0 +1,6 @@
from setuptools import setup
setup(
name='release-action',
version='0.0.1.dev0',
)

View File

@@ -2,8 +2,6 @@ import pickle
import re import re
from argparse import ArgumentParser from argparse import ArgumentParser
from dataclasses import replace from dataclasses import replace
from os import path
from tempfile import gettempdir
from typing import Optional from typing import Optional
import yaml import yaml
@@ -82,7 +80,7 @@ def dump_project_description(project_description: ProjectDescription):
print(' release version name: %s' % release_info.version_str) print(' release version name: %s' % release_info.version_str)
elif isinstance(generated, Wheel): elif isinstance(generated, Wheel):
print(' - wheel: %s' % generated.filename) print(' - wheel: %s' % generated.pattern)
print(' repository: %s' % generated.repository) print(' repository: %s' % generated.repository)
print(' release version name: %s' % release_info.version_str) print(' release version name: %s' % release_info.version_str)
@@ -152,6 +150,7 @@ def make_artefact(type: str,
name: str, name: str,
filename: str, filename: str,
package_name: str, package_name: str,
pattern: str,
directory: str, directory: str,
version_descriptor) -> ArtefactDescription: version_descriptor) -> ArtefactDescription:
@@ -171,8 +170,8 @@ def make_artefact(type: str,
**maybe_repository) **maybe_repository)
elif type == 'wheel': elif type == 'wheel':
assert filename is not None assert pattern is not None
generated = Wheel(filename=filename, **maybe_repository) generated = Wheel(pattern=pattern, **maybe_repository)
elif type == 'sdist': elif type == 'sdist':
assert filename is not None assert filename is not None
@@ -232,29 +231,15 @@ def make_deployment(type: str,
return DeploymentDescription(deployment=deployment, **maybe_condition) return DeploymentDescription(deployment=deployment, **maybe_condition)
def sync_versions(project_description: ProjectDescription): if __name__ == '__main__':
planned_version = project_description.planned_version
def sync(descriptor_filename: str):
v = versioning.use_any(descriptor_filename)
v.version = planned_version
v.store()
sync(project_description.version_descriptor)
for artefact in project_description.artefacts:
if artefact.version_descriptor is not None:
sync(artefact.version_descriptor)
def main_cli():
parser = ArgumentParser() parser = ArgumentParser()
parser.add_argument('action', choices=[ parser.add_argument('action', choices=[
# TODO missing: adjust version (development)
# TODO missing: check if release already exists
'declare', 'declare',
'check', 'check',
'add-artefact', 'add-artefact',
'add-deployment', 'add-deployment',
'sync-versions',
'publish-artefacts', 'publish-artefacts',
'update-deployments', 'update-deployments',
'create-release', 'create-release',
@@ -277,7 +262,7 @@ def main_cli():
else: else:
raise Exception('flag can be "0" or "1". got: %s' % val) raise Exception('flag can be "0" or "1". got: %s' % val)
parser.add_argument('--state', type=nullable_string) parser.add_argument('--state', required=True)
parser.add_argument('--version-descriptor', type=nullable_string) parser.add_argument('--version-descriptor', type=nullable_string)
parser.add_argument('--release-yaml-filename', type=nullable_string) parser.add_argument('--release-yaml-filename', type=nullable_string)
parser.add_argument('--dry-run', type=true_or_false) parser.add_argument('--dry-run', type=true_or_false)
@@ -296,6 +281,7 @@ def main_cli():
parser.add_argument('--artefact-name', type=nullable_string) parser.add_argument('--artefact-name', type=nullable_string)
parser.add_argument('--artefact-package-name', type=nullable_string) parser.add_argument('--artefact-package-name', type=nullable_string)
parser.add_argument('--artefact-filename', type=nullable_string) parser.add_argument('--artefact-filename', type=nullable_string)
parser.add_argument('--artefact-pattern', type=nullable_string)
parser.add_argument('--artefact-directory', type=nullable_string) parser.add_argument('--artefact-directory', type=nullable_string)
parser.add_argument('--deployment-type', parser.add_argument('--deployment-type',
@@ -310,8 +296,6 @@ def main_cli():
parser.add_argument('--write-env-vars-to-filename') parser.add_argument('--write-env-vars-to-filename')
args = parser.parse_args() args = parser.parse_args()
state_file = (args.state
or str(path.join(gettempdir(), 'release_project_state')))
def clean_repository_name(name: str) -> str: def clean_repository_name(name: str) -> str:
if name.startswith('//'): if name.startswith('//'):
@@ -320,22 +304,13 @@ def main_cli():
return name return name
if args.action == 'declare': if args.action == 'declare':
if args.version_descriptor is None: if args.release_yaml_filename is None:
project_description = make_project_description(
args.version_descriptor)
else:
with open(args.release_yaml_filename, 'r') as f: with open(args.release_yaml_filename, 'r') as f:
project_description = parse_project_description( project_description = parse_project_description(
yaml.safe_load(f)) yaml.safe_load(f))
else:
project_description = make_project_description(
args.version_descriptor)
if args.is_pre_release is None:
assert args.release_ref_name is not None
is_pre_release = not any(
map(lambda rn: rn in args.release_ref_name,
['master', 'main']))
else:
is_pre_release = args.is_pre_release
project_description = replace( project_description = replace(
project_description, project_description,
@@ -345,18 +320,19 @@ def main_cli():
args.release_ref_name, args.release_ref_name,
args.release_run_number, args.release_run_number,
args.release_commit_sha, args.release_commit_sha,
is_pre_release)) args.is_pre_release))
save_project_description(state_file, project_description) save_project_description(args.state, project_description)
elif args.action == 'add-artefact': elif args.action == 'add-artefact':
project_description = load_project_description(state_file) project_description = load_project_description(args.state)
artefact = make_artefact(args.artefact_type, artefact = make_artefact(args.artefact_type,
args.artefact_repository, args.artefact_repository,
args.artefact_name, args.artefact_name,
args.artefact_filename, args.artefact_filename,
args.artefact_package_name, args.artefact_package_name,
args.artefact_pattern,
args.artefact_directory, args.artefact_directory,
args.version_descriptor) args.version_descriptor)
@@ -364,10 +340,10 @@ def main_cli():
project_description, project_description,
artefacts=project_description.artefacts + [artefact]) artefacts=project_description.artefacts + [artefact])
save_project_description(state_file, project_description) save_project_description(args.state, project_description)
elif args.action == 'add-deployment': elif args.action == 'add-deployment':
project_description = load_project_description(state_file) project_description = load_project_description(args.state)
deployment = make_deployment(args.deployment_type, deployment = make_deployment(args.deployment_type,
args.deployment_release_name, args.deployment_release_name,
@@ -380,46 +356,38 @@ def main_cli():
project_description, project_description,
deployments=project_description.deployments + [deployment]) deployments=project_description.deployments + [deployment])
save_project_description(state_file, project_description) save_project_description(args.state, project_description)
elif args.action == 'sync-versions':
project_description = load_project_description(state_file)
sync_versions(project_description)
elif args.action == 'publish-artefacts': elif args.action == 'publish-artefacts':
project_description = load_project_description(state_file) project_description = load_project_description(args.state)
publish_artefacts(project_description, args.dry_run) publish_artefacts(project_description, args.dry_run)
elif args.action == 'update-deployments': elif args.action == 'update-deployments':
project_description = load_project_description(state_file) project_description = load_project_description(args.state)
update_deployments(project_description, args.dry_run) update_deployments(project_description, args.dry_run)
elif args.action == 'create-release': elif args.action == 'create-release':
project_description = load_project_description(state_file) project_description = load_project_description(args.state)
create_release(project_description, args.dry_run) create_release(project_description, args.dry_run)
elif args.action == 'dump': elif args.action == 'dump':
project_description = load_project_description(state_file) project_description = load_project_description(args.state)
dump_project_description(project_description) dump_project_description(project_description)
elif args.action == 'check': elif args.action == 'check':
project_description = load_project_description(state_file) project_description = load_project_description(args.state)
else: else:
raise NotImplementedError() raise NotImplementedError()
assert project_description is not None assert project_description is not None
assert state_file is not None
env_var_filename = args.write_env_vars_to_filename env_var_filename = args.write_env_vars_to_filename
if env_var_filename is not None: if env_var_filename is not None:
env_vars = { env_vars = project_description.environment_variables
'RELEASE_ACTION_STATEFILE': state_file,
**project_description.environment_variables
}
assert not any(map(lambda v: '"' in v, env_vars.values())) assert not any(map(lambda v: '"' in v, env_vars.values()))
with open(env_var_filename, 'a') as f: with open(env_var_filename, 'a') as f:
f.write( f.write(
'\n'.join(map(lambda it: '%s=%s' % it, env_vars.items()))) '\n'.join(map(lambda it: '%s="%s"' % it, env_vars.items())))

View File

@@ -1,12 +0,0 @@
from packaging.version import parse as parse_version
from semver import Version
def python_version_str(version: Version) -> str:
return ('%d.%d.%d' % (version.major, version.minor, version.patch)) \
+ ('' if version.prerelease is None else '.%s' % version.prerelease)
def python_parse_version(txt: str) -> Version:
version = parse_version(txt)
return Version(*version.release, version.pre)

View File

@@ -6,7 +6,6 @@ from itertools import chain
from typing import Optional, Union from typing import Optional, Union
from release import toolkit, versioning from release import toolkit, versioning
from release.common import python_version_str
from release.context import ReleaseContext from release.context import ReleaseContext
from release.versioning import Version from release.versioning import Version
@@ -21,6 +20,11 @@ def _normalize_env_var_fragment(txt: str) -> str:
return txt.upper().replace('-', '_').replace('.', '_') return txt.upper().replace('-', '_').replace('.', '_')
def _python_version_str(version: Version) -> str:
return ('%d.%d.%d' % (version.major, version.minor, version.patch)) \
+ ('' if version.prerelease is None else '.%s' % version.prerelease)
@dataclass(frozen=True) @dataclass(frozen=True)
class OciImageReleaseInfo: class OciImageReleaseInfo:
image_name: str image_name: str
@@ -97,14 +101,14 @@ class Tarball:
@dataclass(frozen=True) @dataclass(frozen=True)
class WheelReleaseInfo: class WheelReleaseInfo:
filename: str pattern: str
repository: str repository: str
version_str: str version_str: str
@dataclass(frozen=True) @dataclass(frozen=True)
class Wheel: class Wheel:
filename: str pattern: str
repository: str = DEFAULT_PYPI_REPOSITORY_NAME repository: str = DEFAULT_PYPI_REPOSITORY_NAME
def make_environment_variables(self, context, version): def make_environment_variables(self, context, version):
@@ -112,9 +116,9 @@ class Wheel:
def make_release_info(self, context: ReleaseContext, version: Version): def make_release_info(self, context: ReleaseContext, version: Version):
return WheelReleaseInfo( return WheelReleaseInfo(
filename=self.filename, pattern=self.pattern,
repository=self.repository, repository=self.repository,
version_str=python_version_str(version)) version_str=_python_version_str(version))
@dataclass(frozen=True) @dataclass(frozen=True)
@@ -136,7 +140,7 @@ class Sdist:
return SdistReleaseInfo( return SdistReleaseInfo(
filename=self.filename, filename=self.filename,
repository=self.repository, repository=self.repository,
version_str=python_version_str(version)) version_str=_python_version_str(version))
@dataclass(frozen=True) @dataclass(frozen=True)
@@ -262,7 +266,7 @@ class ProjectDescription:
if self.gitea_tool is None: if self.gitea_tool is None:
return None return None
return self.gitea_tool.is_released(self.project_version) return self.gitea_tool.is_released(self.planned_version)
@cached_property @cached_property
def gitea_tool(self): def gitea_tool(self):
@@ -302,8 +306,6 @@ class ProjectDescription:
str(self.project_version), str(self.project_version),
'RELEASE_PROJECT_PLANNED_VERSION': 'RELEASE_PROJECT_PLANNED_VERSION':
str(self.planned_version), str(self.planned_version),
'RELEASE_PROJECT_IS_RELEASED':
'1' if self.is_released else '0',
}] }]
)) ))
@@ -327,8 +329,8 @@ def parse_project_description(obj):
**optional(tar, 'repository')) **optional(tar, 'repository'))
def parse_wheel(whl): def parse_wheel(whl):
assert 'filename' in whl assert 'pattern' in whl
return Wheel(filename=whl['filename'], return Wheel(pattern=whl['pattern'],
**optional(whl, 'repository')) **optional(whl, 'repository'))
def parse_sdist(sdist): def parse_sdist(sdist):

View File

@@ -9,8 +9,6 @@ from release.project import (DeploymentCondition, HelmRelease, HelmReleaseInfo,
SdistReleaseInfo, Tarball, TarballReleaseInfo, SdistReleaseInfo, Tarball, TarballReleaseInfo,
Wheel, WheelReleaseInfo) Wheel, WheelReleaseInfo)
DEFAULT_PACKAGE_OWNER = 'puzzleYOU'
class Cli: class Cli:
def __init__(self, dry_run: bool): def __init__(self, dry_run: bool):
@@ -68,9 +66,8 @@ def publish_tarball(info: TarballReleaseInfo, cli: Cli):
'--upload-file', info.filename, '--upload-file', info.filename,
'-i', '-i',
'-X', 'PUT', '-X', 'PUT',
'%s/api/packages/%s/generic/%s/%s/%s' % ( '%s/api/packages/puzzleYOU/generic/%s/%s/%s' % ( # TODO owner
info.repository, info.repository,
DEFAULT_PACKAGE_OWNER,
info.package_name, info.package_name,
info.version_str, info.version_str,
path.basename(info.filename))) path.basename(info.filename)))
@@ -84,7 +81,7 @@ def publish_wheel(info: WheelReleaseInfo, cli: Cli):
'upload', 'upload',
'--verbose', '--verbose',
'--repository', info.repository, '--repository', info.repository,
info.filename) info.pattern)
print() print()
@@ -150,19 +147,19 @@ def update_helm_release(info: HelmReleaseInfo, cli: Cli):
'--version', chart_version, '--version', chart_version,
'-d', td) '-d', td)
chart_filename = '%s/%s-%s.tgz' % (td, chart_name, chart_version) chart_filename = '%s/%s-%s.tgz' % (td, chart_name, chart_version)
value_overrides = ','.join( value_overrides = ','.join(
map(lambda t: '%s=%s' % (t, info.image_tag), info.image_paths)) map(lambda t: '%s=%s' % (t, info.image_tag), info.image_paths))
cli('helm', cli('helm',
'upgrade', info.release_name, 'upgrade', info.release_name,
chart_filename, chart_filename,
'--version', chart_version, '--version', chart_version,
'--namespace', info.namespace, '--namespace', info.namespace,
'--reuse-values', '--reuse-values',
'--set', value_overrides, '--set', value_overrides,
'--timeout', info.timeout) '--timeout', info.timeout)
def update_deployments(project: ProjectDescription, dry_run: bool = False): def update_deployments(project: ProjectDescription, dry_run: bool = False):

View File

@@ -19,10 +19,10 @@ artefacts:
repository: balls repository: balls
- type: wheel - type: wheel
filename: './scratch/wheels/*.whl' pattern: './scratch/wheels/*.whl'
- type: wheel - type: wheel
filename: './scratch/wheels/*.whl' pattern: './scratch/wheels/*.whl'
repository: other repository: other
- type: sdist - type: sdist

View File

@@ -1,6 +1,5 @@
from os import path from os import path
from unittest import TestCase from unittest import TestCase
from unittest.mock import patch
import yaml import yaml
from semver import Version from semver import Version
@@ -15,14 +14,6 @@ from release.project import (ArtefactDescription, DeploymentCondition,
WheelReleaseInfo, parse_project_description) WheelReleaseInfo, parse_project_description)
class MockGiteaTool:
def __init__(self, *args, **kwargs):
pass
def is_released(self, version):
return False
class TestProjectDescription(TestCase): class TestProjectDescription(TestCase):
def test_can_describe_projects(self): def test_can_describe_projects(self):
# resi-lib # resi-lib
@@ -30,7 +21,7 @@ class TestProjectDescription(TestCase):
version_descriptor='src/python/Cargo.toml', version_descriptor='src/python/Cargo.toml',
artefacts=[ artefacts=[
ArtefactDescription( ArtefactDescription(
generated=Wheel(filename='./scratch/wheels/*.whl')) generated=Wheel(pattern='./scratch/wheels/*.whl'))
]) ])
# productdesignerd # productdesignerd
@@ -55,7 +46,7 @@ class TestProjectDescription(TestCase):
ArtefactDescription( ArtefactDescription(
generated=OciImage(name='masa-images')), generated=OciImage(name='masa-images')),
ArtefactDescription( ArtefactDescription(
generated=Wheel(filename='./scratch/wheels/*.whl')) generated=Wheel(pattern='./scratch/wheels/*.whl'))
], ],
deployments=[ deployments=[
DeploymentDescription( DeploymentDescription(
@@ -134,7 +125,7 @@ class TestProjectDescription(TestCase):
artefacts=[ artefacts=[
ArtefactDescription( ArtefactDescription(
version_descriptor='src/python/pyproject.toml', version_descriptor='src/python/pyproject.toml',
generated=Wheel(filename='./scratch/wheels/*.whl')), generated=Wheel(pattern='./scratch/wheels/*.whl')),
ArtefactDescription(generated=OciImage(name='prngl')), ArtefactDescription(generated=OciImage(name='prngl')),
], ],
deployments=[ deployments=[
@@ -145,7 +136,6 @@ class TestProjectDescription(TestCase):
namespace='prngl-testing')) namespace='prngl-testing'))
]) ])
@patch('release.project.toolkit.Gitea', MockGiteaTool)
def test_environment_variables(self): def test_environment_variables(self):
# motacilla # motacilla
desc = ProjectDescription( desc = ProjectDescription(
@@ -194,7 +184,6 @@ class TestProjectDescription(TestCase):
'RELEASE_IMAGE_LOCAL_NAME_MOTACILLA_CDN': 'RELEASE_IMAGE_LOCAL_NAME_MOTACILLA_CDN':
'motacilla-cdn:0AB123', 'motacilla-cdn:0AB123',
'RELEASE_IS_PRERELEASE': '1', 'RELEASE_IS_PRERELEASE': '1',
'RELEASE_PROJECT_IS_RELEASED': '0',
'RELEASE_PROJECT_CURRENT_VERSION': '2.10.4', 'RELEASE_PROJECT_CURRENT_VERSION': '2.10.4',
'RELEASE_PROJECT_PLANNED_VERSION': '2.10.4-dev42' 'RELEASE_PROJECT_PLANNED_VERSION': '2.10.4-dev42'
} }
@@ -211,9 +200,9 @@ class TestProjectDescription(TestCase):
tarball.make_release_info(None, Version(1, 2, 3, 'dev4'))) tarball.make_release_info(None, Version(1, 2, 3, 'dev4')))
def test_wheel_release_info(self): def test_wheel_release_info(self):
wheel = Wheel(filename='dist/wheels/*') wheel = Wheel(pattern='dist/wheels/*')
self.assertEqual( self.assertEqual(
WheelReleaseInfo(filename='dist/wheels/*', WheelReleaseInfo(pattern='dist/wheels/*',
repository='gitea', repository='gitea',
version_str='1.2.3.dev4'), version_str='1.2.3.dev4'),
wheel.make_release_info(None, Version(1, 2, 3, 'dev4'))) wheel.make_release_info(None, Version(1, 2, 3, 'dev4')))
@@ -304,12 +293,11 @@ class TestProjectDescription(TestCase):
img.make_release_info(release_context, release_version)) img.make_release_info(release_context, release_version))
def test_project_release_info(self): def test_project_release_info(self):
project_0 = ProjectDescription( project_0 = ProjectDescription(version_descriptor='version.txt')
version_descriptor='test-assets/version.txt')
self.assertIsNone(project_0.release_info) self.assertIsNone(project_0.release_info)
project_pre = ProjectDescription( project_pre = ProjectDescription(
version_descriptor='test-assets/version.txt', version_descriptor='version.txt',
context=ReleaseContext( context=ReleaseContext(
repository_name='resi', repository_name='resi',
ref_name='testing', ref_name='testing',
@@ -320,16 +308,16 @@ class TestProjectDescription(TestCase):
self.assertEqual( self.assertEqual(
ProjectReleaseInfo( ProjectReleaseInfo(
gitea_release_title='Version 1.33.7-dev42', gitea_release_title='Version 0.0.1-dev42',
gitea_release_description='', gitea_release_description='',
gitea_is_prerelease=True, gitea_is_prerelease=True,
gitea_git_commitish='PROBABLY_BROKEN', gitea_git_commitish='PROBABLY_BROKEN',
git_tags=['v1.33.7-dev42', 'development'], git_tags=['v0.0.1-dev42', 'development'],
), ),
project_pre.release_info) project_pre.release_info)
project = ProjectDescription( project = ProjectDescription(
version_descriptor='test-assets/version.txt', version_descriptor='version.txt',
context=ReleaseContext( context=ReleaseContext(
repository_name='resi', repository_name='resi',
ref_name='master', ref_name='master',
@@ -340,11 +328,11 @@ class TestProjectDescription(TestCase):
self.assertEqual( self.assertEqual(
ProjectReleaseInfo( ProjectReleaseInfo(
gitea_release_title='Version 1.33.7', gitea_release_title='Version 0.0.1',
gitea_release_description='', gitea_release_description='',
gitea_is_prerelease=False, gitea_is_prerelease=False,
gitea_git_commitish='PROBABLY_BROKEN', gitea_git_commitish='PROBABLY_BROKEN',
git_tags=['v1.33.7', 'v1.33', 'v1', 'latest'], git_tags=['v0.0.1', 'v0.0', 'v0', 'latest'],
), ),
project.release_info) project.release_info)
@@ -366,9 +354,9 @@ class TestProjectDescription(TestCase):
repository='balls')), repository='balls')),
ArtefactDescription(generated=Wheel( ArtefactDescription(generated=Wheel(
filename='./scratch/wheels/*.whl')), pattern='./scratch/wheels/*.whl')),
ArtefactDescription(generated=Wheel( ArtefactDescription(generated=Wheel(
filename='./scratch/wheels/*.whl', repository='other')), pattern='./scratch/wheels/*.whl', repository='other')),
ArtefactDescription(generated=Sdist( ArtefactDescription(generated=Sdist(
filename='./dist/papyru-0.0.1.tar.gz')), filename='./dist/papyru-0.0.1.tar.gz')),

View File

@@ -18,12 +18,12 @@ def _test_can_read_version(test, filename, expected):
def _test_can_write_version(test, filename): def _test_can_write_version(test, filename):
v = use_any(_asset_path(filename)) v = use_any(_asset_path(filename))
v.version = Version(1, 33, 7, 42) v.version = Version(1, 33, 7)
with NamedTemporaryFile() as tf: with NamedTemporaryFile() as tf:
v.store(tf.name) v.store(tf.name)
v2 = use_any(tf.name) v2 = use_any(tf.name)
test.assertEqual(v2.version, Version(1, 33, 7, 42)) test.assertEqual(v2.version, Version(1, 33, 7))
class TestSetupPy(TestCase): class TestSetupPy(TestCase):

View File

@@ -6,8 +6,6 @@ from logging import getLogger
import toml import toml
from semver import Version from semver import Version
from release.common import python_parse_version, python_version_str
logger = getLogger(__name__) logger = getLogger(__name__)
RE_SETUP_PY = re.compile(r'version\s?=\s?[\'"](.*)[\'"]') RE_SETUP_PY = re.compile(r'version\s?=\s?[\'"](.*)[\'"]')
@@ -26,13 +24,12 @@ class SetupPy:
self.filename = filename self.filename = filename
self.content = content self.content = content
self.version = python_parse_version(version_string.group(1)) self.version = Version.parse(version_string.group(1))
def store(self, destination=None): def store(self, destination=None):
destination = destination or self.filename destination = destination or self.filename
edited = RE_SETUP_PY.sub( edited = RE_SETUP_PY.sub(
'version=\'%s\'' % python_version_str(self.version), 'version=\'%s\'' % self.version, self.content)
self.content)
with open(destination, 'w') as f: with open(destination, 'w') as f:
f.write(edited) f.write(edited)
@@ -47,7 +44,6 @@ class Structured:
for part in item_path: for part in item_path:
cur = cur[part] cur = cur[part]
self.filename = filename
self.format = format self.format = format
self.item_path = item_path self.item_path = item_path
self.content = obj self.content = obj

View File

@@ -1,30 +0,0 @@
name: "sync version descriptors"
description: "update all version descriptors to the planned version."
inputs: {}
runs:
using: composite
steps:
- name: declare project if neccessary
run: |
if [[ ! -z "${RELEASE_PROJECT_CURRENT_VERSION}" ]]; then
echo "already set up."
exit 0
fi
nix run ${{ github.action_path }} -- \
declare \
--release-yaml-filename ".gitea/release.yaml" \
--gitea-instance "https://gitea.puzzleyou.net" \
--release-repository-name "${{ github.repository }}" \
--release-ref-name "${{ github.ref_name }}" \
--release-run-number "${{ github.run_number }}" \
--release-commit-sha "${{ github.sha }}" \
--write-env-vars-to-filename "$GITHUB_ENV"
- name: sync versions
run: |
nix run ${{ github.action_path }} -- \
sync-versions \
--state "${RELEASE_ACTION_STATEFILE}"

1
version.txt Normal file
View File

@@ -0,0 +1 @@
0.0.1