Skip to content
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
74 changes: 74 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: Release

on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
tag:
description: 'Git tag to release (e.g. v2.6.10)'
required: true

permissions:
contents: write

jobs:
build-and-release:
name: Build and Create GitHub Release
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ inputs.tag || github.ref }}

- name: Set up JDK 8
uses: actions/setup-java@v4
with:
java-version: '8'
distribution: 'zulu'
cache: maven

- name: Run Maven verify
run: mvn --batch-mode verify -DskipITs -Dgpg.skip

- name: Build SDK Artifacts
run: mvn --batch-mode clean package -Pshade-all -DskipTests

- name: Collect release assets
run: |
mkdir -p release-assets
cp target/qingstor.sdk.java-*.jar release-assets/
rm -f release-assets/*-sources.jar release-assets/*-javadoc.jar
ls -la release-assets/

- name: Extract Release Notes from CHANGELOG.md
id: changelog
run: |
TAG="${{ inputs.tag || github.ref_name }}"
VERSION="${TAG#v}"
sed -n "/^## \[v\?${VERSION}\]/,/^## \[v\?[0-9]/p" CHANGELOG.md | sed '1d;$d' > RELEASE_NOTES.md
if [ ! -s RELEASE_NOTES.md ]; then
echo "Release notes for ${TAG} not found in CHANGELOG.md, fallback to auto-generate."
rm -f RELEASE_NOTES.md
fi

- name: Create GitHub Release
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ inputs.tag || github.ref_name }}
run: |
RELEASE_ARGS=(
"$TAG"
release-assets/*
--title "Release $TAG"
)
if [ -s RELEASE_NOTES.md ]; then
RELEASE_ARGS+=(--notes-file RELEASE_NOTES.md)
else
RELEASE_ARGS+=(--generate-notes)
fi
gh release create "${RELEASE_ARGS[@]}"
35 changes: 35 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Repository Guidelines

## Project Structure & Module Organization

This is a Maven-based Java SDK for QingStor. Main source lives in `src/main/java/com/qingstor/sdk`, with resources in `src/main/resources`. Unit tests live under `src/test/java/com/qingstor/sdk`; integration and Cucumber tests live under `src/test/java/integration/cucumber` and use feature files from `tests/features`. API specs are in `specs/qingstor`, code-generation templates are in `template`, and user-facing documentation is in `docs`. Architecture/release decisions belong in `docs/adr`, with implementation specs in `docs/specs`.

## Build, Test, and Development Commands

- `mvn test`: run unit tests, excluding integration tests.
- `mvn verify -DskipITs -Dgpg.skip`: run the CI-style Maven verify phase without signing.
- `mvn spotless:check`: verify formatting of Java and Markdown files.
- `mvn spotless:apply`: format Java and Markdown files according to repo style.
- `mvn integration-test`: run service/integration tests; configure local credentials from `tests/config.yaml.example` or `tests/test_config.yaml.example`.
- `mvn package -Prelease`: build normal jar, sources, and javadocs.
- `mvn clean -Pshade-all -DskipTests package`: build the shaded jar at `target/qingstor.sdk.java-<version>-shaded.jar`.
- `make generate`: regenerate service code from Swagger specs using `snips`, then apply formatting.

## Coding Style & Naming Conventions

Java targets source/bytecode level 8. Formatting is managed by Spotless with google-java-format `1.7` in AOSP style and the header in `spotless.license.java`; run `mvn spotless:apply` before committing generated or manually edited Java. Use package names under `com.qingstor.sdk`. Keep test classes named `*Test` and integration/Cucumber classes grouped under the existing integration package.

## Testing Guidelines

Use JUnit 4 for unit tests and Cucumber for behavior/integration coverage. Prefer focused unit tests for utility and model behavior; reserve integration tests for QingStor service workflows that require credentials. Do not commit local secrets or generated test config files.

## Commit & Pull Request Guidelines

Recent commits use concise, imperative subjects with optional prefixes, for example `fix(delete-obj): ...`, `deps: ...`, `chore: ...`, and `Bump version to ...`. Keep commits scoped to one concern. Pull requests should describe the behavior change, list verification commands run, link related issues when available, and call out release-impacting changes such as dependency updates, Central publishing, or shaded jar behavior.

## Release Guidelines

- **Release Guide & SOP**: See [`docs/release.md`](docs/release.md) for the complete, step-by-step maintainer release guide.
- **Version Bump Checklist**: Update version across `pom.xml`, `src/main/resources/version.properties`, `docs/install.md`, `docs/install_zh-CN.md`, and document changes in `CHANGELOG.md`.
- **GitHub Releases**: Automated via `.github/workflows/release.yml`. Pushing a tag `v<version>` automatically verifies, builds the standard JAR + shaded JAR, extracts notes from `CHANGELOG.md`, and creates the GitHub Release with assets attached.
- **Maven Central Publishing**: Use `mvn clean deploy -Prelease` (do NOT activate `shade-all`) to upload signed standard artifacts to Sonatype Central Portal, then confirm deployment in the portal.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@

All notable changes to QingStor SDK for JAVA will be documented in this file.

## [v2.6.10] - 2026-08-21

### Added

- Add GitHub Actions workflow for automated releases on tag push.
- Add maintainer release guide in `docs/release.md` and repository guidelines in `AGENTS.md`.

### Changed

- Improve error logging in `QSOkHttpRequestClient` to include stack traces.
- Update Maven Central badge and documentation links to use Shields.io and Sonatype Central Portal.

### Fixed

- Preserve root cause and enhance error message formatting in `QSException`.
- Preserve root cause exception on request execution and callback parsing failures in `QSOkHttpRequestClient`.

## [v2.6.9] - 2026-08-04

### Changed
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# QingStor SDK for Java

[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.yunify/qingstor.sdk.java/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.yunify/qingstor.sdk.java)
[![Maven Central](https://img.shields.io/maven-central/v/com.yunify/qingstor.sdk.java.svg)](https://central.sonatype.com/artifact/com.yunify/qingstor.sdk.java)
![Build Status](https://github.com/qingstor/qingstor-sdk-java/workflows/Unit%20Test/badge.svg)
[![API Reference](https://img.shields.io/badge/api-reference-green.svg)](https://docsv4.qingcloud.com/user_guide/storage/object_storage/)
[![License](https://img.shields.io/badge/license-apache%20v2-blue.svg)](https://github.com/yunify/qingstor-sdk-Java/blob/master/LICENSE)
Expand Down
2 changes: 1 addition & 1 deletion README_zh-CN.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# QingStor SDK for Java

[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.yunify/qingstor.sdk.java/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.yunify/qingstor.sdk.java)
[![Maven Central](https://img.shields.io/maven-central/v/com.yunify/qingstor.sdk.java.svg)](https://central.sonatype.com/artifact/com.yunify/qingstor.sdk.java)
![Build Status](https://github.com/qingstor/qingstor-sdk-java/workflows/Unit%20Test/badge.svg)
[![API Reference](https://img.shields.io/badge/api-reference-green.svg)](https://docsv4.qingcloud.com/user_guide/storage/object_storage/)
[![License](https://img.shields.io/badge/license-apache%20v2-blue.svg)](https://github.com/yunify/qingstor-sdk-Java/blob/master/LICENSE)
Expand Down
4 changes: 2 additions & 2 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ Maven:
<dependency>
<groupId>com.yunify</groupId>
<artifactId>qingstor.sdk.java</artifactId>
<version>2.6.9</version>
<version>2.6.10</version>
</dependency>
```

[Latest SDK jar](https://maven-badges.herokuapp.com/maven-central/com.yunify/qingstor.sdk.java) are available from Maven Central.
[Latest SDK jar](https://central.sonatype.com/artifact/com.yunify/qingstor.sdk.java) are available from Maven Central.

If you want to use a fatJar(with all deps included), you can download it from our [release page](https://github.com/qingstor/qingstor-sdk-java/releases/latest).
4 changes: 2 additions & 2 deletions docs/install_zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ Maven:
<dependency>
<groupId>com.yunify</groupId>
<artifactId>qingstor.sdk.java</artifactId>
<version>2.6.9</version>
<version>2.6.10</version>
</dependency>
```

[最新的 SDK jar](https://maven-badges.herokuapp.com/maven-central/com.yunify/qingstor.sdk.java) 可以从 Maven Central 获取.
[最新的 SDK jar](https://central.sonatype.com/artifact/com.yunify/qingstor.sdk.java) 可以从 Maven Central 获取.

如果你需要使用 fatJar(所有依赖打包在一起), 你可以从我们的 [发布页面](https://github.com/qingstor/qingstor-sdk-java/releases/latest) 下载.
103 changes: 103 additions & 0 deletions docs/release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Release Guide (发布操作手册)

本文档面向 QingStor Java SDK 维护者,详细记录了标准版本发布操作流程 (Release SOP)。

---

## 流程概览

```mermaid
flowchart TD
A["1. 更新版本号与 CHANGELOG.md"] --> B["2. 本地测试与代码格式校验"]
B --> C["3. 创建 release 分支并提 PR: gh pr create --fill"]
C --> D["4. 等待 CI 通过并 Rebase Merge"]
D --> E["5. master 打 Tag 并推送: git push origin v<version>"]
E --> F["【自动】GitHub Actions 自动构建并发布 GitHub Release"]
D --> G["6. 本地部署 Maven Central: mvn clean deploy -Prelease"]
G --> H["7. Sonatype Central Portal 确认并发布"]
```

---

## 详细步骤

### 第一步:版本号更新与本地校验

1. **更新版本号清单 (Version Bump)**:
- `pom.xml`: `<version>X.Y.Z</version>`
- `src/main/resources/version.properties`: `version=X.Y.Z`
- `docs/install.md`: Maven 依赖版本
- `docs/install_zh-CN.md`: Maven 依赖版本
- `CHANGELOG.md`: 补充 `## [vX.Y.Z] - YYYY-MM-DD` 对应更新日志
2. **本地执行验证**:
```bash
mvn spotless:apply
mvn test
mvn verify -DskipITs -Dgpg.skip
```

---

### 第二步:创建发布分支并提交 PR

```bash
# 1. 切出发布分支并提交
git checkout -b release/v<version>
git push -u origin release/v<version>

# 2. 使用 gh 创建 Pull Request
gh pr create --fill
```

---

### 第三步:等待 CI 校验并合并

```bash
# 1. 检查 CI 运行状态
gh pr checks

# 2. 执行 Rebase Merge(管理员使用 --admin 绕过审批限制立即合并)
gh pr merge --rebase --delete-branch --admin
```

> **说明**:仓库配置了 1 位 Reviewer 审批规则,维护者使用 `--admin` 参数可直接以管理员权限绕过限制完成合并(等同于网页端勾选 Bypass rules)。

---

### 第四步:打 Tag 触发 GitHub Release 自动化发布

```bash
# 1. 切换回 master 并拉取最新合并代码
git checkout master
git pull origin master

# 2. 打 Tag 并推送到 GitHub 远程仓库
git tag -a v<version> -m "Release v<version>"
git push origin v<version>

# 3. 监控 GitHub Actions 自动化发布进度
gh run watch
```

> **自动化说明**:
> GitHub Actions (`.github/workflows/release.yml`) 会在检测到 `v*` Tag 后自动触发:
> - 使用 JDK 8 环境执行验证
> - 自动打包生成标准 Jar 与 Shaded Jar
> - 自动从 `CHANGELOG.md` 提取当前版本的 Release Notes
> - 自动创建 GitHub Release 并附加两个 Jar 产物

---

### 第五步:发布至 Maven Central

在具备 GPG 私钥与 Sonatype 认证配置的环境下执行:

```bash
# 本地执行构建、签名与上传(切勿激活 shade-all Profile)
mvn clean deploy -Prelease
```

1. 上传成功后,登录 [Sonatype Central Portal](https://central.sonatype.com/)。
2. 在 **Deployments** 列表中确认当前部署包校验状态为 **Validated**。
3. 点击 **Publish** 按钮确认发布(约 15~30 分钟内全球镜像同步生效)。
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>com.yunify</groupId>
<artifactId>qingstor.sdk.java</artifactId>
<version>2.6.9</version>
<version>2.6.10</version>
<name>Qingcloud Qingstor SDK for Java</name>
<description>The official QingStor SDK for the Java programming language.</description>
<url>https://www.qingcloud.com/products/objectstorage/</url>
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/version.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version=2.6.9
version=2.6.10
Loading