name: Release on: push: branches: - main permissions: contents: write packages: write jobs: release: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 token: ${{ secrets.GITEA_TOKEN }} - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: 22 cache: npm - name: Set up Java uses: actions/setup-java@v4 with: distribution: temurin java-version: 17 cache: gradle cache-dependency-path: plugins/velocity/*.gradle.kts - name: Install dependencies run: npm ci - name: Validate release source run: | npm run design:validate npm run lint npm run typecheck npm test npm run build (cd plugins/velocity && ./gradlew clean test) - name: Capture previous tag id: previous_tag run: | if git describe --tags --abbrev=0 >/dev/null 2>&1; then echo "value=$(git describe --tags --abbrev=0)" >> "$GITHUB_OUTPUT" else echo "value=" >> "$GITHUB_OUTPUT" fi - name: Run semantic-release env: GITHUB_TOKEN: ${{ secrets.GITEA_TOKEN }} run: | npx -y \ -p semantic-release@24.2.9 \ -p @semantic-release/commit-analyzer@13.0.1 \ -p @semantic-release/release-notes-generator@14.1.0 \ semantic-release - name: Capture current tag id: current_tag run: | if git describe --tags --exact-match HEAD >/dev/null 2>&1; then echo "value=$(git describe --tags --exact-match HEAD)" >> "$GITHUB_OUTPUT" else echo "value=" >> "$GITHUB_OUTPUT" fi - name: Resolve release id: release env: PREVIOUS_TAG: ${{ steps.previous_tag.outputs.value }} CURRENT_TAG: ${{ steps.current_tag.outputs.value }} run: | if [ -n "$CURRENT_TAG" ] && [ "$CURRENT_TAG" != "$PREVIOUS_TAG" ]; then echo "created=true" >> "$GITHUB_OUTPUT" echo "tag=$CURRENT_TAG" >> "$GITHUB_OUTPUT" echo "version=${CURRENT_TAG#v}" >> "$GITHUB_OUTPUT" else echo "created=false" >> "$GITHUB_OUTPUT" fi - name: Build versioned Velocity JAR if: steps.release.outputs.created == 'true' env: VERSION: ${{ steps.release.outputs.version }} run: ./gradlew clean test shadowJar -PreleaseVersion="$VERSION" working-directory: plugins/velocity - name: Upload release workflow artifact if: steps.release.outputs.created == 'true' uses: actions/upload-artifact@v3 with: name: minecraft-account-manager-velocity-${{ steps.release.outputs.version }} path: plugins/velocity/build/libs/minecraft-account-manager-velocity-${{ steps.release.outputs.version }}.jar if-no-files-found: error - name: Install Docker CLI if: steps.release.outputs.created == 'true' run: | if ! command -v docker >/dev/null 2>&1; then apt-get update apt-get install -y ca-certificates curl gnupg install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg chmod a+r /etc/apt/keyrings/docker.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(. /etc/os-release && echo $VERSION_CODENAME) stable" > /etc/apt/sources.list.d/docker.list apt-get update apt-get install -y docker-ce-cli fi - name: Log in to Gitea container registry if: steps.release.outputs.created == 'true' run: echo "${{ secrets.CONTAINER_REGISTRY_TOKEN }}" | docker login git.garvis.dev -u "${{ secrets.REGISTRY_USERNAME }}" --password-stdin - name: Build and push web image if: steps.release.outputs.created == 'true' env: VERSION: ${{ steps.release.outputs.version }} run: | docker build \ --platform linux/amd64 \ --target runner \ --build-arg VERSION="$VERSION" \ -t "git.garvis.dev/dmg/minecraft-account-manager:${VERSION}" \ . docker push "git.garvis.dev/dmg/minecraft-account-manager:${VERSION}" - name: Build and push Discord bot image if: steps.release.outputs.created == 'true' env: VERSION: ${{ steps.release.outputs.version }} run: | docker build \ --platform linux/amd64 \ --target bot \ --build-arg VERSION="$VERSION" \ -t "git.garvis.dev/dmg/minecraft-account-manager-bot:${VERSION}" \ . docker push "git.garvis.dev/dmg/minecraft-account-manager-bot:${VERSION}" - name: Build and push migration image if: steps.release.outputs.created == 'true' env: VERSION: ${{ steps.release.outputs.version }} run: | docker build \ --platform linux/amd64 \ --target migrate \ --build-arg VERSION="$VERSION" \ -t "git.garvis.dev/dmg/minecraft-account-manager-migrate:${VERSION}" \ . docker push "git.garvis.dev/dmg/minecraft-account-manager-migrate:${VERSION}" - name: Create Gitea release and upload Velocity JAR if: steps.release.outputs.created == 'true' env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} GITEA_SERVER_URL: ${{ github.server_url }} REPOSITORY: ${{ github.repository }} TAG: ${{ steps.release.outputs.tag }} VERSION: ${{ steps.release.outputs.version }} PREVIOUS_TAG: ${{ steps.previous_tag.outputs.value }} run: | api_url="${GITEA_SERVER_URL}/api/v1" jar="plugins/velocity/build/libs/minecraft-account-manager-velocity-${VERSION}.jar" export RELEASE_BODY if [ -n "$PREVIOUS_TAG" ]; then RELEASE_BODY=$(git log --pretty='format:- %s (%h)' "${PREVIOUS_TAG}..HEAD") else RELEASE_BODY=$(git log --pretty='format:- %s (%h)' HEAD) fi payload=$(node -e ' const payload = { tag_name: process.env.TAG, name: process.env.TAG, body: process.env.RELEASE_BODY, draft: false, prerelease: false }; process.stdout.write(JSON.stringify(payload)); ') response=$(curl --fail-with-body --silent --show-error \ -X POST \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/json" \ "${api_url}/repos/${REPOSITORY}/releases" \ --data "$payload") release_id=$(printf '%s' "$response" | node -e ' let input = ""; process.stdin.on("data", chunk => input += chunk); process.stdin.on("end", () => { const response = JSON.parse(input); if (!response.id) process.exit(1); process.stdout.write(String(response.id)); }); ') curl --fail-with-body --silent --show-error \ -X POST \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/octet-stream" \ --data-binary "@${jar}" \ "${api_url}/repos/${REPOSITORY}/releases/${release_id}/assets?name=minecraft-account-manager-velocity-${VERSION}.jar"