This commit is contained in:
@@ -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
|
||||||
@@ -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
|
||||||
@@ -1,30 +1,110 @@
|
|||||||
|
|
||||||
# j3270
|
# j3270
|
||||||
|
|
||||||
An x3270 based emulator ported to Java using AI
|
[](https://git.hugfreevikings.wtf/rudi/j3270/actions)
|
||||||
|
[](https://git.hugfreevikings.wtf/rudi/j3270/releases)
|
||||||
|
[](https://adoptium.net)
|
||||||
|
[](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
|
```bash
|
||||||
|
# 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
|
./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
|
```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)
|
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)
|
- [Antigravity](https://antigravity.google)
|
||||||
- Claude Opus 4.6
|
- Claude Opus 4.6
|
||||||
- Gemini 3.1 Pro (High)
|
- Gemini 3.1 Pro
|
||||||
|
|||||||
Reference in New Issue
Block a user