28 Eylül 2023 Perşembe

Yazılım Mimarisi - Event Driven Architecture (EDA) - Claim Check

Giriş
Açıklaması şöyle
This pattern could be used whenever a message cannot fit the supported message limit of the chosen message bus technology. 
Açıklaması şöyle
For example, a message may contain a set of data items that may be needed later in the message flow, but that are not necessary for all intermediate processing steps. We may not want to carry all this information through each processing step because it may cause performance degradation and makes debugging harder.

Sending such large messages to the message bus directly is not recommended, because they require more resources and bandwidth to be consumed. Also, most messaging platforms have limits on message size, so you may need to work around these limits for large messages.
Çözüm
Açıklaması şöyle. Yani veri tabanı gibi bir yere kaydedip ID değerini gönderiyoruz
Store the entire message payload into an external service, such as a database. Get the reference to the stored payload and send just that reference to the message bus. The reference acts like a claim check used to retrieve a piece of luggage, hence the name of the pattern. Clients interested in processing that specific message can use the obtained reference to retrieve the payload, if needed.
Mesaj işlendikten sonra veri tabanından silinebilir

Mutual TLS - mTLS

Giriş
Açıklaması şöyle
mTLS helps ensure that the traffic is secure and trusted in both directions between a client and server. This provides an additional layer of security for users who log in to an organization’s network or applications. It also verifies connections with client devices that do not follow a login process, such as Internet of Things (IoT) devices.

Nowadays, mTLS is commonly used by microservices or distributed systems in a zero trust security model to verify each other.
Yani TLS client authentication veya istemcinin kendi sertifikasını sunması demek. Açıklaması şöyle. Eskiden genellikle VPN gibi kapalı ağlarda kullanılıyordu.
TLS client authentication (requiring clients to present certs) is something you usually see on VPN servers, enterprise WPA2 WiFi access points, and corporate intranets. These are all closed systems where the sysadmin has full control over issuing certs to users, and they use this to control which users have access to which resources. This makes no sense in a public website setting, and is definitely a non-standard config for an HTTPS webserver.
İstemci Sertifikası Şifreleme İçin Kullanılmaz
Açıklaması şöyle
The certificate of the client is only used to authenticate the client. It is not used in key exchange which happens before the client even sends the certificate and proves ownership of the private key. The client certificates is thus neither directly nor indirectly included in the traffic encryption or MAC

27 Eylül 2023 Çarşamba

Pagination Yöntemleri

1. Offset pagination
Açıklaması şöyle
In this type of pagination, the client sends a request specifying the page number and the number of items per page. Ultimately, this translates into an SQL query using limit and offset.
Örnek
Şöyle bir istek gönderilir
GET /api/v1/bookings?page=1&size=3
2. Token pagination
Açıklaması şöyle
Token pagination can be implemented in different ways. I’ll show you one of them.

In the initial request, we send a typical search query. The response contains the token to retrieve the next portion of data.

In following requests, we send only the next token.

To avoid storing unnecessary states on the backend, we can embed the search query and the ID of the last returned item into a token. We can then compress the data using gzip or snappy and convert it, for instance, to base62.
Örnek
İlk istek ve cevabı şöyledir
/api/v1/logs?categories=bookings,orders&size=100&sort=createdAt:desc

Response
{ 
  data: [...], 
  next: "2H83GdysPu"
}
İkinci istek ve cevabı şöyledir
Request
/api/v1/logs?next=2H83GdysPu

Response
{ 
  data: [...], 
  next: "v95Gdkta3d"
}
Örnek - Token pagination from different sources
Açıklaması şöyle. Yani booking_logs ve  order_logs kayıtlarından kaldığı yerden 3 tane daha alırız ve toplam 6 kayıt göndeririz. Son gönderdiğimiz kayıtların ID'lerini de cevaba ilave ederiz.
Let’s say we have multiple sources: booking_logs and order_logs, and we need to return combined data from both sources.

With token pagination, we can embed the last returned ID from each source into the token. When executing a request for 3 items, we select 3 items from each source, and then sort them on the backend to determine which specific items to return.



14 Eylül 2023 Perşembe

OAuth2 Refresh Token Grant

Giriş
Eğer Expired 401 hatası alıyorsak bu grant tipi ile token'ın yenilenmesi istenir. Açıklaması şöyle.
The authorization server will respond with a JSON object containing the following properties:

- token_type with the value Bearer
- expires_in with an integer representing the TTL of the access token
- access_token the access token itself
- refresh_token a refresh token that can be used to acquire a new access token when the original expires
Şeklen şöyle



OAuth2 Client Credentials Grant - Sunucular Arasında Kullanılır

Giriş
Açıklaması şöyle.
Intended for the server-to-server authentication, this flow describes an approach when the client application acts on its own behalf rather than on behalf of any individual user. In most scenarios, this flow provides the means to allow users to specify their credentials in the client application, so it can access the resources under the client’s control.
Açıklaması şöyle. İnsan müdahalesi olmadan bilgisayarlar arasında kullanılır.
The OAuth 2.0 Client Credentials Grant type is exclusively used for scenarios in which no user exists (CRON jobs, scheduled tasks, other data workloads, etc.).
...
The goal of the Client Credentials Grant is to allow two machines to communicate securely. In this grant type, you have a client (think of this as your application) making API requests to another service (this is your resource server).
Bundan önce Basic Authentication vardı. Açıklaması şöyle.
Before OAuth 2.0, the way developers handled server-to-server authentication was with HTTP Basic Auth. Essentially, this boiled down to a developer that would send over a server’s unique username and password (often referred to as an ID and secret) on each request. The API service would then validate this username and password on every request by connecting to a user store (database, LDAP, etc.) in order to validate the credentials.
Akış şöyle
     +---------+                                  +---------------+
     |         |                                  |               |
     |         |>--(A)- Client Authentication --->| Authorization |
     | Client  |                                  |     Server    |
     |         |<--(B)---- Access Token ---------<|               |
     |         |                                  |               |
     +---------+                                  +---------------+
Örnek
URL'ye şöyle yazarız. Yani Client Credentials gönderiyoruz
localhost:8080/oauth/token?grant_type=client_credentials&scope=any
Diğer parametreleri de eklemek gerekir. Açıklaması şöyle
Please make sure you've added your clientId and client secret in the basic auth header of the authorization tab in postman and you get a successful response like this.
Yani Authorization sekmesinde Basic Auth seçilir. Username Password alanları doldurulur

Cevap olarak şuna benzer bir şey alırız. Yani Access Token alıyruz
{
  "access_token": "qbE0ipKzzX5FNj3OVe8LWu40T_s",
  "token_type": "bearer",
  "expires_in": 43199,
  "scope": "any"
}

OAuth2 Authorization Code Grant

Giriş

Authorization Code Grant ve PKCE
Açıklaması şöyle
PKCE is required for all OAuth clients using the authorization code flow
Verifier ve challenge şöyle. Yani challenge bir hash değeri
verifier = "random string code"
challenge = hash(verifier)
Açıklaması şöyle. Burada işi authorization server yapıyor gibi anlatılıyor
PKCE (pronounced “pixy”) stands for “Proof Key for Code Exchange.” It is a security mechanism that is used to protect authorization code grants when used with OAuth 2.0 and OpenID Connect.

When an application wants to access a user’s resources on a resource server (such as an API), the application must first obtain an authorization code from the authorization server. This authorization code can then be exchanged for an access token, which allows the application to access the user’s resources.

However, this process can be vulnerable to attacks if the authorization code is intercepted by an attacker. PKCE was introduced to protect against this type of attack by requiring the application to include additional information, called a “code verifier,” when requesting the authorization code. The authorization server includes this code verifier when issuing the authorization code, and the application must provide it again when exchanging the authorization code for an access token. This ensures that the application is the one that initiated the request, rather than an attacker who may have intercepted the authorization code.

PKCE is particularly important when an application is using the authorization code grant type in a native application, as it is more vulnerable to code interception attacks.

PKCE will be mandatory with the authorization code flow in OAUTH 2.1
Bir başka açıklaması şöyle. Burada işi client yapıyor gibi anlatılıyor
- When the user is redirected to the login page, the client application generates the verifier and the challenge.

- The challenge is sent to the Authorization Server along with user credentials for authentication request.
After successful authentication and getting the Authorization Code, the client makes the request to get the access token, and instead of sending the client credentials along with the request the client sends the verifier to the Authorization Server.

The Authorization Server that already has the challenge now can validate if the verifier is indeed the same as the challenge by using the hash function matches.
Authorization Code Grant Nedir?
Açıklaması şöyle.
The flow works this way, you visit a third-party site and it redirects you to the authorization server's login page, and you log in there, the authorization server redirects you back to the site issuing the authorization code. The client application then uses the authorization code to get the access token for accessing your protected resources on the resource server.
Akış şöyle
     +--------+                               +---------------+
     |        |--(A)- Authorization Request ->|   Resource    |
     |        |                               |     Owner     |
     |        |<-(B)-- Authorization Grant ---|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |--(C)-- Authorization Grant -->| Authorization |
     | Client |                               |     Server    |
     |        |<-(D)----- Access Token -------|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |--(E)----- Access Token ------>|    Resource   |
     |        |                               |     Server    |
     |        |<-(F)--- Protected Resource ---|               |
     +--------+                               +---------------+
Şeklen şöyle
Bir başka şekil burada.


Authorization Request
Örnek
/oauth/authorize 
   ?client_id=a17c21ed 
   &response_type=code 
   &state=5ca75bd30 
   &redirect_uri=https://example.com/cb 
   &scope=photos
Açıklaması şöyle
Once the authorization server receives the request it should perform the following steps:
1. Verify user identity for example against access token. The request contains users' consent so it must be secured with user identity.

2. Validate request parameters:
  - client_id should be registered to authorization server with exact redirect_uri
  - response_type specifies which OAuth 2.0 flow is requested; for authorization code flow it should be equal to code
  - state contains a random string generated on the client to be verified against the one returned in response; they should be equal
  - scope contains a list of scopes requested by the client

3. Generate authorization code: This should be a random string secure enough to not be guessed.
4. Store in DB request data: The authorization code and user data (probably from token) to use them while token issuance
Authorization Response
Örnek
Şöyledir Burada authorization code cevabını alıyoruz
https://example.com/cb ?state=txcSDMn3Q5bZ-w32 &code=EVOcNHq7TBVaxVw
Açıklaması şöyle
The authorization response is a redirect back to the client to the redirect_uri specified in the authorization request. The code parameter contains the authorization code and the state originally passed by the client.
Açıklaması şöyle
After successful user authentication, the Authorization Server sends the client Authorization Code. The Authorization Code can be used only once by the client to get access token. It doesn’t matter whether the request by the client was successful or not, once the Authorization Code is consumed by the Authorization Server it cannot be used anymore.
Token Exchange Request
Şöyledir. Burada backend de de çalışan uygulamamız authorization code + client credentials gönderiyor
/token ?code=EVOcNHq7TBVaxVw &grant_type=code &redirect_uri=https://example.com/cb &client_id=a17c21ed &client_secret=ZGVmMjMz
Açıklaması şöyle
The /token endpoint receives parameters needed to issue access token:
code contains authorization code generated as a result of authorization request; it's a key by which authorization server should look for data in DB.
grant_type specifies which way the server should issue access tokens; code means the token should be issued based on the authorization code.
client_id and client_secret (or code_verifier in case of using PKCE) are needed to authorize the request since just authorization code validation is not enough because it might be intercepted.
- Get data from DB by the authorization code, the most important of which are user id and scopes requested. Therefore, the access token issued should represent the users and should be limited to scopes they confirmed giving consent.
- Issue tokens (most probably your would like to issue refresh token alongside with access one)
Token Exchange Response 
Şöyledir. Burada access token alıyoruz
{ "token_type": "Bearer", "expires_in": 86400, "access_token": "sjmHG1EywNbSDAelt", "refresh_token": "Qb6kKM4BWPIwq" }
Delegated Authorization vs Federated Authentication
Authorization Code Grant akışına "Delegated Authorization" denilir. Çünkü sadece bir kaynağa (resource) belli bir erişim hakkı veriyoruz. "OpenID Connect" ile ayrıldıkları nokta burası, çünkü "OpenID Connect"  "Delegated Authorization" yerine "Federated Authentication" kullanıyor. Açıklaması şöyle. Yani authorization (yetkilendirme) yerine, authentication (doğrulama) yapılıyor
Note that Federated Authentication is different from Delegated Authorization.

Federated Authentication allows you to login to a site using your facebook or google account.

Delegated Authorization is the ability of an external app to access resources. This use case would be for example Spotify trying to access your google contacts list to import it into Spotify.

OAuth 2.0 was designed primarily for delegated authorization, OpenId Connect is the few additional steps added over OAuth 2.0 to extend OAuth 2.0 for Federated Authentication.
Fark aslında çok basit bir şeyden kaynaklanıyor. Open ID access token'a ilave olarak bir de id_token kullanıyor. Açıklaması şöyle
1. it introduces a completely new token (id_token) with radically different semantics than the OAuth 2.0 access_token and a standardized format that is understood by the Client as opposed to the access_token which is opaque to the Client

2. it "twists" the role of the Client, now becoming the "audience" (or: intended recipient) of a token (i.e. the id_token) whilst the audience of the access_token is still a remote entity (aka. Resource Server) and the Client is only the "presenter" of the latter

The 2nd item is the primary source of confusion between OAuth 2.0 and OpenID Connect.

13 Eylül 2023 Çarşamba

Redis Hash Veri Yapısı

Giriş
Açıklaması şöyle
Redis Hashes offer built-in functionality for sorting and searching data, making it easy to find specific data points or organize data based on certain criteria.

Redis Hashes offers transaction support, allowing you to perform multiple operations on data in a single transaction, ensuring consistency and reducing the risk of data corruption.

Redis Hashes are highly reliable, with built-in data replication and backup features to ensure that your data is always available and recoverable in the event of a failure.

Redis Hashes offer built-in security features, including support for SSL/TLS encryption and password authentication, making it a secure solution for applications that handle sensitive data.
1. HSET
Açıklaması şöyle
The HSET command sets the value of a field in a hash. If the field does not exist, it creates a new field and sets its value. If the field already exists, it overwrites its value.
Örnek
Şöyle yaparız. This command sets the name of user1 to “John”.      
HSET user1 name "John"
2. HGET
Açıklaması şöyle
The HGET command gets the value of a field in a hash. If the field exists, it returns its value. If the field does not exist, it returns nil.
Örnek
Şöyle yaparız. This command gets the name of user1.
HGET user1 name
3. HMSET
Açıklaması şöyle
The HMSET command sets multiple fields in a hash.
Örnek
Şöyle yaparız. This command sets the name, email, and age of user1.
HMSET user1 name "John" email "john@example.com" age 30
4. HMGET
Açıklaması şöyle
The HMGET command gets the values of multiple fields in a hash.
Örnek
Şöyle yaparız. This command gets the name, email, and age of user1.
HMGET user1 name email age
5. HDEL
Açıklaması şöyle
The HDEL command deletes one or more fields in a hash.
Örnek
Şöyle yaparız. This command deletes the age field of user1.
HDEL user1 age
6. HEXISTS
Açıklaması şöyle
The HEXISTS command checks if a field exists in a hash.
Örnek
Şöyle yaparız. This command checks if the name field exists in user1.
HEXISTS user1 name
7. HKEYS
Açıklaması şöyle
The HKEYS command gets all the keys in a hash.
Örnek
Şöyle yaparız. This command gets all the keys in user1.
HKEYS user1
8. HVALS
Açıklaması şöyle
The HVALS command gets all the values in a hash.
Örnek
Şöyle yaparız. This command gets all the values in user1.
HVALS user1
9. HLEN
Açıklaması şöyle
The HLEN command gets the number of fields in a hash.
Örnek
Şöyle yaparız. This command gets the number of fields in user1.
HLEN user1
10. HINCRBY
Açıklaması şöyle
The HINCRBY command increments the value of a field in a hash by a specified amount.
Örnek
Şöyle yaparız. This command increments the age of the user1 by 5.
HINCRBY user1 age 5
11. HINCRBYFLOAT
Açıklaması şöyle
This command increments the value of a floating-point field in a hash by a specified amount.
Örnek
Şöyle yaparız. This command increments the weight of user1 by 2.5
HINCRBYFLOAT user1 weight 2.5
Örnek
Şöyle yaparız
// create a Redis Hash named “customer1” using the HMSET
HMSET customer1 name "John Doe" email "johndoe@example.com" address "123 Main St"
  phone "555-1234" orders "5"

// use the HGET command to get the name and email of the customer
HGET customer1 name
//Output: “John Doe”

HGET customer1 email
// Output: “johndoe@example.com”

// use the HSET command to update the phone number of the customer
HSET customer1 phone "555-5678"

// use the HINCRBY command to increment the order count for the customer
HINCRBY customer1 orders 1

// se the HMGET command to get the customer’s address and order history
HMGET customer1 address orders
// Output: [“123 Main St”, “6”] 

// use the HDEL command to delete the customer’s phone number
HDEL customer1 phone

// use the HEXISTS command to check if a field exists in the customer1 hash
HEXISTS customer1 email
// Output: 1 (true)

HEXISTS customer1 phone
// Output: 0 (false)



Engineering Manager

Engineering Manager Ne İş Yapar?
Açıklaması şöyle. Yani bazı şeylerin otomasyona geçmesi için çaba sarf eder
... as an engineering manager (EM) on the Interfaces team in October 2022, I was focused on organizing the work in our Jira board and setting up automation to streamline the software development lifecycle.
Teknik Lider vs Engineering Manager
Şeklen şöyle

Açıklaması şöyle
- The manager should delegate the team technical leadership to the technical lead and get out of the weeds. Managers should not fall off the bus and forget decades of technical background. However, managing is fundamentally a policy job, and managers should respect boundaries. Anything else is micromanaging and breaking trust.
- The technical lead should delegate the career, team growth, communications, and coordination work to the engineering manager and focus on architecture, technical choices, technical direction, and helping to drive execution.

11 Eylül 2023 Pazartesi

SSTable - Sorted String Table

Giriş
Açıklaması şöyle
- SSTable (Sorted String Table) is a file format used in various storage systems, particularly in LSM (Log-Structured Merge) trees, for storing and accessing sorted key-value pairs on disk.
- SSTables are designed for efficient read operations, especially range queries, and are commonly used in systems that require high-performance data retrieval.
immutable on-disk “Map” implementation
SSTable Bileşenleri Nelerdir?
Açıklaması şöyle
A Sorted String Table consists of two main files, one with actual data and another with an index to speed up look-ups.

LSM-Tree veya Log-Structured Merge Tree

LSM Tree Ne İçindir?
LSM-Tree hızlı yazma içindir. Açıklaması şöyle
- LSM (Log-Structured Merge) tree is a data structure designed for efficient write-intensive workloads, commonly used in storage systems and database engines.
- It offers high write throughput and efficient disk space utilization by leveraging sequential write operations and periodic merging of data.
LSM Tree Bileşenleri
Açıklaması şöyle
We can distinguish two key components of the tree, the in-memory buffer, also called Memtable, and the disk-resident tables. The main idea is to accept writes to the in-memory part of the tree, and to flush them periodically, or when a certain size is met.

A key aspect of this structure is ordering, indeed, keys are sorted both in RAM and on disk, enabling logarithmic searches.
Yani LSM Tree iki kısımdan oluşur
1. Memtable
2. Disk Resident Tables

1. Memtable
Sıralı yani sorted olması gerekir.  Red-Black Tree , AVL Tree Skip List gibi bir veri yapısı kullanılabilir

2. Disk Resident Tables
 SSTable - Sorted String Table  veri yapısı kullanılır

3. Yani
Skiplist + SSTable  kullanılabilir. 
 Skip List + SSTable kullanılabilir

Compaction
Açıklaması şöyle
Level 0 segments are periodically merged into Level 1 segments. This process is called compaction
B-Tree vs LSM-Tree
Açıklaması şöyle
The biggest difference is probably this:
  -B-Tree enables faster reads
 - LSM-Tree enables fast writes

6 Eylül 2023 Çarşamba

GitHub Actions Workflow

Örnek
Bir repository yaratırız ve .github/workflows/create-spring-boot-repository.yaml  dosyasını yaratırız. Dosya şöyle. Dosyanın çalışması için bir personal access token yaratılır ve secret olarak kaydedilir
name: Create Spring Boot Repository

on:
  workflow_dispatch:
    inputs:
      name:
        description: 'Repository Name'
        required: true
      description:
        description: 'Repository Description'
        required: true
      private:
        description: 'Private Repository'
        required: true
        default: 'false'
      groupId:
        description: 'Maven Group ID'
        required: true
      artifactId:
        description: 'Maven Artifact ID'
        required: true
      springBootVersion:
        description: 'Spring Boot Version'
        required: true
        default: '3.0.0'
      mainClassName:
        description: 'Main Class Name'
        required: true
        default: 'Application'
      userName:
        description: 'User Name'
        required: true
      userEmail:
        description: 'User Email'
        required: true
        
jobs:
  create-spring-boot-repository:
    runs-on: ubuntu-latest

    steps:
    - name: Step 1 - Checkout code
      uses: actions/checkout@v3

    - name:  Step 2 - Generate Spring Boot Project with Maven Wrapper
      run: |
        curl https://start.spring.io/starter.zip -o project.zip \
             -d type=maven-project \
             -d bootVersion=${{ github.event.inputs.springBootVersion }} \
             -d groupId=${{ github.event.inputs.groupId }} \
             -d artifactId=${{ github.event.inputs.artifactId }} \
             -d name=${{ github.event.inputs.mainClassName }}
        unzip project.zip -d spring-boot-project
        cd spring-boot-project
        mvn wrapper:wrapper

    - name: Step 3 - Create new GitHub repository
      run: |
        curl -X POST -H "Authorization: token ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}" \
             -d '{
                  "name": "${{ github.event.inputs.name }}",
                  "description": "${{ github.event.inputs.description }}",
                  "private": ${{ github.event.inputs.private }}
                }' \
             https://api.github.com/user/repos

    - name: Step 4 - Push to new repository
      run: |
        cd spring-boot-project
        echo "# ${{  github.event.inputs.name }}" >> README.md
        git config --global user.email "${{ github.event.inputs.userEmail }}"
        git config --global user.name "${{ github.event.inputs.userName }}"
        git init
        git add .
        git add README.md
        git commit -m "first commit"
        git branch -M main
        git remote add origin git@github.com:${{ github.actor }}/${{ github.event.inputs.name }}.git
        git remote set-url origin https://x-access-token:${{ env.GH_PERSONAL_ACCESS_TOKEN }}@github.com/${{ github.actor }}/${{ github.event.inputs.name }}
        git push -u origin main  # Push to 'main' branch
      env:
        GH_PERSONAL_ACCESS_TOKEN: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}

Github Actions - maven

Örnek - checkout + Set up JDK + Build
GitHub'daki repository'ye gidilir. Üst başlıktaki "Actions" düğmesine tıklanır. "New workflow" düğmesine tıklanır. "Java with Maven" düğmesine tıklanır. Şeklen şöyle

Karşımıza çıkan dosya şöyle. Dosya yolu şöyle "myrepository/.github/workflows/maven.yaml"
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/ building-and-testing-java-with-maven

name: Java CI with Maven

on:
  push:
    branches: [ "master" ]
  pull_request:
    branches: [ "master" ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Set up JDK 11
      uses: actions/setup-java@v3
      with:
        java-version: '11'
        distribution: 'temurin'
        cache: maven
    - name: Build with Maven
      run: mvn -B package --file pom.xml
Örnek - checkout + Set up JDK + Build
Şöyle yaparız
name: Java CI with Maven

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v2

    - name: Set up JDK 11
      uses: actions/setup-java@v2
      with:
        java-version: '11'
        distribution: 'adopt'

    - name: Build with Maven
      run: ./mvnw clean install

Örnek
Push işleminden sonra testleri çalıştırıp, Docker'a image push'lamak için şöyle yaparız
name: CI/CD Pipeline

## The following codes trigger the pipeline when the code is pushed on the main branch.
on:
  push:
    branches: [ main ]

jobs:
  ## First Job: Test
  test:
    name: Unit Test
    ## Run on Ubuntu using the Latest Version
    runs-on: ubuntu-latest
    ## Job's steps
    steps:
      - uses: actions/checkout@v1
      ## Set up JDK 11
      - name: Set up JDK
        uses: actions/setup-java@v1
        with:
          java-version: '11'
      ## Set up Maven Cache
      - name: Cache Maven packages
        uses: actions/cache@v1
        with:
          path: ~/.m2
          key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
          restore-keys: ${{ runner.os }}-m2
      ## Run Maven Tests
      - name: Run Tests
        run: mvn -B test

  ## Second Job: Build and Push
  build-and-push:
    name: Build and Push
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up JDK 11
        uses: actions/setup-java@v3
        with:
          java-version: '11'
          distribution: 'adopt'
          cache: maven
      - name: Build with Maven
        run: mvn -B package --file pom.xml

      - name: Dockerize & Push Docker Image
        uses: mr-smithers-excellent/docker-build-push@v5
        with:
          ## Docker Hub Account Number / Repository Name
          image: 19812381238/product-microservice
          tags: latest
          registry: docker.io
          ## Dockerfile Path
          dockerfile: product/Dockerfile
          ## Keep these secrets on GitHub for the privacy of our information
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
Örnek
Github sayfasına release yapmak için şöyle yaparız
name: Java CI to create and upload release on pull request
on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

env:
  build-number: ${GITHUB_RUN_NUMBER}

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-java@v3
        with:
          java-version: '11'
          distribution: 'temurin'
          cache: 'maven'
      - run: mvn clean package -DskipTests
      - run: mkdir staging && mv target/yb-workload-sim.jar target/yb-workload-sim-${{ env.build-number }}.jar && cp target/*.jar staging
      - uses: actions/upload-artifact@v3
        with:
          name: Package
          path: staging
          retention-days: 1
      - uses: marvinpinto/action-automatic-releases@latest
        with:
          repo_token: "${{ secrets.YOUR-GITHUB-TOKEN }}"
          automatic_release_tag: "${{ github.run_number }}"
          title: "Automated Build ${{ github.run_number }}"
          prerelease: true
          files: staging/*.jar

3 Eylül 2023 Pazar

Aikido Ai Hanmi Katete Dori - Tek El İle Bilekten Tutuş

Mikyo
Nikyo ile Aikido Ai Hanmi Katete Dori'den kurtulmak mümkün. Bir video burada
KotaGaeshi ile de mümkün. Yine aynı videoda bu da göstereliyor

2 Eylül 2023 Cumartesi

Aikido Uke Nagashi - Flowing reception

Giriş
Uke nagashi Iaydo kılış sanatında da var. Akıp gitmek demek. Wing chun'da bong sao'ya benziyor.

Kokyu Nage
Uke Nagashi'den kokyu nage'ye geçişi gösteren bir video burada.

Aikido - Kagi Zuki - Çengel Yumruk - Hook Punch Savunma

1. Rakipte Silah Varsa
Silah bir sopa veya bıçak olabilir. Sopa ve bıçak durumu değiştiriyor.

Sopa Varsa, Tek Elle Tutulmuşsa ve Yokomen Uchi Şeklinde Geliyorsa 
En iyisi içeriye doğru girmek. Sopayı savuran ele doğru hamle yapılır
Yana doğru adım atıp kaçmak çok faydalı değil. 
Geriye veya bir şekilde dışarıya çıkmak ta uygun olur

Sopa Varsa, Çift Elle Tutulmuşsa ve Yokomen Uchi Şeklinde Geliyorsa 
Eğer içeri girecekse rakip tam yan dönmüşken yani daha hızını almamışken hamle yapılır. Bir video burada

2. Rakipte Silah Yoksa

2.1 İleri ve Bazen Biraz Yana Doğru Yapılan Hamleler

Rakibin Bileğine Doğru
Bileğe yakın yapılan hamle ile benim karşı yumruk vurmam daha kolay. 

Burada Aikido ve Wing Chun bu hamleye biraz farklı yaklaşıyor.

Aikido 45 derece vücudu döndürerek direkt rakibin dirseğini durduruyor.
Wing Chun ise ileri doğru elleri uzatıp daha sonra yarı yolda örneğin sol eli çiçeğin açılması gibi açıyor. 

Bir video burada. 2. dakika civarında gösteriyor.

Rakibin Dirseğine Doğru
Engelleme rakibin dirseğinin içine doğru hamle yaparak durdurmak şeklinde. Ancak durumda rakibe çok fazla yaklaşmış oluyorum. 

Rakibin Dirseğine Doğru - Randori kokyu nage
Bir video burada

Rakibin Dirseğine Doğru - Upper Cut
Wing Chun tekniği, ama mantık aynı. Rakibin dirseğinin içine doğru hamle yaparken karşı yumruk için upper cut kullanmak daha iyi. Çünkü rakibe çok yaklaştığım için direkt vuruşa yeterli yer yok.
Bir video burada

2.2 Geriye ve Bazen Biraz Yana Doğru Yapılan Hamleler
Wing chundaki tan sao gibi karşılayıp geriye ve yana doğru dönmek şeklinde.