Compare commits

..

9 Commits

4 changed files with 2 additions and 209 deletions
+2 -104
View File
@@ -8,7 +8,7 @@ on:
workflow_dispatch:
inputs:
version:
description: 'Version tag (e.g. v1.26.1-moko.05.01.00)'
description: 'Version tag (e.g. v1.26.1-moko.04.00.00)'
required: true
default: 'latest'
environment:
@@ -30,7 +30,6 @@ env:
DEPLOY_HOST: git.mokoconsulting.tech
DEPLOY_PORT: 2918
DEPLOY_USER: mokoconsulting
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
deploy:
@@ -48,30 +47,15 @@ jobs:
echo "source_dir=/opt/gitea/source" >> $GITHUB_OUTPUT
echo "branch=main" >> $GITHUB_OUTPUT
echo "tag=${VERSION}" >> $GITHUB_OUTPUT
echo "instance_url=https://git.mokoconsulting.tech" >> $GITHUB_OUTPUT
else
echo "compose_dir=/opt/gitea-dev" >> $GITHUB_OUTPUT
echo "container=mokogitea-dev" >> $GITHUB_OUTPUT
echo "source_dir=/opt/gitea-dev/source" >> $GITHUB_OUTPUT
echo "branch=dev" >> $GITHUB_OUTPUT
echo "tag=${VERSION}-dev" >> $GITHUB_OUTPUT
echo "instance_url=https://git.dev.mokoconsulting.tech" >> $GITHUB_OUTPUT
fi
- name: Enable maintenance mode
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
INSTANCE_URL: ${{ steps.config.outputs.instance_url }}
run: |
echo "Enabling maintenance mode on ${INSTANCE_URL}..."
curl -sf -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/x-www-form-urlencoded" \
"${INSTANCE_URL}/-/admin/config" \
-d 'key=instance.maintenance_mode&value={"AdminWebAccessOnly":true}' \
|| echo "WARNING: Could not enable maintenance mode (instance may be down)"
- name: Build and deploy via SSH
- name: Build, push, and deploy via SSH
env:
SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
TAG: ${{ steps.config.outputs.tag }}
@@ -140,92 +124,6 @@ jobs:
exit 1
"
- name: Update updates.xml
if: success()
env:
GITEA_TOKEN: ${{ secrets.GA_TOKEN }}
TAG: ${{ steps.config.outputs.tag }}
INSTANCE_URL: ${{ steps.config.outputs.instance_url }}
DEPLOY_ENV: ${{ github.event.inputs.environment }}
run: |
# Only update updates.xml for production stable releases
if [ "$DEPLOY_ENV" != "production" ]; then
echo "Skipping updates.xml — dev deployments don't update stable channel"
exit 0
fi
# Extract moko version from tag (e.g. v1.26.1-moko.05.01.01 -> 05.01.01)
MOKO_VER=$(echo "$TAG" | sed -n 's/.*-moko\.\(.*\)/\1/p')
if [ -z "$MOKO_VER" ]; then
echo "Could not extract moko version from tag: $TAG"
exit 0
fi
RELEASE_URL="https://${REGISTRY}/MokoConsulting/MokoGitea/releases/tag/${TAG}"
DOCKER_IMG="${REGISTRY}/${IMAGE}:${TAG}"
python3 << PYEOF
import json, os, re, base64, urllib.request
token = os.environ["GITEA_TOKEN"]
registry = os.environ["REGISTRY"]
tag = os.environ["TAG"]
moko_ver = os.environ["MOKO_VER"]
release_url = os.environ["RELEASE_URL"]
docker_img = os.environ["DOCKER_IMG"]
api = f"https://{registry}/api/v1/repos/MokoConsulting/MokoGitea"
# Fetch current updates.xml
req = urllib.request.Request(f"{api}/contents/updates.xml?ref=main",
headers={"Authorization": f"token {token}"})
with urllib.request.urlopen(req) as resp:
data = json.loads(resp.read())
sha = data["sha"]
content = base64.b64decode(data["content"]).decode("utf-8")
# Update stable channel version, infourl, and docker tag
content = re.sub(
r"(<tags><tag>stable</tag></tags>[\s\S]*?<version>)[^<]*(</version>)",
rf"\g<1>{moko_ver}\2", content)
content = re.sub(
r"(<tags><tag>stable</tag></tags>[\s\S]*?<infourl[^>]*>)[^<]*(</infourl>)",
rf"\g<1>{release_url}\2", content)
content = re.sub(
r"(<tags><tag>stable</tag></tags>[\s\S]*?<downloadurl[^>]*>)[^<]*(</downloadurl>)",
rf"\g<1>{docker_img}\2", content)
# Also update VERSION comment at top
content = re.sub(r"VERSION: [^\n]*", f"VERSION: {moko_ver}", content)
# Push updated file
encoded = base64.b64encode(content.encode()).decode()
payload = json.dumps({
"message": f"chore(ci): update updates.xml to {moko_ver}",
"content": encoded,
"sha": sha,
"branch": "main",
}).encode()
req = urllib.request.Request(f"{api}/contents/updates.xml",
data=payload, method="PUT",
headers={"Authorization": f"token {token}", "Content-Type": "application/json"})
with urllib.request.urlopen(req) as resp:
print(f"updates.xml updated to {moko_ver}")
PYEOF
- name: Disable maintenance mode
if: always()
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
INSTANCE_URL: ${{ steps.config.outputs.instance_url }}
run: |
echo "Disabling maintenance mode on ${INSTANCE_URL}..."
curl -sf -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/x-www-form-urlencoded" \
"${INSTANCE_URL}/-/admin/config" \
-d 'key=instance.maintenance_mode&value={"AdminWebAccessOnly":false}' \
|| echo "WARNING: Could not disable maintenance mode"
- name: Verify
run: |
sleep 5
@@ -18,7 +18,6 @@ import (
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/context"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/context/upload"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/convert"
release_service "git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/release"
)
func checkReleaseMatchRepo(ctx *context.APIContext, releaseID int64) bool {
@@ -264,14 +263,6 @@ func CreateReleaseAttachment(ctx *context.APIContext) {
return
}
// Regenerate checksums after new attachment
rel, relErr := repo_model.GetReleaseByID(ctx, releaseID)
if relErr == nil {
if checksumErr := release_service.GenerateReleaseChecksums(ctx, rel); checksumErr != nil {
log.Error("GenerateReleaseChecksums after upload: %v", checksumErr)
}
}
ctx.JSON(http.StatusCreated, convert.ToAPIAttachment(ctx.Repo.Repository, attach))
}
-82
View File
@@ -1,82 +0,0 @@
// Copyright 2026 Moko Consulting <hello@mokoconsulting.tech>
// SPDX-License-Identifier: GPL-3.0-or-later
package release
import (
"bytes"
"context"
"crypto/sha256"
"fmt"
"io"
repo_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/storage"
attachment_service "git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/attachment"
)
// GenerateReleaseChecksums computes SHA256 checksums for all attachments
// on a release and adds a checksums.sha256 manifest file as an attachment.
func GenerateReleaseChecksums(ctx context.Context, rel *repo_model.Release) error {
// Load attachments into rel.Attachments
if err := repo_model.GetReleaseAttachments(ctx, rel); err != nil {
return fmt.Errorf("GetReleaseAttachments: %w", err)
}
if len(rel.Attachments) == 0 {
return nil
}
// Remove existing checksums file if present
for _, a := range rel.Attachments {
if a.Name == "checksums.sha256" {
if err := repo_model.DeleteAttachment(ctx, a, true); err != nil {
log.Warn("Failed to delete old checksums.sha256: %v", err)
}
break
}
}
// Compute SHA256 for each attachment
var manifest bytes.Buffer
for _, a := range rel.Attachments {
if a.Name == "checksums.sha256" {
continue
}
fr, err := storage.Attachments.Open(a.RelativePath())
if err != nil {
log.Warn("Cannot open attachment %s for checksumming: %v", a.Name, err)
continue
}
h := sha256.New()
if _, err := io.Copy(h, fr); err != nil {
fr.Close()
log.Warn("Cannot read attachment %s for checksumming: %v", a.Name, err)
continue
}
fr.Close()
fmt.Fprintf(&manifest, "%x %s\n", h.Sum(nil), a.Name)
}
if manifest.Len() == 0 {
return nil
}
// Create the checksums.sha256 attachment
checksumAttach := &repo_model.Attachment{
RepoID: rel.RepoID,
ReleaseID: rel.ID,
Name: "checksums.sha256",
}
if _, err := attachment_service.NewAttachment(ctx, checksumAttach, &manifest, int64(manifest.Len())); err != nil {
return fmt.Errorf("create checksums.sha256 attachment: %w", err)
}
log.Info("Generated checksums.sha256 for release %s (repo %d)", rel.TagName, rel.RepoID)
return nil
}
-14
View File
@@ -190,13 +190,6 @@ func CreateRelease(gitRepo *git.Repository, rel *repo_model.Release, attachmentU
return err
}
// Generate SHA256 checksums for all release attachments
if len(attachmentUUIDs) > 0 {
if err := GenerateReleaseChecksums(gitRepo.Ctx, rel); err != nil {
log.Error("GenerateReleaseChecksums for %s: %v", rel.TagName, err)
}
}
if !rel.IsDraft {
notify_service.NewRelease(gitRepo.Ctx, rel)
}
@@ -351,13 +344,6 @@ func UpdateRelease(ctx context.Context, doer *user_model.User, gitRepo *git.Repo
}
}
// Regenerate checksums when attachments change
if len(addAttachmentUUIDs) > 0 || len(delAttachmentUUIDs) > 0 {
if err := GenerateReleaseChecksums(ctx, rel); err != nil {
log.Error("GenerateReleaseChecksums for %s: %v", rel.TagName, err)
}
}
if !rel.IsDraft {
if !isTagCreated && !isConvertedFromTag {
notify_service.UpdateRelease(gitRepo.Ctx, doer, rel)