init local

This commit is contained in:
16 changed files with 2522 additions and 0 deletions

124
.gitea/workflows/build.yaml Normal file
View File

@@ -0,0 +1,124 @@
name: Release Build
on:
push:
tags:
- v*
jobs:
create-docker-image:
runs-on: ubuntu-latest
container:
image: docker:28.3.2-dind
steps:
- name: Checkout repository
run: |
# Install git
apk add --no-cache git
echo "=== GitHub Variables ==="
echo "github.ref = ${{ github.ref }}"
echo "github.ref_name = ${{ github.ref_name }}"
echo "github.sha = ${{ github.sha }}"
echo "github.repository = ${{ github.repository }}"
echo "========================"
git clone https://oauth2:${{ secrets.GITEATOKEN }}@direct-dev.ru/gitea/GiteaAdmin/hello_gitea.git hello_gitea
cd hello_gitea
git checkout ${{ github.ref }}
- name: Setup Docker Buildx
run: |
# Docker is already installed in docker:dind image
docker --version
# Setup Docker Buildx for multi-platform builds
docker buildx create --use
docker buildx inspect --bootstrap
- name: Login to Docker Hub
run: |
echo ${{ secrets.DOCKERHUB_TOKEN }} | docker login -u ${{ secrets.DOCKERHUB_USERNAME }} --password-stdin
- name: Build multi-platform Docker images
run: |
cd hello_gitea
# Build multi-platform images using buildx
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag ${{ secrets.DOCKERHUB_USERNAME }}/hello-api:${{ github.ref_name }} \
--tag ${{ secrets.DOCKERHUB_USERNAME }}/hello-api:latest \
--push \
.
create-release:
runs-on: ubuntu-latest
container:
# image: golang:1.21
image: ${DOCKERHUB_USERNAME}/my-build-golang-runner:latest
needs: create-docker-image
steps:
- name: Checkout repository
run: |
git clone https://oauth2:${{ secrets.GITEATOKEN }}@direct-dev.ru/gitea/GiteaAdmin/hello_gitea.git hello_gitea
cd hello_gitea
git checkout ${{ github.ref }}
- name: Setup Go
run: |
# Install jq for JSON parsing
apt-get update && apt-get install -y jq
git --version
go version
jq --version
- name: Build all binaries
run: |
cd hello_gitea
mkdir -p bin
# Build for all platforms
GOOS=linux GOARCH=amd64 go build -o bin/hello-api-linux-amd64 main.go
GOOS=linux GOARCH=arm64 go build -o bin/hello-api-linux-arm64 main.go
GOOS=windows GOARCH=amd64 go build -o bin/hello-api-windows-amd64.exe main.go
GOOS=darwin GOARCH=amd64 go build -o bin/hello-api-darwin-amd64 main.go
GOOS=darwin GOARCH=arm64 go build -o bin/hello-api-darwin-arm64 main.go
# Create archives
cd bin
tar -czf hello-api-linux-amd64.tar.gz hello-api-linux-amd64
tar -czf hello-api-linux-arm64.tar.gz hello-api-linux-arm64
tar -czf hello-api-windows-amd64.tar.gz hello-api-windows-amd64.exe
tar -czf hello-api-darwin-amd64.tar.gz hello-api-darwin-amd64
tar -czf hello-api-darwin-arm64.tar.gz hello-api-darwin-arm64
ls -la
- name: Create Release
run: |
cd hello_gitea
# Create release using Gitea API
curl -X POST \
-H "Authorization: token ${{ secrets.GITEATOKEN }}" \
-H "Content-Type: application/json" \
-d '{
"tag_name": "${{ github.ref_name }}",
"name": "Release ${{ github.ref_name }}",
"body": "Automated release with multi-platform binaries and Docker image",
"draft": false,
"prerelease": false
}' \
"https://direct-dev.ru/gitea/api/v1/repos/GiteaAdmin/hello_gitea/releases"
# Upload assets
RELEASE_ID=$(curl -s -H "Authorization: token ${{ secrets.GITEATOKEN }}" \
"https://direct-dev.ru/gitea/api/v1/repos/GiteaAdmin/hello_gitea/releases/tags/${{ github.ref_name }}" | \
jq -r '.id')
# Upload all binaries
for file in bin/*.tar.gz; do
echo "Uploading $file..."
curl -X POST \
-H "Authorization: token ${{ secrets.GITEATOKEN }}" \
-H "Content-Type: application/octet-stream" \
--data-binary @$file \
"https://direct-dev.ru/gitea/api/v1/repos/GiteaAdmin/hello_gitea/releases/$RELEASE_ID/assets?name=$(basename $file)"
done

View File

@@ -0,0 +1,51 @@
name: Release Build
on:
push:
tags:
- builder-*
jobs:
create-builder-docker-image:
runs-on: ubuntu-latest
container:
image: docker:28.3.2-dind
steps:
- name: Checkout repository
run: |
# Install git
apk add --no-cache git
echo "=== GitHub Variables ==="
echo "github.ref = ${{ github.ref }}"
echo "github.ref_name = ${{ github.ref_name }}"
echo "github.sha = ${{ github.sha }}"
echo "github.repository = ${{ github.repository }}"
echo "========================"
git clone https://oauth2:${{ secrets.GITEATOKEN }}@direct-dev.ru/gitea/GiteaAdmin/hello_gitea.git hello_gitea
cd hello_gitea
git checkout ${{ github.ref }}
- name: Setup Docker Buildx
run: |
# Docker is already installed in docker:dind image
docker --version
# Setup Docker Buildx for multi-platform builds
docker buildx create --use
docker buildx inspect --bootstrap
- name: Login to Docker Hub
run: |
echo ${{ secrets.DOCKERHUB_TOKEN }} | docker login -u ${{ secrets.DOCKERHUB_USERNAME }} --password-stdin
- name: Build multi-platform Docker images
run: |
cd hello_gitea
# Build multi-platform images using buildx
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag ${{ secrets.DOCKERHUB_USERNAME }}/my-build-golang-runner:${{ github.ref_name }} \
--tag ${{ secrets.DOCKERHUB_USERNAME }}/my-build-golang-runner:latest \
--push \
-f Dockerfile.builder \
.

28
.gitignore vendored Normal file
View File

@@ -0,0 +1,28 @@
# ---> Go
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# Go workspace file
go.work
go.work.sum
# env file
.env
bin/
dockerhub_token

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"makefile.configureOnOpen": false
}

51
Dockerfile Normal file
View File

@@ -0,0 +1,51 @@
# Build stage
FROM --platform=$BUILDPLATFORM golang:1.21-alpine AS builder
# Install git and ca-certificates
RUN apk --no-cache add git ca-certificates
WORKDIR /app
# Copy go mod files
COPY go.mod go.sum ./
# Download dependencies
RUN go mod download
# Copy source code
COPY . .
# Build the application for target platform
ARG TARGETPLATFORM
ARG BUILDPLATFORM
ARG TARGETOS
ARG TARGETARCH
RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -a -installsuffix cgo -o hello-api main.go
# Final stage
FROM alpine:latest
# Install jq and ca-certificates
RUN apk --no-cache add ca-certificates jq
# Create non-root user
RUN addgroup -g 1001 -S appgroup && \
adduser -u 1001 -S appuser -G appgroup
WORKDIR /app
# Copy binary from builder stage
COPY --from=builder /app/hello-api .
# Change ownership to non-root user
RUN chown appuser:appgroup hello-api
# Switch to non-root user
USER appuser
# Expose port (if your app uses one)
EXPOSE 8080
# Run the application
CMD ["./hello-api"]

13
Dockerfile.builder Normal file
View File

@@ -0,0 +1,13 @@
# Используем образ Go с поддержкой мультиплатформенности
FROM golang:1.24
# Устанавливаем пакеты (одинаково работают на amd64/arm64)
RUN apt-get update && \
apt-get install -y --no-install-recommends \
git \
ca-certificates \
jq && \
rm -rf /var/lib/apt/lists/*
# (Опционально) Можно добавить команду по умолчанию
CMD ["bash"]

18
LICENSE Normal file
View File

@@ -0,0 +1,18 @@
MIT License
Copyright (c) 2025 GiteaAdmin
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF 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.

154
README.md Normal file
View File

@@ -0,0 +1,154 @@
# Hello Gitea API
Простой REST API сервер, построенный на Go с использованием Gin framework.
## 🚀 Возможности
- ✅ REST API с JSON ответами
- ✅ Health check endpoint
- ✅ CORS поддержка
- ✅ Мультиплатформенная сборка
- ✅ Docker образы для Linux AMD64/ARM64
- ✅ Автоматические релизы через Gitea Actions
## 📦 Установка
### Из бинарного файла
1. Скачайте бинарный файл для вашей платформы из [релизов](https://direct-dev.ru/gitea/GiteaAdmin/hello_gitea/releases)
2. Распакуйте архив
3. Запустите: `./hello-api-<platform>`
### Из Docker образа
```bash
docker pull <username>/hello-api:latest
docker run -p 8080:8080 <username>/hello-api:latest
```
### Из исходного кода
```bash
git clone https://direct-dev.ru/gitea/GiteaAdmin/hello_gitea.git
cd hello_gitea
go mod download
go run main.go
```
## 🔧 Конфигурация
Сервер запускается на порту 8080 по умолчанию. Можно изменить через переменную окружения:
```bash
export PORT=3000
./hello-api
```
## 📡 API Endpoints
### GET /
Основной endpoint
**Ответ:**
```json
{
"message": "Hello, World!",
"version": "1.0.0"
}
```
### GET /health
Health check endpoint
**Ответ:**
```json
{
"status": "ok",
"version": "1.0.0"
}
```
### GET /api/v1/info
Информация о сервисе
**Ответ:**
```json
{
"service": "hello-api",
"status": "running",
"version": "1.0.0"
}
```
### POST /api/v1/echo
Echo endpoint - возвращает отправленное сообщение
**Запрос:**
```json
{
"message": "Hello from client!"
}
```
**Ответ:**
```json
{
"echo": "Hello from client!",
"version": "1.0.0"
}
```
## 🛠 Разработка
### Зависимости
- Go 1.21+
- Gin framework
### Сборка
```bash
# Для текущей платформы
go build -o hello-api main.go
# Для Linux AMD64
GOOS=linux GOARCH=amd64 go build -o hello-api-linux-amd64 main.go
# Для Linux ARM64
GOOS=linux GOARCH=arm64 go build -o hello-api-linux-arm64 main.go
# Для Windows
GOOS=windows GOARCH=amd64 go build -o hello-api-windows-amd64.exe main.go
# Для macOS
GOOS=darwin GOARCH=amd64 go build -o hello-api-darwin-amd64 main.go
GOOS=darwin GOARCH=arm64 go build -o hello-api-darwin-arm64 main.go
```
### Тестирование
```bash
# Запуск сервера
go run main.go
# Тестирование API
curl http://localhost:8080/
curl http://localhost:8080/health
curl http://localhost:8080/api/v1/info
curl -X POST http://localhost:8080/api/v1/echo \
-H "Content-Type: application/json" \
-d '{"message":"Hello!"}'
```
## 🚀 CI/CD
При создании тега (например, `v1.1.0`) автоматически:
1. Собираются бинарники для всех платформ
2. Создается Docker образ для Linux AMD64/ARM64
3. Образ публикуется в Docker Hub
4. Создается релиз в Gitea с бинарниками
## 📄 Лицензия
MIT License

View File

@@ -0,0 +1,8 @@
#!/bin/bash
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag ${DOCKERHUB_USERNAME}/my-build-golang-runner:latest \
--push \
-f Dockerfile_for_runner_image \
.

1647
docs/gitea-actions-guide.md Normal file

File diff suppressed because it is too large Load Diff

34
go.mod Normal file
View File

@@ -0,0 +1,34 @@
module direct-dev-ru/hello_gitea
go 1.21
require github.com/gin-gonic/gin v1.10.1
require (
github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.20.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.8.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
google.golang.org/protobuf v1.34.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

89
go.sum Normal file
View File

@@ -0,0 +1,89 @@
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

87
main.go Normal file
View File

@@ -0,0 +1,87 @@
package main
import (
"net/http"
"os"
"github.com/gin-gonic/gin"
)
const version = "1.0.0"
func main() {
// Set Gin mode
gin.SetMode(gin.ReleaseMode)
// Create router
r := gin.Default()
// Add middleware for CORS
r.Use(func(c *gin.Context) {
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
c.Header("Access-Control-Allow-Headers", "Origin, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(http.StatusNoContent)
return
}
c.Next()
})
// Health check endpoint
r.GET("/health", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"status": "ok",
"version": version,
})
})
// Main endpoint
r.GET("/", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "Hello, World!",
"version": version,
})
})
// API endpoints
api := r.Group("/api/v1")
{
api.GET("/info", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"service": "hello-api",
"version": version,
"status": "running",
})
})
api.POST("/echo", func(c *gin.Context) {
var request struct {
Message string `json:"message"`
}
if err := c.ShouldBindJSON(&request); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "Invalid JSON",
})
return
}
c.JSON(http.StatusOK, gin.H{
"echo": request.Message,
"version": version,
})
})
}
// Get port from environment or use default
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
// Start server
r.Run(":" + port)
}

25
makefile Normal file
View File

@@ -0,0 +1,25 @@
.PHONY: build clean test release
BIN_DIR=bin
APP_NAME=hello-api
VERSION=1.0.0
build:
mkdir -p $(BIN_DIR)
go build -o $(BIN_DIR)/$(APP_NAME)-$(VERSION) main.go
clean:
rm -rf $(BIN_DIR)
test:
go test -v ./...
# Задача для создания релиза
# Использование: make release VERSION=1.0.25
release:
# @if [ -z "$(VERSION)" ]; then \
# echo "Ошибка: Необходимо указать версию"; \
# echo "Использование: make release VERSION=1.0.25"; \
# exit 1; \
# fi
@./scripts/release-interactive.sh $(VERSION)

114
scripts/release-interactive.sh Executable file
View File

@@ -0,0 +1,114 @@
#!/bin/bash
# Интерактивный скрипт для автоматизации релиза
# Использование: ./scripts/release-interactive.sh [version]
# Если версия не указана, скрипт запросит её интерактивно
set -e # Остановить выполнение при ошибке
# Функция для получения версии интерактивно
get_version_interactive() {
echo "🚀 Создание нового релиза"
echo ""
# Показываем текущую версию
CURRENT_VERSION=$(grep 'const version = "' main.go | sed 's/const version = "\([^"]*\)"/\1/')
echo "📋 Текущая версия: $CURRENT_VERSION"
echo ""
# Запрашиваем новую версию
read -p "Введите новую версию (формат X.Y.Z): " VERSION
# Проверяем, что версия не пустая
if [ -z "$VERSION" ]; then
echo "❌ Версия не может быть пустой"
exit 1
fi
# Проверяем формат версии
if [[ ! $VERSION =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "❌ Неверный формат версии. Используйте формат X.Y.Z (например, 1.0.25)"
exit 1
fi
# Подтверждение
echo ""
echo "📝 Подтверждение:"
echo " Текущая версия: $CURRENT_VERSION"
echo " Новая версия: $VERSION"
echo ""
read -p "Продолжить? (y/N): " CONFIRM
if [[ ! $CONFIRM =~ ^[Yy]$ ]]; then
echo "❌ Релиз отменен"
exit 0
fi
}
# Проверяем, передана ли версия как аргумент
if [ $# -eq 0 ]; then
# Версия не указана, запрашиваем интерактивно
get_version_interactive
else
# Версия указана как аргумент
VERSION=$1
# Проверка формата версии
if [[ ! $VERSION =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Ошибка: Неверный формат версии. Используйте формат X.Y.Z (например, 1.0.25)"
exit 1
fi
fi
echo "🚀 Начинаем релиз версии v$VERSION..."
# Проверяем, что мы в git репозитории
if ! git rev-parse --git-dir > /dev/null 2>&1; then
echo "Ошибка: Не найден git репозиторий"
exit 1
fi
# Проверяем, что нет незакоммиченных изменений
# if ! git diff-index --quiet HEAD --; then
# echo "Ошибка: Есть незакоммиченные изменения. Сначала закоммитьте их."
# exit 1
# fi
# Обновляем версию в main.go
echo "📝 Обновляем версию в main.go..."
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS
sed -i '' "s/const version = \"[^\"]*\"/const version = \"$VERSION\"/" main.go
else
# Linux
sed -i "s/const version = \"[^\"]*\"/const version = \"$VERSION\"/" main.go
fi
# Проверяем, что изменение применилось
if ! grep -q "const version = \"$VERSION\"" main.go; then
echo "Ошибка: Не удалось обновить версию в main.go"
exit 1
fi
echo "✅ Версия обновлена в main.go"
# Выполняем git команды
echo "📦 Добавляем изменения в git..."
git add .
echo "💾 Создаем коммит..."
git commit -m "Release v$VERSION"
echo "🏷️ Создаем тег..."
git tag -a "v$VERSION" -m "Release v$VERSION"
echo "🚀 Отправляем изменения и теги..."
git push
git push --tags
echo "🎉 Релиз v$VERSION успешно завершен!"
echo "📋 Выполненные действия:"
echo " - Обновлена версия в main.go"
echo " - Создан коммит с сообщением 'Release v$VERSION'"
echo " - Создан тег v$VERSION"
echo " - Изменения отправлены в удаленный репозиторий"

76
scripts/release.sh Executable file
View File

@@ -0,0 +1,76 @@
#!/bin/bash
# Скрипт для автоматизации релиза
# Использование: ./scripts/release.sh <version>
# Пример: ./scripts/release.sh 1.0.25
set -e # Остановить выполнение при ошибке
# Проверка аргументов
if [ $# -eq 0 ]; then
echo "Ошибка: Необходимо указать версию"
echo "Использование: $0 <version>"
echo "Пример: $0 1.0.25"
exit 1
fi
VERSION=$1
# Проверка формата версии (простая проверка)
if [[ ! $VERSION =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Ошибка: Неверный формат версии. Используйте формат X.Y.Z (например, 1.0.25)"
exit 1
fi
echo "🚀 Начинаем релиз версии v$VERSION..."
# Проверяем, что мы в git репозитории
if ! git rev-parse --git-dir > /dev/null 2>&1; then
echo "Ошибка: Не найден git репозиторий"
exit 1
fi
# Проверяем, что нет незакоммиченных изменений
if ! git diff-index --quiet HEAD --; then
echo "Ошибка: Есть незакоммиченные изменения. Сначала закоммитьте их."
exit 1
fi
# Обновляем версию в main.go
echo "📝 Обновляем версию в main.go..."
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS
sed -i '' "s/const version = \"[^\"]*\"/const version = \"$VERSION\"/" main.go
else
# Linux
sed -i "s/const version = \"[^\"]*\"/const version = \"$VERSION\"/" main.go
fi
# Проверяем, что изменение применилось
if ! grep -q "const version = \"$VERSION\"" main.go; then
echo "Ошибка: Не удалось обновить версию в main.go"
exit 1
fi
echo "✅ Версия обновлена в main.go"
# Выполняем git команды
echo "📦 Добавляем изменения в git..."
git add .
echo "💾 Создаем коммит..."
git commit -m "Release v$VERSION"
echo "🏷️ Создаем тег..."
git tag -a "v$VERSION" -m "Release v$VERSION"
echo "🚀 Отправляем изменения и теги..."
git push
git push --tags
echo "🎉 Релиз v$VERSION успешно завершен!"
echo "📋 Выполненные действия:"
echo " - Обновлена версия в main.go"
echo " - Создан коммит с сообщением 'Release v$VERSION'"
echo " - Создан тег v$VERSION"
echo " - Изменения отправлены в удаленный репозиторий"