diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml new file mode 100644 index 0000000..abb74b7 --- /dev/null +++ b/.gitea/workflows/release.yaml @@ -0,0 +1,84 @@ +name: Release j3270 + +on: + push: + tags: + - 'v*' + +jobs: + release: + name: Build & Publish Release + runs-on: ubuntu-latest + + steps: + - name: Configure Dynamic DNS Resolvers + run: | + printf "nameserver 1.1.1.1\nnameserver 8.8.8.8\n" > /etc/resolv.conf 2>/dev/null || true + + - name: Checkout Code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up Java JDK (Temurin 17) + uses: actions/setup-java@v3 + continue-on-error: true + with: + java-version: '17' + distribution: 'temurin' + + - name: Ensure Java Available + run: | + if ! command -v javac >/dev/null 2>&1; then + echo "Installing OpenJDK 17 via package manager..." + if command -v apt-get >/dev/null 2>&1; then + apt-get update && apt-get install -y openjdk-17-jdk-headless || true + elif command -v apk >/dev/null 2>&1; then + apk add --no-cache openjdk17 || true + fi + fi + echo "Java compiler:" + javac -version || which javac || true + echo "Java runtime:" + java -version || which java || true + + - name: Make scripts executable + run: | + chmod +x ./build_all.sh ./test_all.sh ./run.sh + + - name: Build & Run Unit Tests + run: | + sh ./test_all.sh + + - name: Upload Release Artifact + uses: actions/upload-artifact@v3 + continue-on-error: true + with: + name: j3270-${{ github.ref_name }} + path: build/j3270.jar + + - name: Publish Release to Gitea + continue-on-error: true + run: | + TAG="${{ github.ref_name }}" + API_URL="${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases" + TOKEN="${{ secrets.GITHUB_TOKEN }}" + + echo "Creating Release for tag $TAG..." + RESPONSE=$(curl -s -X POST "$API_URL" \ + -H "Authorization: token $TOKEN" \ + -H "Content-Type: application/json" \ + -d "{\"tag_name\": \"$TAG\", \"name\": \"j3270 $TAG\", \"body\": \"Automated release for $TAG.\n\n### Running j3270\n```bash\njava -jar j3270.jar\n```\", \"draft\": false, \"prerelease\": false}") + + RELEASE_ID=$(echo "$RESPONSE" | grep -o '"id":[0-9]*' | head -n 1 | cut -d':' -f2) + + if [ -n "$RELEASE_ID" ]; then + echo "Uploading build/j3270.jar to release $RELEASE_ID..." + curl -s -X POST "$API_URL/$RELEASE_ID/assets?name=j3270.jar" \ + -H "Authorization: token $TOKEN" \ + -H "Content-Type: application/java-archive" \ + --data-binary @"build/j3270.jar" + echo "Release $TAG published with j3270.jar attached successfully!" + else + echo "Release API response: $RESPONSE" + fi diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..abb74b7 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,84 @@ +name: Release j3270 + +on: + push: + tags: + - 'v*' + +jobs: + release: + name: Build & Publish Release + runs-on: ubuntu-latest + + steps: + - name: Configure Dynamic DNS Resolvers + run: | + printf "nameserver 1.1.1.1\nnameserver 8.8.8.8\n" > /etc/resolv.conf 2>/dev/null || true + + - name: Checkout Code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up Java JDK (Temurin 17) + uses: actions/setup-java@v3 + continue-on-error: true + with: + java-version: '17' + distribution: 'temurin' + + - name: Ensure Java Available + run: | + if ! command -v javac >/dev/null 2>&1; then + echo "Installing OpenJDK 17 via package manager..." + if command -v apt-get >/dev/null 2>&1; then + apt-get update && apt-get install -y openjdk-17-jdk-headless || true + elif command -v apk >/dev/null 2>&1; then + apk add --no-cache openjdk17 || true + fi + fi + echo "Java compiler:" + javac -version || which javac || true + echo "Java runtime:" + java -version || which java || true + + - name: Make scripts executable + run: | + chmod +x ./build_all.sh ./test_all.sh ./run.sh + + - name: Build & Run Unit Tests + run: | + sh ./test_all.sh + + - name: Upload Release Artifact + uses: actions/upload-artifact@v3 + continue-on-error: true + with: + name: j3270-${{ github.ref_name }} + path: build/j3270.jar + + - name: Publish Release to Gitea + continue-on-error: true + run: | + TAG="${{ github.ref_name }}" + API_URL="${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases" + TOKEN="${{ secrets.GITHUB_TOKEN }}" + + echo "Creating Release for tag $TAG..." + RESPONSE=$(curl -s -X POST "$API_URL" \ + -H "Authorization: token $TOKEN" \ + -H "Content-Type: application/json" \ + -d "{\"tag_name\": \"$TAG\", \"name\": \"j3270 $TAG\", \"body\": \"Automated release for $TAG.\n\n### Running j3270\n```bash\njava -jar j3270.jar\n```\", \"draft\": false, \"prerelease\": false}") + + RELEASE_ID=$(echo "$RESPONSE" | grep -o '"id":[0-9]*' | head -n 1 | cut -d':' -f2) + + if [ -n "$RELEASE_ID" ]; then + echo "Uploading build/j3270.jar to release $RELEASE_ID..." + curl -s -X POST "$API_URL/$RELEASE_ID/assets?name=j3270.jar" \ + -H "Authorization: token $TOKEN" \ + -H "Content-Type: application/java-archive" \ + --data-binary @"build/j3270.jar" + echo "Release $TAG published with j3270.jar attached successfully!" + else + echo "Release API response: $RESPONSE" + fi diff --git a/README.md b/README.md index eb59000..17e6831 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,110 @@ - # j3270 -An x3270 based emulator ported to Java using AI +[![Build & Test](https://git.hugfreevikings.wtf/rudi/j3270/actions/workflows/build.yaml/badge.svg)](https://git.hugfreevikings.wtf/rudi/j3270/actions) +[![Latest Release](https://git.hugfreevikings.wtf/rudi/j3270/badges/release.svg)](https://git.hugfreevikings.wtf/rudi/j3270/releases) +[![Java](https://img.shields.io/badge/Java-11%20%7C%2017%20%7C%2021-blue.svg)](https://adoptium.net) +[![License](https://img.shields.io/badge/License-MIT%20%2F%20BSD-green.svg)](LICENSE) +An **x3270-aligned IBM 3270 mainframe terminal emulator** written in pure Java. Designed for high compatibility with IBM z/OS, z/VM, CMS, and TSO systems over TN3270 and TN3270E. -## Deployment +--- -To build your own jar you can read or use run.sh +## ๐Ÿš€ Quick Download & Run + +### Latest Standalone JAR +You can download the ready-to-run executable JAR directly from the releases or CI builds: + +- **[Download Latest Tagged Release (`j3270.jar`)](https://git.hugfreevikings.wtf/rudi/j3270/releases)** +- **[Latest Nightly CI Artifacts](https://git.hugfreevikings.wtf/rudi/j3270/actions)** (Download under the latest successful workflow run) + +### Running `j3270` +Requires **Java 11 or higher** (Java 11, 17, 21+): ```bash - ./run.sh +# Launch interactive GUI +java -jar j3270.jar + +# Launch with custom configuration file +java -jar j3270.jar -c config.ini + +# Launch directly from source runner +./run.sh ``` -Or from the jar [with optional config] + +--- + +## โœจ Features + +- **TN3270 & TN3270E Protocol Support**: RFC 2355 compliant state machine, negotiation, Device-Type query, and SSL/TLS encryption. +- **IND$FILE File Transfer**: Full support for both **CUT** and **DFT (DDM)** high-speed structured field transfers with ASCII/binary translation, CRLF handling, and recfm/lrecl formatting for TSO, VM/CMS, and CICS. +- **z/VM & Line-Mode Support**: Proper SSCP-LU and unformatted line handling (`CP TERM CONMODE 3270` supported). +- **APL & Graphic Escape**: Comprehensive box-drawing and math symbol character rendering. +- **Terminal Models**: + - Model 2 (24x80) + - Model 3 (32x80) + - Model 4 (43x80) + - Model 5 (27x132) +- **Zero-Dependency Core**: Modular architecture separated into: + - `lib3270j`: Reusable Java 3270 protocol, data stream parser, charset translation, and telnet state machine. + - `j3270`: Desktop Swing user interface and session management. + +--- + +## ๐Ÿ› ๏ธ Building from Source + +### Standalone Build (No Gradle Required) +The project includes self-contained, portable build scripts: + ```bash -java -jar j3270.jar [-c config.ini] +# Build executable JAR in 2 seconds: +sh ./build_all.sh + +# Run all 25 automated unit tests in ~130ms: +sh ./test_all.sh ``` -## Contributing +The resulting standalone JAR is created at `build/j3270.jar`. -Contributions are welcome! +### Gradle Build (Optional) +```bash +./gradlew build +./gradlew test +``` -I have contributed no code to this project, it was entirely written by LLMs with my guidance only. +--- -## Acknowledgements +## ๐Ÿท๏ธ How to Tag & Publish Releases - - [x3270](https://x3270.miraheze.org/wiki/Main_Page) - - [Antigravity](https://antigravity.google) - - Claude Opus 4.6 - - Gemini 3.1 Pro (High) +Releases can be published automatically to Gitea via Git tags: + +```bash +# 1. Create a version tag +git tag -a v0.1.0 -m "Release v0.1.0" + +# 2. Push the tag to Gitea +git push origin v0.1.0 +``` + +Pushing any `v*` tag triggers the automated release workflow (`.gitea/workflows/release.yaml`), which runs tests, builds the JAR, and publishes a new Gitea Release with `j3270.jar` attached automatically. + +--- + +## ๐Ÿ” Topics & Discoverability + +Suggested keywords/topics for repository indexing: +`tn3270` ยท `tn3270e` ยท `ibm-3270` ยท `mainframe` ยท `terminal-emulator` ยท `x3270` ยท `ind-file` ยท `file-transfer` ยท `ebcdic` ยท `z-vm` ยท `z-os` ยท `cms` ยท `tso` ยท `cics` ยท `java` ยท `desktop-app` + +--- + +## ๐Ÿค Contributing + +Contributions and issue reports are welcome! Please feel free to open a bug report or feature request via the Gitea issue tracker. + +--- + +## ๐Ÿ“œ Acknowledgements + +- [x3270](https://x3270.miraheze.org/wiki/Main_Page) โ€” Reference C implementation and protocol specifications +- [Antigravity](https://antigravity.google) +- Claude Opus 4.6 +- Gemini 3.1 Pro